Event-Driven I/O in Linux¶
Overview¶
In Linux, device drivers do not provide callback-based async APIs to user space.
Instead, Linux uses a unified I/O model:
- blocking I/O
- non-blocking I/O
- event-driven I/O through poll/select/epoll
Blocking vs Non-Blocking¶
Blocking read¶
- If no data is available, the process sleeps.
- The driver wakes it up later through a wait queue.
Non-blocking read¶
- If no data is available,
read()returns immediately. - The usual return code is
-EAGAIN.
Event-Driven I/O¶
Key idea¶
Event-driven I/O separates:
- waiting for an event
- reading the data
Typical user-space flow:
poll() waits for readiness.
read() fetches the actual data.
Wait Queue¶
Purpose¶
A wait queue is used to:
- put a process to sleep
- wake it up later when an event occurs
Declaration¶
Initialization¶
Sleep¶
This puts the process to sleep until the condition becomes true.
Wakeup¶
This wakes processes sleeping on the wait queue.
poll()¶
Role¶
poll() does not read data.
It only answers this question:
- Is this file descriptor ready?
Driver implementation example¶
static __poll_t mygpio_poll(struct file *file, poll_table *wait)
{
struct mygpio_dev *mydev = file->private_data;
__poll_t mask = 0;
poll_wait(file, &mydev->read_queue, wait);
if (mydev->event_pending)
mask |= POLLIN | POLLRDNORM;
return mask;
}
Key API: poll_wait()¶
This connects the file descriptor to the driver's wait queue.
If no event is ready yet, the process can sleep and later be awakened by:
Return value¶
POLLINmeans readablePOLLRDNORMmeans normal readable data0means not ready
Relationship Between Components¶
IRQ
→ event_pending = 1
→ wake_up_interruptible()
→ poll() wakes up
→ read() consumes data
→ event_pending = 0
Driver vs User Space Responsibilities¶
Driver side¶
The driver is responsible for:
- detecting the event
- storing event state
- waking sleeping processes
- reporting readiness through
.poll()
User-space side¶
User space is responsible for:
- choosing blocking or non-blocking mode
- calling poll/select/epoll
- calling read() to fetch data
Important Insight¶
Linux does not let the kernel call user callbacks directly.
Instead:
- the kernel exposes readiness
- user space controls its own event loop
Summary¶
| Feature | Mechanism |
|---|---|
| Blocking read | wait_event_interruptible() |
| Non-blocking read | O_NONBLOCK + -EAGAIN |
| Event-driven I/O | poll/select/epoll |
| Wakeup source | IRQ |
| Bridge between IRQ and user | wait queue |