IO Multiplexing
A single thread tracks each socket’s state to manage multiple I/O streams at once.
When user input blocks, the process cannot see the socket’s EOF if the server terminates. The socket won’t show EOF until read time. So processes need to tell the kernel in advance which I/O conditions to watch. The kernel then notifies the process when those conditions are ready. This is called I/O multiplexing.
Use Cases
- Client handles multiple descriptors
- Handle multiple sockets
- TCP server listens and processes sockets
- Handle both TCP and UDP
- Process multiple services or protocols
Socket Input Operations
- Wait for network data (packets arrive)
- Copy data to kernel buffers
- Copy data from kernel to application buffers
UNIX I/O Models
Blocking I/O Model
System calls like recvfrom block the whole process until data arrives or an error occurs.
Non-blocking I/O Model
Polling
The process keeps calling recvfrom to check if data is ready. If not ready, it returns an error. This wastes CPU time.
I/O Multiplexing Model: select
Use select to block until a socket becomes readable. Then call recvfrom. This avoids polling. You get two system calls instead of one, but you can wait for multiple descriptors.
Signal-driven I/O Model
Tell the kernel to send a SIGIO signal when the descriptor is ready. The signal handler calls recvfrom.
Asynchronous I/O Model
Call non-blocking aio_read with a user-space buffer pointer and size. The kernel copies data to user space and sends a signal to the process. This works like a callback function.
![][image-1]
epoll Event-driven I/O Model
Epoll signals readability when a file descriptor’s kernel buffer is not empty. It signals writability when the write buffer is not full.
- Epoll uses
put_userto write data to user space - Epoll is event-driven.
epoll_ctlregisters events and callback functions.epoll_waitonly returns events that occurred, avoiding the full polling operations ofselectandpoll. The kernel tells the process when data arrives on any socket.
Epoll performance bottleneck: If requests exceed 50,000 per machine, the single-machine request limit becomes the bottleneck. You need load balancing. If requests stay below this limit, database I/O handling becomes the bottleneck.
Internal implementation:
- Event callback queue
- File descriptor red-black tree
- Spinlock protects the queue, mutex protects the red-black tree for thread safety
Level-triggered
- As long as the read kernel buffer is not empty and has data to read, keep signaling readability
- As long as the kernel write buffer is not full and has space to write, keep signaling writability
Edge-triggered
- When the read kernel buffer changes from empty to not empty, signal readability
- When the kernel write buffer changes from full to not full, signal writability
Differences
Level-triggered keeps signaling as long as the read buffer has data. Edge-triggered only signals once when empty changes to not empty.