我正在为连接到带有慢速 ARM SoC 的开发板的自定义实验室硬件编写 Linux 字符驱动程序,但在尝试实现从内核空间到用户空间的合适通知系统时遇到了困难。
基本上,我定期(每 10 毫秒)从 HW 读取数据,通过运行在内核空间中的一些过滤器处理这些数据(这部分没问题),并在满足某些条件时通知用户空间。我的方法是让用户空间守护进程使用 poll()
系统调用等待来自驱动程序的通知(很自然,因为我也在监视那里的网络套接字)。
在驱动程序初始化时,我创建了一个计时器(使用
setup_timer
),它将调用负责读取硬件的函数,设置用于此的 GPIO,并创建一个等待队列(使用init_waitqueue_head
) 从计时器处理程序向struct file_operations
中的.poll
处理程序发出信号。这部分看起来还可以。有一个
.unlocked_ioctl
处理程序来设置和获取条件,但这部分正在工作。我的
.read
方法来自struct file_operations
只是将一个带有状态的字节放入用户空间;它永远不会阻塞,因为总有一个有效的(包括“W”表示“等待来自传感器的更多数据”)。打开设备后,我会启用计时器。它的处理函数在 10 毫秒后被调用,从 HW 读取数据,运行过滤器,并设置定时器再次运行(使用
mod_timer
);如果过滤后的数据符合我的条件,它会更改状态,将标志poll_evt_waiting
设置为 1 并在与.poll
共享的队列上调用wake_up_interruptible
>来自struct file_operations
的方法。这个方法只是:static unsigned int firflt_file_poll(struct file *filp, poll_table *wait) { unsigned int mask = 0; poll_wait(filp, &firflt_queue, wait); if (poll_evt_waiting != 0) { mask = POLLIN | POLLRDNORM; poll_evt_waiting = 0; } return mask; }
问题是:我的用户空间守护进程中的poll()
从未收到来自驱动程序的通知!我的方法有什么明显的错误吗?特别是关于等待队列?我以前从未实现过 poll() 的“另一面”,并从 2005 年版的“Linux 设备驱动程序”中获得了所有相关信息。
如果连续读取设备文件描述符,我可以从用户空间看到状态变化,但这会使我的守护进程处于繁忙循环中,这对慢速 CPU 来说太过分了。我真的需要让它在民意调查中等待,直到有新的东西出现。
此外,我对等待队列所做的唯一操作是使用 init_waitqueue_head
对其进行初始化,在状态更改时使用 poll_evt_waiting
将其唤醒,并将其传递给 poll_wait
在我的 .poll
处理程序中。这种方法合理吗?
最佳答案
在轮询队列上调用wake_up_interruptible()
只是强制.poll
方法再次被调用。用户空间进程仅当 .poll
方法返回已设置轮询位的掩码时接收通知。
检查您的 .poll
方法是否实际返回非零掩码。
关于linux - 通过等待队列从计时器处理程序发出轮询/选择事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38492237/