linux select

ddatsh

dev linux #c

标准输入上等待输入事件

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>

int main() {
    fd_set read_fds;        // 读文件描述符集合
    struct timeval timeout; // 超时时间结构体

    int max_fd = 1; // 文件描述符的最大值
    int result;

    while (1) {
        FD_ZERO(&read_fds);           // 清空文件描述符集合
        FD_SET(STDIN_FILENO, &read_fds); // 将标准输入添加到文件描述符集合

        timeout.tv_sec = 5;  // 设置超时时间为5秒
        timeout.tv_usec = 0;

        // 使用 select 函数检查文件描述符集合上是否有可读事件
        result = select(max_fd, &read_fds, NULL, NULL, &timeout);

        if (result == -1) {
            perror("select");
            exit(EXIT_FAILURE);
        } else if (result == 0) {
            // 超时,可以在这里添加相应的处理逻辑
            printf("Timeout occurred!\n");
            fflush(stdout);
        } else {
            // 文件描述符上有可读事件发生
            if (FD_ISSET(STDIN_FILENO, &read_fds)) {
                char buffer[1024];
                // 从标准输入读取数据
                ssize_t bytesRead = read(STDIN_FILENO, buffer, sizeof(buffer));

                if (bytesRead == -1) {
                    perror("read");
                    exit(EXIT_FAILURE);
                } else if (bytesRead == 0) {
                    // EOF,表示输入结束
                    printf("End of file reached. Exiting...\n");
                    break;
                } else {
                    // 处理读取到的数据,这里简单地将其输出
                    printf("Read from stdin: %.*s", (int)bytesRead, buffer);
                    fflush(stdout);
                }
            }
        }
    }

    return 0;
}
  1. fd_set为 bitmap 结构,且有长度为 1024 的限制
// select.h
typedef struct {
   ...
__fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];   
   ...
} fd_set;
/* Number of descriptors that can fit in an `fd_set'.  */
#define __FD_SETSIZE   1024
  1. fdset 无法做到重用,每次循环必须重新创建

  2. 频繁的用户态和内核态拷贝,性能开销较大

  3. 需要对文件描述符表进行遍历,O(n) 的轮询时间复杂度