fasync and SIGIO¶
fasync allows a driver to notify a user-space process asynchronously by sending SIGIO. This is another notification model besides blocking read(), poll, and epoll.
SIGIO is complementary to blocking I/O and readiness-based mechanisms such as poll() and epoll(). While poll() and epoll() require applications to wait for readiness, SIGIO allows the kernel to notify user space asynchronously when an event occurs.
All three mechanisms ultimately observe the same driver state but expose different event notification models.
Basic Flow¶
Application
fcntl(F_SETOWN)
↓
fcntl(F_SETFL | O_ASYNC)
↓
VFS
↓
driver .fasync()
↓
fasync_helper()
↓
Device Event
↓
kill_fasync(..., SIGIO, POLL_IN)
↓
User-space SIGIO handler
When It Is Useful¶
SIGIO can be useful for simple asynchronous notification, but it is usually less structured than fd-based event loops.
Driver Event Notification¶
A driver should notify every supported event mechanism whenever its internal state changes.
Device Event
↓
data_ready = true
↓
┌───────────────┬────────────────┐
▼ ▼ ▼
wake_up() kill_fasync() .poll()
│ │ │
▼ ▼ ▼
Blocking I/O SIGIO poll / epoll
The driver does not need to know which notification model an application is using. It simply updates its internal state and notifies every supported mechanism.
Driver-Side Components¶
| Component | Purpose |
|---|---|
.poll |
Reports current readiness state |
.fasync |
Registers or unregisters async notification target |
fasync_helper() |
Maintains async notification list |
kill_fasync() |
Sends SIGIO to registered process |
Common Pitfalls¶
Warning
Signal handlers should do as little work as possible. Writing to eventfd is a safer pattern than doing complex processing inside the handler.
Warning
SIGIO is process-signal based, while epoll is fd-based. Mixing both models requires careful design.
Relationship with poll() and epoll()¶
poll(), epoll(), and SIGIO observe the same driver readiness but use different notification models.
| Mechanism | Notification Model |
|---|---|
Blocking read() |
Sleep until awakened |
poll() |
Readiness polling |
epoll() |
Event-driven readiness polling |
SIGIO |
Asynchronous signal delivery |
Drivers typically implement both .poll() and .fasync() so applications can choose the most appropriate I/O model.