poll and select¶
poll() and select() are readiness-based I/O multiplexing APIs. They allow a process to wait until one or more file descriptors become ready for I/O.
Core Concept¶
This avoids CPU-wasting busy loops such as repeatedly calling read() until data appears.
Blocking vs Non-blocking I/O¶
| Mode | Behavior |
|---|---|
Blocking read() |
Sleeps until data is available |
Non-blocking read() |
Returns -1 with errno = EAGAIN if no data is available |
poll() + non-blocking fd |
Sleeps until an fd is ready, then performs non-blocking I/O |
Typical poll Loop¶
struct pollfd fds[1];
fds[0].fd = fd;
fds[0].events = POLLIN;
while (1) {
int ret = poll(fds, 1, -1);
if (ret < 0) {
if (errno == EINTR)
continue;
break;
}
if (fds[0].revents & POLLIN) {
/* Read until the event is consumed. */
read(fd, buf, sizeof(buf));
}
}
Relationship with Kernel Drivers¶
A pollable character driver usually implements:
static __poll_t mydev_poll(struct file *file, poll_table *wait)
{
poll_wait(file, &ctx->read_wq, wait);
if (event_available(ctx))
return EPOLLIN | EPOLLRDNORM;
return 0;
}
Important points:
.polldoes not consume data..pollonly reports readiness.- Userspace must call
read()after the fd becomes ready. - If data remains unread,
poll()will keep reporting readiness.
Common Pitfalls¶
| Pitfall | Result |
|---|---|
Forgetting to read after poll() |
The same fd keeps waking the event loop |
Busy loop with non-blocking read() |
High CPU usage |
| Treating readiness as data | Incorrect design; readiness only means I/O may proceed |
Ignoring EINTR |
Event loop exits unexpectedly when interrupted by signals |