blocking versus non-blocking I/O
You phone a shop to ask if your order is ready. In one style, the clerk says 'hold the line' and keeps you waiting silently until the answer is ready - you cannot do anything else meanwhile. In the other style, the clerk says 'not yet, call back later' and lets you go do other things. The first is blocking; the second is non-blocking.
Concretely, by default a read() or write() is blocking: if a read has no data available yet - the keyboard is silent, the pipe is empty, the network has not delivered - the call simply does not return; your program is suspended (the kernel marks it not-runnable) until data arrives. That is fine when waiting is exactly what you want, and it costs no CPU while suspended. Non-blocking I/O changes the deal: you open the file with the O_NONBLOCK flag (or set it later with fcntl). Now if a read would have to wait, it returns -1 immediately with errno set to EAGAIN (or EWOULDBLOCK) meaning 'nothing right now, try again later,' and a write that cannot proceed does the same. Your program stays in control and can go do other useful work, then come back and retry.
Why it matters: blocking is simple and perfect for a program that does one thing at a time. But a program juggling many connections at once - a chat server with hundreds of clients - cannot afford to freeze on one slow reader while the others starve. Non-blocking I/O is the foundation for handling many descriptors together, usually paired with a readiness mechanism (select, poll, epoll) that tells you which descriptors can be read or written without blocking, so you only touch the ones that are ready. The trade-off is more complex code: you must handle EAGAIN everywhere and manage your own loop.
int fd = open("pipe", O_RDONLY | O_NONBLOCK); ssize_t n = read(fd, buf, sizeof buf); if (n < 0 && errno == EAGAIN) { /* nothing ready right now - go do other work, retry later */ }
With O_NONBLOCK, a read that would block returns EAGAIN instead of suspending the program.
EAGAIN/EWOULDBLOCK is not a real error - it means 'try again,' and you must handle it, usually with a readiness call (poll/select/epoll) so you do not busy-loop. A blocked process uses zero CPU while waiting; a naive non-blocking retry loop can burn 100% of a core for nothing.