poll
是 Linux 系统中的一个系统调用,用于监视多个文件描述符的状态变化(例如是否可读、可写或异常)。与 select
类似,poll
允许单个线程处理多个 I/O 操作,从而避免了为每个文件描述符创建单独线程的开销。
poll
函数原型如下:
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
fds
是一个指向 pollfd
结构体数组的指针,每个 pollfd
结构体代表一个要监视的文件描述符。nfds
是 fds
数组中的元素数量。timeout
是等待时间,以毫秒为单位。如果设置为 -1,则 poll
会无限期等待,直到至少有一个文件描述符就绪;如果设置为 0,则 poll
会立即返回。pollfd
结构体定义如下:
struct pollfd {
int fd; // 文件描述符
short events; // 请求的事件
short revents; // 返回的事件
};
poll
相较于 select
在处理大量文件描述符时有更好的性能,因为它不需要每次调用时重新初始化文件描述符集合。poll
的 API 更加直观,使用起来更方便。下面是一个简单的 poll
使用示例,演示如何监视两个文件描述符(例如两个套接字)的可读性:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <poll.h>
#define MAX_FDS 2
int main() {
int sockfd1, sockfd2;
struct sockaddr_in serv_addr1, serv_addr2;
socklen_t length;
if ((sockfd1 = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(1);
}
if ((sockfd2 = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(1);
}
// 设置服务器地址和端口...
struct pollfd fds[MAX_FDS];
fds[0].fd = sockfd1;
fds[0].events = POLLIN;
fds[1].fd = sockfd2;
fds[1].events = POLLIN;
int ret = poll(fds, MAX_FDS, -1);
if (ret < 0) {
perror("poll");
exit(1);
}
for (int i = 0; i < MAX_FDS; i++) {
if (fds[i].revents & POLLIN) {
char buf[1024];
ssize_t n = read(fds[i].fd, buf, sizeof(buf));
if (n < 0) {
perror("read");
exit(1);
}
printf("Received data from socket %d: %s
", fds[i].fd, buf);
}
}
close(sockfd1);
close(sockfd2);
return 0;
}
poll
时需要注意文件描述符的数量限制,虽然它比 select
有更好的性能,但在处理大量文件描述符时仍然可能成为瓶颈。领取专属 10元无门槛券
手把手带您无忧上云