multithreading - 为什么linux省略驱动关闭功能
问题描述
全部。
我有我的模块 - 几个 DMA 通道的字符驱动程序。它为每个 DMA 的用户提供打开/关闭/ioctl 功能。
从一个应用程序线程使用时一切正常 - 3 个 DMA 按要求工作。
当我添加另一个线程以分别使用其中一个 DMA 时,我陷入了非常奇怪的情况 - 对函数 close() 的应用程序调用执行时返回代码为零,而没有(!)进入我的驱动程序的关闭函数(printk 文本不存在)。只是为了测试,我立即再次调用 close() - 它返回 errno=9(错误的描述符)。在下一个代码行中关闭下一个通道可以正常工作。
我插入了所有可能的信号量来保护应用程序和驱动程序中的代码 - 没有成功。我清楚地知道问题出在某些赛车状态 - 稍微延迟第二个线程可以解决问题。但我无法抓住它。
什么,让我抓狂的是 - 函数调用 close() 怎么可能没有到达我的驱动程序?我跟踪调用直到汇编程序“svc 0”——文件处理程序是正确的,返回码是 0。
那么,在什么情况下 Linux 可以省略调用驱动程序函数 close()?
更新:我在“不工作” close() 之后立即插入了对 IOCTL 函数的调用 - 返回码是 -9 - 错误的文件描述符。这意味着 Linux 真的在没有进入我的“关闭”函数的情况下关闭了这个处理程序!
UPDATE2:我在驱动程序中添加了一个新的IOCTL,它只直接调用close()驱动程序函数。在应用程序中:我在调用 close() 之前只调用了这个新的 IOCTL 一行。现在一切正常!
不仅如此 - 我删除了所有用于测试的信号量(我写了所有可重入的东西,但添加了假设错误的信号量)!仍然一切都很好!
解决方案
多亏了 Ian Abbot,问题才得以解决。
我的驱动程序需要一个大内存区域进行控制,每个通道缓冲区需要一个大区域。为此,在第一次open()
调用之后,我调用mmap()
了控制区域所有对open()
mmapped() 的连续调用,只有它们对应的缓冲区。这有效地导致第一个文件处理程序的引用计数器设置为 2。当我尝试“正常”关闭它时,我的驱动程序release
函数没有被调用!而且,由于它没有被调用,它没有清理驱动程序状态并阻止进一步重新打开。
我错过/不知道的事情总结:
mmap
系统调用增加了文件的引用调用。mmap
系统调用是每个文件而不是每个驱动程序。
再次感谢 Ian Abbot!
推荐阅读
- asp.net - Angular 与 Asp.net Core Jwt 令牌实现
- http - 如何为 prometheus scrape_configs 作业配置环境变量或 http_proxy?
- javascript - 如何禁用踢出具有更高角色的成员?
- python - 应用statistics.median(Python)时排序列表为空
- java - 如何在 file.properties 文件中创建全局变量以在文件中使用
- linux - 使用 ansible 应用数据库迁移
- java - 使用 ArrayList Java 不重复并使用输入缩短数组
- php - Laravel 连接仅在所有连接的表都包含值时出现
- java - 有没有办法(以某种方式)在 Java Swing 中实现两个计时器,其中每个计时器用于同时运行的每个移动对象?
- r - 是否有 R 函数检查前几行的日期?