网络编程(五)——poll和epoll

poll原理:


当调用poll函数时,内核会遍历所有需要监测的文件描述符,并将其添加到一个等待队列中。

当有事件发生时,内核会遍历等待队列上的文件描述符,检查是否有事件发生。

当有事件发生的文件描述符被找到时,内核会通过修改poll函数的返回值,告知应用程序哪些文件描述符有事件发生。

应用程序通过遍历poll函数返回的结构体数组,找到有事件发生的文件描述符,并进行相应的处理。

epoll原理:

当调用epoll_create函数时,内核会创建一个epoll对象,并返回一个文件描述符,该文件描述符用于对epoll对象进行操作。

当调用epoll_ctl函数时,我们可以将需要监测的文件描述符添加到epoll对象中。

当调用epoll_wait函数时,内核会等待事件发生,并将发生事件的文件描述符添加到一个就绪队列中。

应用程序通过调用epoll_wait函数获取就绪队列上的事件,利用返回的文件描述符进行相应的处理。

与poll不同,为了避免遍历所有需要监测的文件描述符,epoll采用事件驱动的方式,只需要遍历就绪队列上的文件描述符即可。

epoll相较于poll的优势主要体现在:

CPU效率:epoll使用事件驱动的方式,只有在有事件到达时才会遍历,节省了CPU资源。而poll需要遍历所有需要监测的文件描述符。

内存复制:epoll返回文件描述符而不是复制数据,避免了poll每次返回数据时需要进行内存复制的开销。

文件描述符数量:epoll支持打开的文件描述符数量更大,不会随着文件描述符数目的增长而降低效率。


总的来说,poll和epoll都是为了实现I/O多路复用提供的机制,但epoll相对于poll在性能上有更好的表现。因此,在高性能的网络编程中,epoll被广泛使用。

poll和epoll是Linux系统中的两种I/O多路复用机制。

poll结构体的定义

struct pollfd {
    int fd;           // 文件描述符
    short events;     // 监控的事件
    short revents;    // 实际发生的事件
};


poll的使用示例:

#include 
#include 
#include 
#include 

#define TIMEOUT_MS 5000

int main() {
    struct pollfd fds;
    int ret;

    fds.fd = STDIN_FILENO;    // 监控标准输入
    fds.events = POLLIN;      // 监控可读事件

    ret = poll(&fds, 1, TIMEOUT_MS);
    if (ret == -1) {
        perror("poll");
        return 1;
    }

    if (ret == 0) {
        printf("Timeout\n");
    }

    if (fds.revents & POLLIN) {
        printf("Data is available now.\n");
    }

    return 0;
}


epoll结构体的定义:

struct epoll_event {
    __uint32_t events;  // epoll事件类型
    epoll_data_t data;  // 用户数据
};

typedef union epoll_data {
    void *ptr;
    int fd;
    __uint32_t u32;
    __uint64_t u64;
} epoll_data_t;

epoll的使用示例:

#include 
#include 
#include 
#include 

#define MAX_EVENTS 5

int main() {
    struct epoll_event event, events[MAX_EVENTS];
    int epoll_fd, event_count;

    // 创建epoll实例
    epoll_fd = epoll_create1(0);
    if (epoll_fd == -1) {
        perror("epoll_create1");
        return 1;
    }

    // 监听标准输入可读事件
    event.events = EPOLLIN;
    event.data.fd = STDIN_FILENO;

    // 将标准输入添加到epoll监控列表
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, STDIN_FILENO, &event) == -1) {
        perror("epoll_ctl");
        return 1;
    }

    while (1) {
        event_count = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
        if (event_count == -1) {
            perror("epoll_wait");
            return 1;
        }

        printf("Events occurred: %d\n", event_count);

        for (int i = 0; i < event_count; i++) {
            if (events[i].data.fd == STDIN_FILENO) {
                printf("Data is available now.\n");
                char buf[256];
                fgets(buf, sizeof(buf), stdin);
                printf("Read: %s", buf);
            }
        }
    }

    return 0;
}


你可能感兴趣的:(嵌入式学习,网络编程,网络)