本文共 2803 字,大约阅读时间需要 9 分钟。
io复用使得程序能同时监听多个文件描述符,对提高程序的性能非常重要。一般在以下场合经常用到IO复用技术.
1、客户端要同时处理多个socket。 2、客户端要同时处理输入和网络连接。 3、tcp 服务器要同时处理监听sokcet 和 连接socket。 4、服务器要同时处理tcp 和udp 请求。 4、服务器要同时监听多个端口,或处理多个任务。#include#include #include int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
下面有几个在添加文件描述符和删除文件描述符的过程中常用到的函数
// 在 fd_set 结构体中清除 fd 描述符 void FD_CLR(int fd, fd_set *set); // 判断是否设置了fd 文件描述符 int FD_ISSET(int fd, fd_set *set); //设置文件描述符 fd void FD_SET(int fd, fd_set *set); //结构体fd_set 清空 void FD_ZERO(fd_set *set);
#includeint ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, const sigset_t *sigmask);
struct pollfd { int fd; /* file descriptor */ short events; /* requested events */ short revents; /* returned events */};
fd 需要监听的文件描述符
events 注册的事件,告诉poll 需要监听的事件 revents 程序实际发生的事件编号 | 事件 |
---|---|
POLLRDNORM | 有普通数据可读 |
POLLRDBAND | 有优先数据可读 |
POLLPRI | 有紧迫数据可 |
POLLIN | 有数据可读 |
POLLOUT | 写数据不会导致阻塞 |
POLLWRNORM | 写普通数据不会导致阻 |
POLLWRBAND | 写优先数据不会导致阻塞 |
POLLMSGSIGPOLL | 消息可用。 |
POLLER | 指定的文件描述符发生错误。 |
POLLHUP | 指定的文件描述符挂起事件。 |
POLLNVAL | 指定的文件描述符非法。 |
epoll 是内核特有的IO 复用函数,epoll 使用一组函数来完成任务而不是使用一个。
epoll_create#includeepoll_create(int size); //size参数现在并不起作用,而是告诉给内核一个提示,告诉内核文件表需要多大 //该函数返回一个文件描述符,指向一个内核事件表
epoll_ctl
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
编号 | 事件 |
---|---|
EPOLL_CTL_ADD | 往事件表中注册事件 |
EPOLL_CTL_MOD | 修改fd上注册的事件 |
EPOLL_CTL_DEL | 删除fd 上注册的事件 |
typedef union epoll_data { void *ptr; int fd; __uint32_t u32; __uint64_t u64; } epoll_data_t; struct epoll_event { __uint32_t events; /* Epoll events */ epoll_data_t data; /* User data variable */ };
epoll_wait
//返回值表示监听到的事件中,就绪事件的个数int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
三种IO函数的相同点
都能同时监听多个文件描述符,都将有timeout 指定超时时间,直到一个或多个文件描述符有事件发生的时候返回,返回值为就绪的文件描述符的个数,返回0表示没有就绪事件,等待时间超过了timeout 指定的时间三种IO函数的不同点
系统调用 | select | poll | epoll |
---|---|---|---|
事件集合 | 用户通过三个参数感兴趣的可读,可写、异常等事件,内核通过对这些事件的修改,来反馈其中的就绪事件,这使得用户每次调用倒要重新传入这三个参数 | 统一处理所有事件的类型,因此只需要传入一个事件集参数,用户通过pollfd.events 来 传入感兴趣的事件,内核通过pollfd.revents 来反馈就绪的事件 | 内核通过一个事件表直接管理用户感兴趣的所有事件,因此每次调用epoll_wait时,不需要重复传入用户感兴趣的事件,epoll_wait 调用的epoll_events 仅仅用用来反馈就绪的事件 |
应用程序索引文件描述符的事件复杂度 | O(n) | O(n) | O(1) |
最大文件描述符数 | 一般有最大限制 | 65535 | 65535 |
工作模式 | LT | LT | 支持ET高效模式 |
内核实现与工作效率 | 采用轮询方法检测就绪事件 算法时间复杂读O(n) | 采用轮询方法检测就绪事件 算法时间复杂读O(n) | 采用回馈方法检测就绪事件 算法时间复杂读O(1) |
转载地址:http://vxnwi.baihongyu.com/