select、poll、epoll都是IO多路复用。
I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。
select的缺点
每次调用select,都需要将进程加入到所有fd的等待队列,每次唤醒都需要从每个队列中移除; 每次都需要将fd集合从用户态传递给内核;进程被唤醒后,程序并不知道哪些fd就绪,还需要再比遍历一次;
因为遍历开销较大,默认只能监视1024个fd
poll
poll 和 select相似,只是fd集合的方式不同,但是解决了select文件描述符的最大上限
epoll(eventpoll)
功能分离, 将等待队列和阻塞进程分开。
create-创建结构体(eventpoll),ctl-增删fd, wait-唤醒
新增就绪队列
内核维护一个就绪列表,引用就绪的fd,就能避免一次遍历
epoll工作方式:创建eventpoll, 通过ctl增删fd,若fd就绪后,调用回到函数将就绪fd放入就绪列表中,并唤醒在wait中进入睡眠的进程(select 和poll 不断轮询是否有就绪fd) ,wait只需判定列表是否为空,不需要遍历整个fd。
select 和 poll 每次进行等待状态时,都需要将进程挂载在所有监视fd的等待列表里;fd就绪时再解挂
参考:
Epoll原理 https://blog.csdn.net/armlinuxww/article/details/92803381
select、poll、epoll优缺点 https://blog.csdn.net/qq_35433716/article/details/82588619