从内核空间到用户空间的事件通知 [英] Event notification from kernel space to user space

查看:50
本文介绍了从内核空间到用户空间的事件通知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一旦内核空间中发生事件,如何通知用户空间应用程序?

How to notify the user space application whenever an event occurs in the kernel space?

当数据到达某个GPIO时,硬件会产生一个中断.该数据被复制到内核缓冲区.此时,我希望驱动程序通知应用程序它可以调用 read 函数,以将数据形式的内核缓冲区复制到用户空间缓冲区.

A hardware generates an interrupt when the data arrives at some GPIO. This data is copied to the kernel buffer. At this point, I want the driver to notify the application that it can call read function to copy the data form kernel buffer to user space buffer.

我考虑过使用 epoll 方法,但是 epoll 指示设备是否准备好从中读取数据.我想要的是 epoll 指示何时内核缓冲区已满.

I thought of using epoll method, but epoll indicates whether the device is ready to be read from. What I want is that, epoll to indicate whenever kernel buffer is full.

而且,是否可以修改驱动程序中 poll_wait()函数的行为?

And, is there a way to modify the behavior of poll_wait() function in the driver?

推荐答案

(已在聊天会话中回答,但似乎应该在答案中,因此在此进行更详细的介绍.)

(Had replied in the chat session but it seems like this should be in an answer so putting it here with more detail.)

poll_wait所做的是将驱动程序添加到用户空间程序正在等待的文件描述符列表中.模式是:

What poll_wait does is add your driver to the list of file descriptors being waited for by the user space program. The pattern is:

  • 用户程序调用poll/select/epoll_ctl
  • 核心内核调用驱动程序的轮询入口点
  • 驱动程序调用poll_wait将其等待队列添加到等待队列列表中(除非GPIO数据已经可读,您可以通过返回值指示)
  • 稍后,当设备中断时,您可以在等待队列中调用wake_up,这将阻止进程(如果仍在轮询/选择调用中)
  • 用户模式程序唤醒,调用读取以实际获取数据

IOW,poll_wait本身不休眠(或阻止);它只是将您的设备添加到程序列表中,这些程序以后可能会唤醒该过程.睡眠是在核心内核中完成的(例如,在select系统调用内部).这样,用户程序可以使用select一次在任意数量的设备上等待.

IOW, poll_wait itself doesn't sleep (or block); it just adds your device to the list of programs that might wake the process up later. The sleep is done in the core kernel (inside the select system call, for example). That way, a user program can wait on any number of devices at once using select.

如果您的用户空间程序在等待时确实没有其他事情要做,那么您可以简单地读取用户程序调用,并让驱动程序设置其等待队列并调用wait_event_interruptible(或其中之一).其他wait_event_ *变体).这将阻塞该过程,直到您的中断处理程序调用唤醒.何时从内核缓冲区复制到用户缓冲区.

If your user-space program really doesn't have anything else to do while waiting, then you can simply have the user-program call read, and have your driver set up its wait queue and call wait_event_interruptible (or one of the other wait_event_* variants). This will block the process until your interrupt handler calls wake_up; at which time you copy from kernel buffer to user buffer.

或者您可以同时支持这两种方法.通常,如果支持select方法,则还要在读取函数中检查O_NONBLOCK文件标志,以便用户代码可以选择在读取中 not 阻止.

Or you could support both methods. Typically if you support the select method, you also check the O_NONBLOCK file flag in your read function so that the user code has the option to not block in the read.

是的,ISR可以调用wake_up.这是设备I/O的常见模式:在进程上下文"中等待/阻塞,在中断上下文"中唤醒,然后在返回到进程上下文后完成I/O.

Yes, ISRs can call wake_up. It's a common pattern for device I/O: wait/block in "process context", wake-up in "interrupt context", then complete the I/O after returning to process context.

BTW使用选择,轮询或epoll通常是相同的.从用户的角度来看,使用select或poll较为容易.这是一个一次性"的交易:这里有一组文件描述符;阻塞直到其中一个文件可供读取(或写入等)或超时为止".

BTW, from the driver point of view, using select, poll or epoll are typically the same. From the user point of view, using select or poll is somewhat easier. It's a "one shot" deal: "here are a set of file descriptors; block until one of them is ready for read (or write etc) or until a timeout".

而使用 epoll,您首先创建一个 epoll 描述符,然后单独添加 I/O 文件描述符.但是然后,"wait"调用仅指定单个epoll描述符.因此,如果要等待的文件描述符数量很多,则不必在每个系统调用中都指定所有文件描述符,这样可以降低每个epoll调用的系统调用开销.

Whereas with epoll, you first create an epoll descriptor, then add I/O file descriptors individually. But then the "wait" call just specifies the single epoll descriptor. So if you have a large number of file descriptors to wait on, you don't have to specify all of them in each system call which leads to lower system call overhead on each epoll call.

这篇关于从内核空间到用户空间的事件通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆