当调用poll函数时,内核会遍历所有需要监测的文件描述符,并将其添加到一个等待队列中。
当有事件发生时,内核会遍历等待队列上的文件描述符,检查是否有事件发生。
当有事件发生的文件描述符被找到时,内核会通过修改poll函数的返回值,告知应用程序哪些文件描述符有事件发生。
应用程序通过遍历poll函数返回的结构体数组,找到有事件发生的文件描述符,并进行相应的处理。
当调用epoll_create函数时,内核会创建一个epoll对象,并返回一个文件描述符,该文件描述符用于对epoll对象进行操作。
当调用epoll_ctl函数时,我们可以将需要监测的文件描述符添加到epoll对象中。
当调用epoll_wait函数时,内核会等待事件发生,并将发生事件的文件描述符添加到一个就绪队列中。
应用程序通过调用epoll_wait函数获取就绪队列上的事件,利用返回的文件描述符进行相应的处理。
与poll不同,为了避免遍历所有需要监测的文件描述符,epoll采用事件驱动的方式,只需要遍历就绪队列上的文件描述符即可。
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;
}