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