一、select()
1.1、处理流程
1、创建文件描述符集合 fd_set
2、添加文件描述符到集合中 int FD_ISSET(int fd, fd_set *set);
3、通知内核开始监测 select
4、内核返回的结果(两个结果,1、是那种类型得文件),做对应得操作(对IO读、写操作)
1.2、函数接口
(1)select()函数接口
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
功能:检查多了IO
参数:
nifds:最大文件描述符+1(方便内核查找)
readfds 关注读事件的文件描述符集合
writefds:关注的写事件的文件描述符集合
exceptfds:其他异常文件描述符的集合
timeout:超时时间,等到了这个时间到了,就不在死等了,如果不设置超时时间,则设置为NULL
代参宏
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);
返回值
成功:返回到达事件的个数(因为IO端口事件可能同时到达)
失败L:-1设置了超时时间:超时时间到达但没有时间,返回0
文件描述符的范围 0~1023
二、epoll()
2.1、流程
创建文件描述符集合
添加文件描述符到集合
通知内核开始监测
根据返回的结果做对应的操作,对io读,写操作
2.2、epoll函数
epoll:
1、创建文件描述符集合:(在内核中)
函数接口
#include <sys/epoll.h>
int epoll_create(int size);告诉内核大概放多少个文件描述符
返回值:
成功:返回一个文件描述符(集合句柄)
失败:-1
2、添加文件描述符到集合
#include <sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd, struct epoll_event*event);
参数:
epfd :文件描述符集合句柄
op :
EPOLL_CTL_ADD:向集合中添加文件描述符
EPOLL_CTL_MOD:修改集合
EPOLL_CTL_DEL:删除文件描述符
EPOLL_CTL_DEL(集合,对象)
删除的时候不需要关注他具体做什么操作
fd:文件描述符
struct epoll_event *event:
对这个文件描述符所对应的事件做什么操作
struct epoll_event {
uint32_t events; /* Epoll events */
EPOLLIN 读操作
EPOLLOUT 写操作
epoll_data_t data; /* User data variable */
typedef union epoll_data {
void *ptr;
int fd;//设置读事件或者写事件的关注的文件描述符
uint32_t u32;
uint64_t u64;
} epoll_data_t;
返回值
成功:返回0
失败:返回-1或者errno
3、通知内核开始监测
#include <sys/epoll.h>
int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
功能:监测IO事件
参数:
epfd:文件描述符集合句柄
events:保存最终的结果,的数组的首地址(a)
maxevents: 监测时事件的个数
timeout :超时时间
-1:设置超时时间
返回值:
成功:返回到达事件的个数
失败:返回-1
超时时间结束:0
三、三者的特点
3.1、select
1.select监听文件描述符最大个数为1024(数组)时间复杂度为0(n)
2.select监听的文件描述符集合在用户层,需要应用层和内核层互相传递数据
3.select需要循环遍历一次才能找到产生的事件
4.select只能工作在水平触发模式(低速模式)无法工作在边沿触发模式(高速模式)
3.2、poll
1.监测文件描述符不受上限限制(链表)O(n)
2.监听的文件描述符集合在用户层,需要内核层向用户层传递数据
3.需要循环遍历一次才能找到产生的事件
4.只能工作在水平触发模式(低速模式)无法工作在边沿触发模式(高速模式)
3.3、epoll
创建内核事件表,不受到文件描述符上限限制(红黑树)
监听的事件表在内核中,直接在内核中监测事件效率高
epol1会直接获得产生事件的文件描述符的信息,而不需要遍历检测
epo11既能工作在水平触发模式,也能工作在边沿触发模式
四、 应用场景
IO多路复用只用一个进程
耗时比较大;不适合处理比较耗时的任务
应用场景
1、构建并发服务器,用来检测多个客户端套接字
2、使用io多路复用监测多个IO所对应的通信(如:网络、串口、can)
3、在阻塞io中,进行超时监测
实际上是在一个进程中监测多个io的读和写
五、注意
- linux一切皆文件
- 并发量比较小的时候,三者之间的区别不大
- 只有并发量比较大的时候,epoll才体现优势