Day87 - fasync and SIGIO Internals¶
Goal¶
Understand how Linux implements asynchronous event notification using fasync and SIGIO, how user applications enable signal-driven I/O through fcntl(), and how drivers cooperate with the VFS and signal subsystem to notify asynchronous listeners.
What I Learned¶
Signal-driven I/O¶
- Learned why Linux provides signal-driven I/O in addition to blocking I/O and
poll()/epoll(). - Understood the role of
SIGIOas an asynchronous notification mechanism. - Compared blocking, polling, and signal-driven event models.
fasync Infrastructure¶
- Implemented a simplified Linux-style
fasyncframework. - Implemented
struct fasync_structas a linked list of asynchronous listeners. - Implemented
fasync_helper()to register and unregister listeners. - Implemented
kill_fasync()to notify all registered listeners.
Driver .fasync() Callback¶
- Implemented a driver
.fasync()callback. - Connected the driver callback to
fasync_helper(). - Learned that drivers only manage the asynchronous listener list, while signal delivery is handled by the kernel signal subsystem.
VFS Integration¶
- Added a simplified Linux-style
struct file. - Added a simplified
struct file_operations. - Implemented a small VFS helper layer to simulate:
fcntl(F_SETOWN)fcntl(F_SETFL | O_ASYNC)
- Learned how the VFS dispatches asynchronous registration to the driver's
.fasync()callback.
Event Notification Flow¶
- Simulated a device event that updates driver state.
- Verified that one device event can notify:
- Blocking readers through a wait queue.
- Signal-driven applications through
kill_fasync().
- Reinforced that drivers should notify every supported I/O mechanism without knowing which one the application is using.
Relationship with poll() and epoll()¶
- Revisited the role of
.poll()as the single readiness interface implemented by drivers. - Verified that:
poll()andepoll()recheck driver readiness through.poll().SIGIOis delivered independently throughkill_fasync().
- Understood that all three mechanisms observe the same driver state while serving different application models.
Implementation Summary¶
Implemented a simplified Linux-style asynchronous notification framework including:
struct fasync_structfasync_helper()kill_fasync()- Driver
.fasync()callback - Simplified
struct file - Simplified
struct file_operations - Simplified VFS
fcntl()helpers - Wait queue and asynchronous notification integration
- Driver
.poll()integration withepoll
Labs¶
Lab1¶
Implemented the basic fasync framework.
Verified:
- Listener registration
- Duplicate registration detection
- Listener removal
- Multiple asynchronous listeners
Lab2¶
Integrated the driver .fasync() callback.
Verified:
- Driver registration through
.fasync() - Driver-managed asynchronous listener list
- Multiple file instances
Lab3¶
Implemented a simplified VFS fcntl() path.
Verified:
F_SETOWNO_ASYNC- VFS dispatch to
.fasync()
Lab4¶
Integrated wait queue and asynchronous notification.
Verified:
- Blocking read
wake_up()kill_fasync()- Driver event notification
Lab5¶
Integrated .poll(), epoll(), and SIGIO.
Verified:
- Driver readiness before and after events
- Readiness clearing after
read() - Relationship between
poll(),epoll(), and asynchronous notification
Key Takeaways¶
poll(),epoll(), andSIGIOare complementary rather than competing mechanisms.- Drivers expose readiness through
.poll()and asynchronous notification through.fasync(). kill_fasync()complementswake_up()so that one device event can support multiple user-space I/O models.- The VFS bridges user-space
fcntl()requests to the driver's.fasync()callback. - The driver remains the single source of truth for device readiness, while different notification mechanisms expose that state to user space.