1. poll性能优于select的情况
- 连接数较多时:
select
受限于 FD_SETSIZE
(通常为1024),而 poll
通过动态分配 struct pollfd
数组,可以轻松处理大量文件描述符。例如在一个需要处理上千个并发连接的网络服务器场景下,poll
更具优势。
- 对文件描述符类型支持更广泛:
select
主要用于处理套接字和文件描述符,而 poll
除了支持套接字外,还能处理其他类型的文件描述符,如管道、设备文件等。在一个涉及多种类型文件描述符的复杂I/O场景中,poll
更合适。
2. select更合适的情况
- 连接数较少且相对固定时:如果应用程序只需要处理少量(远小于
FD_SETSIZE
)且固定数量的文件描述符,select
的简单性和较低的开销使其成为一个不错的选择。例如一个简单的客户端程序,只与一个服务器进行通信,使用 select
就足够了。
3. 性能优化
select性能优化
- 减少每次调用
select
时重置文件描述符集的开销:select
在返回后会修改传入的文件描述符集,需要每次重新设置。可以通过保存原始的文件描述符集,并在每次调用 select
前复制到临时集合来避免重复设置。
- 合理设置超时时间:根据应用场景,合理设置
select
的超时时间,避免过长的等待导致响应不及时,或者过短的超时导致频繁无效唤醒。
poll性能优化
- 批量处理事件:当
poll
返回有事件发生时,尽量批量处理这些事件,减少系统调用次数。
- 合理分配
struct pollfd
数组:根据预估的最大并发连接数,合理分配 struct pollfd
数组大小,避免频繁的内存分配和释放。
4. 代码示例片段
select示例
#include <stdio.h>
#include <sys/select.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#define FD_SETSIZE 1024
int main() {
fd_set read_fds;
fd_set tmp_fds;
int fd;
FD_ZERO(&read_fds);
FD_ZERO(&tmp_fds);
fd = open("test.txt", O_RDONLY);
if (fd < 0) {
perror("open");
return 1;
}
FD_SET(fd, &read_fds);
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
while (1) {
tmp_fds = read_fds;
int ret = select(fd + 1, &tmp_fds, NULL, NULL, &timeout);
if (ret < 0) {
perror("select");
break;
} else if (ret == 0) {
printf("Timeout\n");
} else {
if (FD_ISSET(fd, &tmp_fds)) {
char buf[1024];
int n = read(fd, buf, sizeof(buf));
if (n < 0) {
perror("read");
} else if (n > 0) {
buf[n] = '\0';
printf("Read: %s\n", buf);
}
}
}
}
close(fd);
return 0;
}
poll示例
#include <stdio.h>
#include <poll.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define MAX_EVENTS 10
int main() {
struct pollfd fds[MAX_EVENTS];
int fd;
fd = open("test.txt", O_RDONLY);
if (fd < 0) {
perror("open");
return 1;
}
fds[0].fd = fd;
fds[0].events = POLLIN;
int nfds = 1;
while (1) {
int ret = poll(fds, nfds, 5000);
if (ret < 0) {
perror("poll");
break;
} else if (ret == 0) {
printf("Timeout\n");
} else {
if (fds[0].revents & POLLIN) {
char buf[1024];
int n = read(fds[0].fd, buf, sizeof(buf));
if (n < 0) {
perror("read");
} else if (n > 0) {
buf[n] = '\0';
printf("Read: %s\n", buf);
}
}
}
}
close(fd);
return 0;
}