MST

星途 面试题库

面试题:C语言下poll和select的性能优化场景

在C语言开发基于Linux的应用程序时,针对高并发I/O场景,说明在哪些情况下使用poll性能会优于select,哪些情况下select更合适,并阐述如何对它们进行性能优化,给出相应的代码示例片段。
20.4万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

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;
}