找回密码
 立即注册
首页 资源区 代码 select和poll

select和poll

JulianaEgg 2025-5-28 22:18:24
select函数

原理

select通过一个文件描述符集合(fd_set)来监控多个文件描述符。它会检查这些文件描述符是否准备好进行读、写或异常操作。fd_set是一个位数组,每个位对应一个文件描述符。select会扫描这个数组,检查每个文件描述符的状态。
使用方法

使用FD_SET宏将文件描述符添加到fd_set中,然后调用select函数。select函数会返回准备好操作的文件描述符的数量,并更新fd_set,将未准备好的文件描述符从集合中移除。
优点


  • select的API相对简单,容易理解和使用。
  • 几乎所有操作系统都支持select,具有很好的兼容性。
缺点


  • select的最大文件描述符数量通常受限于系统定义的FD_SETSIZE(通常是1024)。当监控大量文件描述符时,性能会显著下降。
  • select需要扫描整个fd_set来确定哪些文件描述符准备好,这在文件描述符数量较多时效率较低。
  • select需要为每个文件描述符分配一个位,当文件描述符数量较多时,会浪费较多的内存资源。
  • 不适用于需要处理大量文件描述符的场景。
  1. #include <sys/select.h>
  2. #include <sys/time.h>
  3. int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
  4. //nfds:需要监控的文件描述符的最大值加1
  5. //readfds:指向可读文件描述符集合的指针
  6. //writefds:指向可写文件描述符集合的指针
  7. //exceptfds:指向异常条件文件描述符集合的指针
  8. //timeout:超时时间
  9. //ret:返回集合中文件描述符的数量,调用完成后没有改变的文件描述符会被清除
复制代码
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/select.h>
  4. #include <unistd.h>
  5. int main() {
  6.     // 创建两个文件描述符,用于示例
  7.     int pipefds[2];
  8.     if (pipe(pipefds) == -1) {
  9.         perror("pipe");
  10.         exit(EXIT_FAILURE);
  11.     }
  12.     // 初始化文件描述符集合
  13.     fd_set readfds;
  14.     FD_ZERO(&readfds);
  15.     FD_SET(pipefds[0], &readfds); // 读端
  16.     FD_SET(STDIN_FILENO, &readfds); // 标准输入
  17.     // 设置超时时间
  18.     struct timeval timeout;
  19.     timeout.tv_sec = 5; // 5秒超时
  20.     timeout.tv_usec = 0;
  21.     // 调用 select
  22.     int ret = select(pipefds[0] + 1, &readfds, NULL, NULL, &timeout);
  23.     if (ret == -1) {
  24.         perror("select");
  25.         exit(EXIT_FAILURE);
  26.     } else if (ret == 0) {
  27.         printf("Select timeout\n");
  28.     } else {
  29.         if (FD_ISSET(pipefds[0], &readfds)) {
  30.             printf("Pipe read end is ready for reading\n");
  31.         }
  32.         if (FD_ISSET(STDIN_FILENO, &readfds)) {
  33.             printf("Standard input is ready for reading\n");
  34.         }
  35.     }
  36.     // 关闭文件描述符
  37.     close(pipefds[0]);
  38.     close(pipefds[1]);
  39.     return 0;
  40. }
复制代码
poll函数

原理

poll使用一个pollfd结构数组来监控文件描述符。每个pollfd结构包含一个文件描述符、要监控的事件(如读、写)和事件状态。poll函数会检查这些结构,确定哪些文件描述符已经准备好指定的事件。
使用方法

创建一个pollfd数组,为每个文件描述符设置要监控的事件,然后调用poll函数。poll函数会返回准备好操作的文件描述符的数量,并更新每个pollfd结构的事件状态。
优点


  • poll没有像select那样的文件描述符数量限制,可以处理更多的文件描述符。
  • poll直接返回准备好操作的文件描述符,不需要像select那样扫描整个集合,效率相对较高。
缺点


  • poll需要为每个文件描述符分配一个pollfd结构,当文件描述符数量较多时,会占用较多的内存资源。
  • 虽然poll没有文件描述符数量限制,但在文件描述符数量非常多时,性能也会受到影响,因为poll需要逐个检查每个pollfd结构。
  • 不适用于高并发的场景
  1. struct pollfd {
  2.     int fd;        // 文件描述符
  3.     short events;  // 需要监控的事件
  4.     short revents; // 实际发生的事件
  5. };
  6. #include <poll.h>
  7. int poll(struct pollfd *fds, nfds_t nfds, int timeout);
  8. //fds:指向 pollfd 结构数组的指针
  9. //nfds:pollfd 结构数组的大小。
  10. //timeout:超时时间(毫秒)。如果设置为 -1,则表示阻塞直到有文件描述符准备好。
  11. //ret:>0 状态改变的文件描述符的数量  =0 超时   -1,表示调用发生错误。
复制代码
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <poll.h>
  4. #include <unistd.h>
  5. int main() {
  6.     // 创建两个文件描述符,用于示例
  7.     int pipefds[2];
  8.     if (pipe(pipefds) == -1) {
  9.         perror("pipe");
  10.         exit(EXIT_FAILURE);
  11.     }
  12.     // 初始化 pollfd 结构数组
  13.     struct pollfd fds[2];
  14.     fds[0].fd = pipefds[0]; // 读端
  15.     fds[0].events = POLLIN;
  16.     fds[1].fd = STDIN_FILENO; // 标准输入
  17.     fds[1].events = POLLIN;
  18.     // 调用 poll
  19.     int ret = poll(fds, 2, -1); // 阻塞等待
  20.     if (ret == -1) {
  21.         perror("poll");
  22.         exit(EXIT_FAILURE);
  23.     }
  24.     // 检查结果
  25.     if (ret > 0) {
  26.         if (fds[0].revents & POLLIN) {
  27.             printf("Pipe read end is ready for reading\n");
  28.         }
  29.         if (fds[1].revents & POLLIN) {
  30.             printf("Standard input is ready for reading\n");
  31.         }
  32.     }
  33.     // 关闭文件描述符
  34.     close(pipefds[0]);
  35.     close(pipefds[1]);
  36.     return 0;
  37. }
复制代码
来源:新程序网络收集,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册