多个IO复用一个进程,不创建新进程和线程,效率高
不适合处理比较耗时的任务
应用场景:
1. 构建并发服务器,使用IO多路复用监测多个客户端套接字
2. 使用io多路复用监测多个IO所对应的通信(如:网络、串口、can....)
3. 在阻塞io中,进行超时监测
select
poll
epoll
select模型:
1. 创建文件描述符集合 fd_set
2. 添加文件描述符到集合中 void FD_SET(int fd, fd_set *set);
3. 通知内核开始监测 select
4. 根据返回的结果做对应的操作(对io读、写操作)
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
功能:监测多路IO
参数:
nfds : 关注的文件描述符中的最大值+1
readfds:关注的读事件的文件描述符集合
writefds:关注的写事件的文件描述符结合
exceptfds:其他 异常
timeout : 超时时间,超时后不再阻塞,如果不设置:NULL
返回值:
成功:返回到达事件的个数
失败:-1
设置了超时时间:超时时间到达但没有事件,返回0
void FD_CLR(int fd, fd_set *set); 删除关注的文件描述符
int FD_ISSET(int fd, fd_set *set); 判断集合中文件描述符是否置1
void FD_SET(int fd, fd_set *set); 添加关注的文件描述符到集合中
void FD_ZERO(fd_set *set); 清空集合
select实现TCP并发服务器
epoll模型:
1. 创建文件描述符集合 int epoll_create(int size);
2. 添加文件描述符到集合中 epoll_ctl()
3. 通知内核开始监测 epoll_wait()
4. 根据返回的结果做对应的操作(对io读、写操作)
epoll_create
int epoll_create(int size);
功能: 创建一个监听事件表(内核中)
参数: size:监听事件最大个数
返回值: 成功返回非负值:表示epoll事件表对象(句柄),失败返回-1
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
功能:
参数: epfd:文件描述符集合句柄
op: EPOLL_CTL_ADD: 向集合中添加文件描述符
EPOLL_CTL_MOD: 修改集合
EPOLL_CTL_DEL :删除文件描述符
fd :操作的文件描述符
event :文件描述符所对应的事件
event : EPOLLIN : 读操作
EPOLLOUT : 写事件
int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
功能:监测IO事件
参数:
epfd : 文件描述符集合句柄
events : 保存到达事件的结合的首地址
maxevents : 监测时事件的个数
timeout:超时时间
-1 :不设置超时时间
返回值:
成功:返回到达事件的个数
失败:-1
设置超时:超时时间到达返回0
epoll实现TCP并发服务器
1.select
缺点:
1.select监听文件描述符最大个数为1024 (数组) O(n)
2.select监听的文件描述符集合在用户层,需要应用层和内核层互相传递数据
3.select需要循环遍历一次才能找到产生的事件
4.select只能工作在水平触发模式(低速模式)无法工作在边沿触发模式(高速模式)
2.poll
缺点:
1.poll监测文件描述符不受上限限制 (链表) O(n)
2.poll监听的文件描述符集合在用户层,需要内核层向用户层传递数据
3.poll需要循环遍历一次才能找到产生的事件
4.poll只能工作在水平触发模式(低速模式)无法工作在边沿触发模式(高速模式)
3.epoll
优点:
1.epoll创建内核事件表,不受到文件描述符上限限制 (红黑树) O(logn)
2.epoll监听的事件表在内核中,直接在内核中监测事件效率高
3.epoll会直接获得产生事件的文件描述符的信息,而不需要遍历检测
4.epoll既能工作在水平触发模式,也能工作在边沿触发模式