poll
是 Linux 系统中的一个系统调用,用于监视多个文件描述符的状态变化,比如是否可读、可写或出现异常条件。它是处理多个 I/O 操作的一种高效方式,相比于传统的 select
,poll
在处理大量文件描述符时有更好的性能。
poll
函数允许程序等待多个文件描述符中的任何一个变为可读、可写或有异常条件待处理。其函数原型如下:
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
fds
是一个指向 pollfd
结构体数组的指针,每个结构体代表一个文件描述符及其关注的事件。nfds
是 fds
数组中元素的数量。timeout
是等待的超时时间(以毫秒为单位),如果为 -1,则表示无限期等待直到有事件发生;如果为 0,则表示立即返回。poll
不需要像 select
那样重新初始化文件描述符集,因此在处理大量文件描述符时效率更高。poll
返回时,不需要重新设置文件描述符集,可以直接从返回的结构体数组中获取就绪的文件描述符。pollfd
结构体定义如下:
struct pollfd {
int fd; // 文件描述符
short events; // 关注的事件
short revents; // 发生的事件
};
events
和 revents
是位掩码,可以使用以下事件:
POLLIN
:文件描述符可读。POLLOUT
:文件描述符可写。POLLERR
:文件描述符发生错误。POLLHUP
:文件描述符挂起事件。POLLNVAL
:文件描述符非法。poll
常用于网络编程,如服务器端程序,用于同时处理多个客户端连接。它可以有效地等待多个套接字变得可读或可写,从而实现非阻塞的 I/O 多路复用。
以下是一个简单的 poll
使用示例,用于监听标准输入和网络套接字的事件:
#include <poll.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int sockfd;
int result;
struct sockaddr_in serv_addr;
socklen_t length;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(1);
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(8080);
result = connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (result < 0) {
perror("connect");
exit(1);
}
struct pollfd fds[2];
fds[0].fd = STDIN_FILENO;
fds[0].events = POLLIN;
fds[1].fd = sockfd;
fds[1].events = POLLIN;
while (1) {
result = poll(fds, 2, -1);
if (result < 0) {
perror("poll");
exit(1);
}
if (fds[0].revents & POLLIN) {
char buf[1024];
ssize_t n = read(STDIN_FILENO, buf, sizeof(buf));
if (n > 0) {
printf("stdin: %s", buf);
}
}
if (fds[1].revents & POLLIN) {
char buf[1024];
ssize_t n = read(sockfd, buf, sizeof(buf));
if (n > 0) {
printf("socket: %s", buf);
}
}
}
close(sockfd);
return 0;
}
poll
返回的事件数量非常多,处理这些事件可能会成为瓶颈。此时可以考虑使用更高级的 I/O 多路复用技术,如 epoll
(Linux 特有)。poll
时,需要确保在不再需要监视某个文件描述符时关闭它,以避免文件描述符泄漏。poll
的超时参数需要根据实际应用场景合理设置,以避免程序长时间阻塞或频繁轮询导致的 CPU 占用过高。通过合理使用 poll
,可以有效地管理多个 I/O 操作,提高程序的性能和响应速度。
领取专属 10元无门槛券
手把手带您无忧上云