MST

星途 面试题库

面试题:网络编程中poll机制在Linux系统下的数据结构及工作原理

请详细阐述在Linux操作系统中,poll机制所使用的数据结构以及它是如何工作的,包括如何添加监控的文件描述符、如何检测事件等。
13.4万 热度难度
后端开发网络编程

知识考点

AI 面试

面试题答案

一键面试

poll机制使用的数据结构

在Linux中,poll机制使用pollfd结构体来表示需要监控的文件描述符及其相关信息。该结构体定义在<poll.h>头文件中,通常形式如下:

struct pollfd {
    int fd;         /* 文件描述符 */
    short events;   /* 等待的事件 */
    short revents;  /* 发生的事件 */
};
  • fd:指定要监控的文件描述符。如果fd为负数,则events字段会被忽略,并且revents字段会被设置为0。
  • events:是一个位掩码,用于指定应用程序感兴趣的事件类型。常见的事件类型有POLLIN(数据可读)、POLLOUT(数据可写)、POLLPRI(有紧急数据可读)等。
  • revents:由内核在poll调用返回时设置,它也是一个位掩码,指示实际发生的事件。这些事件是events中请求的事件的子集。

poll机制的工作原理

  1. 添加监控的文件描述符 应用程序通过填充pollfd结构体数组,并将该数组作为参数传递给poll函数来添加需要监控的文件描述符。例如:
#include <poll.h>
#include <stdio.h>
#include <unistd.h>

#define MAX_FDS 10

int main() {
    struct pollfd fds[MAX_FDS];
    // 初始化fds数组,设置要监控的文件描述符和感兴趣的事件
    for (int i = 0; i < MAX_FDS; i++) {
        fds[i].fd = i; // 假设这里的文件描述符是0到9
        fds[i].events = POLLIN; // 只关心可读事件
    }

    int num_fds = MAX_FDS;
    int timeout = -1; // 无限期等待
    int ret = poll(fds, num_fds, timeout);
    if (ret > 0) {
        // 有事件发生,检查每个文件描述符的revents
        for (int i = 0; i < num_fds; i++) {
            if (fds[i].revents & POLLIN) {
                printf("File descriptor %d is readable\n", fds[i].fd);
            }
        }
    } else if (ret == 0) {
        printf("Timeout occurred\n");
    } else {
        perror("poll error");
    }

    return 0;
}
  1. 检测事件 poll函数会阻塞调用线程,直到以下情况之一发生:
    • 数组中的任何一个文件描述符上发生了请求的事件。在这种情况下,poll函数返回大于0的值,该值表示发生事件的文件描述符的数量。应用程序可以遍历pollfd数组,检查每个元素的revents字段,以确定具体发生了哪些事件。
    • 发生了信号中断。此时poll函数返回 -1,并且errno被设置为EINTR
    • 超时时间到(如果设置了非无限期的超时)。如果设置了超时时间(timeout参数大于0),并且在超时时间内没有任何事件发生,poll函数将返回0。

poll函数通过系统调用进入内核,内核会为每个文件描述符维护一个等待队列。当文件描述符的状态发生变化(例如有数据可读、可写等)时,内核会唤醒等待队列上的进程或线程,从而使得poll函数返回,应用程序可以处理相应的事件。