Understanding the Five I/O Models: Blocking, Non‑Blocking, I/O Multiplexing, Signal‑Driven, and Asynchronous I/O
This article explains the five I/O models—blocking, non‑blocking, I/O multiplexing, signal‑driven, and asynchronous—detailing their operation, typical applications, advantages, and drawbacks within the Linux/UNIX networking environment, and compares synchronous versus asynchronous I/O concepts.
1. I/O
I/O (Input/Output) refers to reading (receiving) or writing (sending) data. In a typical I/O operation, data moves between user space and kernel space, then between kernel space and the device (network or disk). Linux processes cannot access devices directly; they must request the kernel via system calls, which uses buffers.
For an input operation, the kernel first checks its buffer; if data is absent, it reads from the device, which is slower. If data is already buffered, it copies directly to the process.
A network input operation therefore consists of two stages: (1) waiting for data to arrive at the NIC and be placed in the kernel buffer, and (2) copying data from the kernel buffer to user space.
2. Five I/O Models
The "UNIX Network Programming" book defines five I/O models: blocking I/O, non‑blocking I/O, I/O multiplexing, signal‑driven I/O, and asynchronous I/O. The first four are synchronous; only asynchronous I/O is truly asynchronous.
2‑1. Blocking I/O Model
The process issues an I/O system call and is blocked until the kernel finishes the operation and returns the result. Typical applications: blocking sockets, Java BIO.
Process blocks without consuming CPU, providing timely response.
Easy to implement and develop.
Suitable for low‑concurrency network applications.
Not suitable for high‑concurrency scenarios because each request requires a dedicated thread or process, leading to large overhead.
2‑2. Non‑Blocking I/O Model
The process issues an I/O call; if the kernel buffer lacks data, the call returns an error immediately without blocking. If data is available, the kernel returns it. Typical application: sockets set to NONBLOCK.
CPU is consumed by repeated polling.
Implementation is slightly more complex than blocking I/O.
Suitable for modest concurrency where immediate response is not critical.
2‑3. I/O Multiplexing Model
Multiple file descriptors are registered with a selector (e.g., select, poll, epoll). A single process calls the selector; it blocks until at least one descriptor becomes readable. The process then reads the ready data. Typical applications: select, poll, epoll, Java NIO; used by high‑performance servers like Nginx.
One process handles many connections, improving performance (Reactor pattern).
Implementation is more complex.
Ideal for high‑concurrency services.
2‑4. Signal‑Driven I/O Model
The process registers a signal handler with the kernel and returns immediately. When the kernel has data ready, it sends a signal to the process, which then reads the data inside the handler. This callback mechanism is difficult to implement.
2‑5. Asynchronous I/O Model
The process issues an I/O request and returns immediately without blocking. The kernel completes the operation and notifies the process (Proactor pattern). Typical applications: Java 7 AIO, high‑performance servers.
Non‑blocking, data is delivered directly.
Requires OS support (Linux 2.5+ kernels).
Implementation is complex but excellent for high‑performance, high‑concurrency workloads.
3. I/O Model Comparison
3‑1. Blocking vs. Non‑Blocking Calls and Models
Blocking I/O call blocks the calling thread until the operation completes; non‑blocking I/O call returns immediately, allowing the thread to perform other work. The blocking I/O model uses a blocking call, while the non‑blocking model uses repeated non‑blocking calls plus a blocking call to wait for readiness.
3‑2. Synchronous vs. Asynchronous I/O
Synchronous I/O: the requestor blocks until the operation finishes.
Asynchronous I/O: the requestor does not block; the kernel notifies completion later.
In the context of the five models, the first four (blocking, non‑blocking, multiplexing, signal‑driven) are synchronous, while only the asynchronous I/O model is truly asynchronous.
END
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
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.