Master Linux Socket I/O Models: Blocking, Non‑Blocking, Select, Signal‑Driven & Asynchronous
This article uses a relatable mailbox story to explain Linux socket I/O models—including synchronous blocking, synchronous non‑blocking, I/O multiplexing with select, signal‑driven I/O, and asynchronous I/O—detailing their mechanisms, advantages, drawbacks, and typical code patterns.
Introduction
The article introduces Linux socket I/O concepts through a humorous analogy: a father (old Chen) waiting for letters from his daughter, which mirrors how a process interacts with sockets.
1. Synchronous Blocking Model
In this classic model the application issues a system call (e.g., connect, send, recv) and blocks until the operation completes or fails. The process does nothing else while waiting, which keeps resource usage minimal but requires a dedicated thread for each connection.
2. Synchronous Non‑Blocking Model
Here the socket is set to non‑blocking mode (e.g., fcntl(fd, F_SETFL, flag | O_NONBLOCK)). System calls return immediately with EAGAIN / EWOULDBLOCK if the operation cannot be completed, forcing the application to poll repeatedly. This allows the process to perform other work while waiting, but busy‑polling wastes CPU cycles.
Typical polling loop:
while (1) {
// non‑blocking read on device 1
if (device1_has_data) {
// handle data
}
// non‑blocking read on device 2
if (device2_has_data) {
// handle data
}
// …
}3. I/O Multiplexing (Asynchronous Blocking) Model
To avoid constant polling, the kernel can notify the process when one of many descriptors becomes ready. The classic implementation uses select(), which blocks until at least one socket is readable/writable or an error occurs. When select returns, the program calls recv to copy the data.
4. Signal‑Driven I/O Model
In this approach the socket is configured to generate a SIGIO signal when it becomes ready. The program installs a signal handler via sigaction(). The handler can call recvfrom() or simply set a flag for the main loop, allowing the process to continue other work without blocking.
5. Asynchronous (Non‑Blocking) I/O Model
Linux’s native asynchronous I/O (AIO) is rarely used. Unlike signal‑driven I/O, the kernel notifies the process only after the entire operation finishes. Typical steps for an asynchronous read are:
Issue read; the call returns immediately, indicating the request was queued.
The kernel performs the actual data transfer in the background.
When the read completes, the kernel sends a signal or invokes a callback, allowing the application to process the data.
Server‑side flow (illustrated in the original diagrams) shows the process issuing an asynchronous read, continuing other work, and later receiving a completion notification.
6. Summary and Q&A
The article revisits the four (actually five) I/O models and answers two key questions:
Blocking vs. Non‑Blocking: Blocking I/O stalls the process until the operation finishes; non‑blocking I/O returns immediately with an error code if data isn’t ready, requiring the application to retry.
Synchronous vs. Asynchronous: Synchronous I/O (including blocking, non‑blocking, and multiplexing) blocks the process at some point during the actual data transfer. Asynchronous I/O returns immediately after the request and only notifies the process upon completion, keeping the process unblocked throughout.
Comparative diagrams (included in the original) illustrate the trade‑offs, emphasizing that non‑blocking still requires active polling, whereas asynchronous I/O fully delegates the operation to the kernel.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ITPUB
Official ITPUB account sharing technical insights, community news, and exciting events.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
