Notify Gpio Interrupt to User Space from a Kernel Module

Notify userland from a kernel module

Calling from the kernel to userspace is certainly possible, for instance spawning a userspace process (consider the kernel launches init, udev and some more) or using IPC (netlink and others).

However, this is not what you want.

As people mentioned to you, the way to go is to have a char device and then use standard and well-known select/poll semantics. I don't think you should be worried about this being slow, assuming your userspace program is well-designed.

In fact, this design is so common that there is an existing framework called UIO or Userspace I/O (see here and here).

How to handle GPIO interrupt-like handling in Linux userspace

From kernel gpio/sysfs.txt:

"value" ... reads as either 0 (low) or 1 (high). If the GPIO
is configured as an output, this value may be written;
any nonzero value is treated as high.

If the pin can be configured as interrupt-generating interrupt
and if it has been configured to generate interrupts (see the
description of "edge"), you can poll(2) on that file and
poll(2) will return whenever the interrupt was triggered. If
you use poll(2), set the events POLLPRI and POLLERR. If you
use select(2), set the file descriptor in exceptfds. After
poll(2) returns, either lseek(2) to the beginning of the sysfs
file and read the new value or close the file and re-open it
to read the value.

"edge" ... reads as either "none", "rising", "falling", or
"both". Write these strings to select the signal edge(s)
that will make poll(2) on the "value" file return.

This file exists only if the pin can be configured as an
interrupt generating input pin.

The preferred way is usually to configure the interrupt with /sys/class/gpio/gpioN/edge and poll(2) for POLLPRI | POLLERR (important it's not POLLIN!) on /sys/class/gpio/gpioN/value. If your process is some "real-time" process that needs to handle the events in real time, consider decreasing it's niceness.

You can even find some example code on github that uses poll, ex. this repo.

sending asynchronous events to user space on interrupt detection

You can use Netlink sockets in order to send an event from kernel space to user space. You can then spawn a thread in user space which listens to this Netlink socket. This can be done using select() or epoll() function in your user-space application. http://www.linuxjournal.com/article/7356 is a good reference.

Event notification from kernel space to user space

(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. The pattern is:

  • user program calls 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)
  • 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
  • user-mode program wakes up, calls read to actually obtain the data

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.

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.

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.

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, 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".

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.



Related Topics



Leave a reply



Submit