Driver I/O Model (Blocking / Non-blocking / poll)¶
🧠 Overview¶
Linux driver data path is event-driven, not polling-driven.
Core idea:
IRQ → event queue → wake_up() → user-space read/poll
🔁 Blocking vs Non-blocking¶
Blocking I/O¶
- read() will sleep if no data
- process is put into wait queue
- resumed when data arrives
Typical pattern:
Non-blocking I/O¶
- controlled by file flag: O_NONBLOCK
- read() returns immediately
💤 Wait Queue¶
Purpose¶
- bridge between:
- interrupt context
- process context
Key APIs¶
Behavior¶
- process calls read()
- no data → sleep
- IRQ occurs
- driver calls wake_up()
- process resumes
📡 poll / select / epoll¶
Role¶
Allow user-space to wait for events without blocking read()
Driver side¶
User side¶
🔄 Event Flow (Driver)¶
IRQ
→ schedule_work / delayed_work
→ read GPIO
→ detect state change
→ enqueue event
→ wake_up_interruptible()
📦 Event Queue Design¶
Why needed?¶
- decouple IRQ and user-space
- avoid losing events
- support burst events
Implementation¶
- ring buffer
- protected by spinlock
🔐 Locking Strategy¶
| Resource | Lock |
|---|---|
| event queue | spinlock |
| control params | mutex |
⚠️ Common Pitfalls¶
1. Fake blocking¶
❌ busy loop in read()
✔ must use wait_event
2. Missing wake_up()¶
→ read() never returns
3. Wake without condition¶
→ spurious wakeup (acceptable but noisy)
4. Race condition¶
check + dequeue not atomic
(acceptable in simple driver)
🎯 Key Takeaway¶
A correct Linux driver must:
- sleep when no data
- wake on event
- never busy loop
- support poll()
This is the standard I/O model used by:
- UART
- input subsystem
- network stack
- sensors