简体   繁体   English

从内核空间到用户空间的事件通知

[英]Event notification from kernel space to user space

How to notify the user space application whenever an event occurs in the kernel space? 如何在内核空间中发生事件时通知用户空间应用程序?

A hardware generates an interrupt when the data arrives at some GPIO. 当数据到达某个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. 此时,我希望驱动程序通知应用程序它可以调用read函数将数据形式的内核缓冲区复制到用户空间缓冲区。

I thought of using epoll method, but epoll indicates whether the device is ready to be read from. 我想过使用epoll方法,但epoll表示设备是否可以读取。 What I want is that, epoll to indicate whenever kernel buffer is full. 我想要的是, epoll表示每当内核缓冲区已满。

And, is there a way to modify the behavior of poll_wait() function in the driver? 并且,有没有办法修改驱动程序中poll_wait()函数的行为?

(Had replied in the chat session but it seems like this should be in an answer so putting it here with more detail.) (如果在聊天会话中回复,但似乎这应该是一个答案,所以把它放在这里更详细。)

What poll_wait does is add your driver to the list of file descriptors being waited for by the user space program. poll_wait的作用是将驱动程序添加到用户空间程序等待的文件描述符列表中。 The pattern is: 模式是:

  • user program calls poll/select/epoll_ctl 用户程序调用poll / select / epoll_ctl
  • core kernel calls your driver's poll entry point 核心内核调用驱动程序的轮询入口点
  • driver calls poll_wait to add its wait queue to the list of waitqueues (unless the GPIO data is already readable, which you indicate via return value) 驱动程序调用poll_wait将其等待队列添加到等待队列列表中(除非GPIO数据已经可读,您通过返回值指示)
  • later, when the device interrupts, you call wake_up on your wait queue, this unblocks the process if it's (still) waiting in a poll/select call 之后,当设备中断时,您在等待队列上调用wake_up,如果它(仍然)在轮询/选择呼叫中等待,则会解锁该进程
  • user-mode program wakes up, calls read to actually obtain the data 用户模式程序唤醒,调用读取实际获取数据

IOW, poll_wait itself doesn't sleep (or block); IOW,poll_wait本身不会休眠(或阻塞); 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). 睡眠是在核心内核中完成的(例如,在select系统调用内)。 That way, a user program can wait on any number of devices at once using select. 这样,用户程序可以使用select一次在任意数量的设备上等待。

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). 如果您的用户空间程序在等待时确实没有其他任何操作,那么您只需读取用户程序调用,并让您的驱动程序设置其等待队列并调用wait_event_interruptible(或其中一个wait_event_ *变种)。 This will block the process until your interrupt handler calls wake_up; 这将阻止进程,直到你的中断处理程序调用wake_up; at which time you copy from kernel buffer to user buffer. 此时您从内核缓冲区复制到用户缓冲区。

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. 通常,如果您支持select方法,还可以检查读取函数中的O_NONBLOCK文件标志,以便用户代码可以选择不在读取中阻止。

Yes, ISRs can call wake_up. 是的,ISR可以调用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. 这是设备I / O的常见模式:“进程上下文”中的等待/阻塞,“中断上下文”中的唤醒,然后在返回到进程上下文后完成I / O.

BTW, from the driver point of view, using select, poll or epoll are typically the same. 顺便说一句,从驱动程序的角度来看,使用select,poll或epoll通常是相同的。 From the user point of view, using select or poll is somewhat easier. 从用户的角度来看,使用select或poll更容易一些。 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". 这是一次“一次性”交易:“这里有一组文件描述符;阻塞直到其中一个准备好读取(或写入等)或直到超时”。

Whereas with epoll, you first create an epoll descriptor, then add I/O file descriptors individually. 而对于epoll,您首先创建一个epoll描述符,然后单独添加I / O文件描述符。 But then the "wait" call just specifies the single epoll descriptor. 但是,“等待”调用只是指定单个epoll描述符。 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. 因此,如果要等待大量文件描述符,则不必在每次系统调用中指定所有这些文件描述符,这会导致每次epoll调用的系统调用开销降低。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM