Skip to content

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.

SIGIO handler
write(eventfd)
epoll_wait(eventfd)

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.