linux - 通过等待队列从计时器处理程序发出轮询/选择事件

标签 linux select linux-kernel linux-device-driver kernel-module

我正在为连接到带有慢速 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/

相关文章:

linux - 为什么即使我使用了 signl(SIGINT, sig_int) 它也会终止?

c++ - GDB "cannot open shared object file"问题

c - 内核模块编程(中断处理程序)

assembly - 为什么linux在entry_SYSCALL_64函数中从rcx寄存器读取ip寄存器?

c - rt linux中如何从用户程序访问内核内存?

linux - 有没有办法在不中断输出的情况下从管道尾部命令每分钟打印一次时间?

linux - 空输入字符垃圾邮件 Linux tty

php - 带 WHERE 子句的 Mysql SELECT 不适用于变量

select - Go Golang select 语句无法接收发送的值

mysql - 连接来自不同脚本 MYSQL 的两个表