epoll阻塞和非阻塞模式
时间: 2025-01-01 18:26:09 浏览: 5
### epoll 阻塞与非阻塞模式的区别
#### 区别说明
在 Linux 系统中,`epoll` 提供了一种高效的 I/O 多路复用机制。其核心优势在于能够高效地管理大量并发连接。对于 `epoll` 来说,存在两种主要的操作方式:阻塞模式和非阻塞模式。
当处于 **阻塞模式** 下时,在调用如 `epoll_wait()` 函数等待事件发生的过程中,如果没有任何就绪的文件描述符,则当前线程会被挂起直到有新的事件到来[^1]。这种方式适用于服务器端应用中有较少数量高吞吐量需求的情况。
而在 **非阻塞模式** 中,即使没有准备好任何可读写的套接字或其他资源,函数也会立即返回并告知应用程序此时无可用数据或准备好的连接请求。这使得开发者可以在不浪费 CPU 资源的情况下快速响应其他任务,并通过轮询的方式持续检查是否有新事件产生[^4]。
#### 使用场景分析
- 对于大多数 Web 应用和服务而言,默认采用的是基于 `epoll` 的阻塞模式来简化逻辑实现,因为在这种情况下可以更方便地处理每一个客户端连接而无需额外考虑复杂的调度算法。
- 当面对极高并发数目的短链接服务(例如即时通讯工具),或是希望减少延迟时间提高实时性的场合下,则更适合选用非阻塞版本配合事件循环机制来进行优化设计[^2]。
```c
// 创建监听socket并设置为非阻塞
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
fcntl(listen_fd, F_SETFL, O_NONBLOCK);
struct sockaddr_in serv_addr;
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portno);
bind(listen_fd, (struct sockaddr *) &serv_addr,sizeof(serv_addr));
listen(listen_fd,5);
// 初始化epoll实例
int epoll_fd = epoll_create(EPOLL_CLOEXEC);
// 添加监听socket到epoll监视列表里
struct epoll_event event;
event.events = EPOLLIN | EPOLLET; // 边缘触发模式
event.data.fd = listen_fd;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd,&event);
while(true){
struct epoll_event events[MAX_EVENTS];
int n_fds = epoll_wait(epoll_fd,events,MAX_EVENTS,-1);
for(int i=0;i<n_fds;++i){
if(events[i].data.fd==listen_fd){ /* handle new connection */ }
else{ /* read data from existing connections or write to them */}
}
}
```
阅读全文