Skip to content

Day87 - fasync and SIGIO Internals

Objective

This lab implements a simplified Linux-style asynchronous notification framework to understand how SIGIO works, how drivers manage asynchronous listeners through .fasync(), and how signal-driven I/O complements blocking I/O, poll(), and epoll().


Lab1 - Basic fasync Framework

Goal

Implement the basic asynchronous notification infrastructure.

Implemented

  • struct fasync_struct
  • fasync_helper()
  • kill_fasync()
  • Linked-list based asynchronous listener management

Verified

  • Register one listener
  • Duplicate registration detection
  • Unregister listener
  • Multiple listener notification

Lab2 - Driver .fasync() Callback

Goal

Integrate asynchronous listener registration into a simulated character driver.

Implemented

  • Driver .fasync() callback
  • Driver-managed asynchronous listener queue
  • Registration through fasync_helper()

Verified

  • Driver callback registration
  • Multiple file instances
  • Listener removal through .fasync()

Lab3 - Simulated VFS fcntl() Path

Goal

Simulate the Linux VFS path for enabling asynchronous notification.

Implemented

  • Simplified struct file
  • Simplified struct file_operations
  • vfs_fcntl_set_owner()
  • vfs_fcntl_set_async()

Verified

  • F_SETOWN
  • F_SETFL | O_ASYNC
  • VFS dispatch to driver .fasync()
  • Duplicate enable detection
  • Disable asynchronous notification

Lab4 - Wait Queue and Asynchronous Notification

Goal

Verify that a single device event notifies both blocking readers and asynchronous listeners.

Driver Flow

Device Event
data_ready = true
    ├── wake_up()
    └── kill_fasync()

Implemented

  • Driver wait queue
  • Driver asynchronous listener queue
  • Blocking read
  • Device event simulation

Verified

  • Blocking reader wakeup
  • kill_fasync() notification
  • Shared driver state

Lab5 - poll(), epoll(), and SIGIO Integration

Goal

Verify that all event notification mechanisms observe the same driver readiness.

Driver Flow

Device Event
data_ready = true
    ├── wake_up()
    ├── kill_fasync()
    └── .poll()

Implemented

  • Driver .poll()
  • Simplified epoll integration
  • Shared driver readiness state

Verified

  • No readiness before event
  • SIGIO notification after event
  • epoll() detects readiness
  • read() clears readiness
  • epoll() reports no events after read

Overall Learning

This lab demonstrates how Linux supports multiple event-driven I/O models using a shared driver state.

                 Device Event
              data_ready = true
      ┌───────────────┼───────────────┐
      ▼               ▼               ▼
 wake_up()      kill_fasync()      .poll()
      │               │               │
      ▼               ▼               ▼
Blocking Read      SIGIO       poll / epoll

The driver does not need to know which notification mechanism an application is using. It simply updates its internal state and notifies every supported event mechanism.