首页 > 解决方案 > 为什么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 一行。现在一切正常!
不仅如此 - 我删除了所有用于测试的信号量(我写了所有可重入的东西,但添加了假设错误的信号量)!仍然一切都很好!

标签: multithreadinglinux-device-driver

解决方案


多亏了 Ian Abbot,问题才得以解决。
我的驱动程序需要一个大内存区域进行控制,每个通道缓冲区需要一个大区域。为此,在第一次open()调用之后,我调用mmap()了控制区域所有对open()mmapped() 的连续调用,只有它们对应的缓冲区。这有效地导致第一个文件处理程序的引用计数器设置为 2。当我尝试“正常”关闭它时,我的驱动程序release函数没有被调用!而且,由于它没有被调用,它没有清理驱动程序状态并阻止进一步重新打开。

我错过/不知道的事情总结:

  1. mmap系统调用增加了文件的引用调用。
  2. mmap系统调用是每个文件而不是每个驱动程序。

再次感谢 Ian Abbot!


推荐阅读