关于什么是I/O多路复用,在知乎上有个很好的回答,能够参考罗志宇前辈的回答
记录下本身的理解:忘记这个坑爹的中文翻译。记住I/O multiplexing
linux
I/O multiplexing 这里面的 multiplexing 指的实际上是在单个线程经过记录跟踪每个Sock(I/O流)的状态来同时管理多个I/O流.
I/O多路复用这一技术。简单来讲,就是一个线程追踪多条io流(读,写,异常),但不使用轮询,而是由设备自己告知程序哪条流可用了,这样一来就解放了cpu,也充分利用io资源,下文主要讲解如何实现这一技术,linux下这一技术有三个实现,select,poll,epoll。数组
阻塞I/O模式下,内核对于I/O事件的处理是阻塞或者唤醒,而非阻塞模式下,咱们能够经过循环把集合中的流从头至尾问一遍,这样就能够处理多个流了,但这样的作法显然很差,由于若是全部流都没有数据,那么只会白白浪费CPU.
为了不CPU空转,能够引进了一个代理(一开始有一位叫作select的代理,后来又有一位叫作poll的代理,不过二者的本质是同样的)。这个代理比较厉害,能够同时观察许多流的I/O事件,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有I/O事件时,就从阻塞态中醒来,因而咱们的程序就会轮询一遍全部的流安全
此种方法与select类似,不做介绍函数
#include <sys/select.h> /** *select将更新这个集合,把其中不可读的套节字去掉只保留符合条件的套节字在这个集合里面 */ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
参数readfds、writefds、exceptfds都是指向文件描述符的指针,数据类型为fd_set。而readfds是用来检测输入的,writefds是用来检测输出的,exceptfds使用检测是否异常的。有关fd_set一般有四个宏供咱们操做:FD_ZERO、FD_SET、FD_CLR、FD_ISSET。spa
文件描述符集合有一个最大容量限制,由常量FD_SETSIZE来决定,在Linux上,该常量值为1024。
参数timeout为超时时间。线程
#include <stdio.h> #include <unistd.h> #include <sys/select.h> int main(void) { int bytes_read, ready; char buffer[128]; fd_set readfds; struct timeval timeout; FD_ZERO(&readfds); FD_SET(STDIN_FILENO, &readfds); timeout.tv_sec = 10; timeout.tv_usec = 0; ready = select(STDIN_FILENO+1, &readfds, NULL, NULL, &timeout); if (ready) { bytes_read = read(STDIN_FILENO, buffer, sizeof(buffer)); if (buffer[bytes_read - 1] == '\n') buffer[bytes_read - 1] = '\0'; printf("%s\n", buffer); } else { printf("No data to read\n"); } return 0; }
因为I/O Multiplexing->select存在如下问题翻译
所以14年后(1997)出现了POLL,修复select的如下问题设计
#include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int timeout); struct pollfd{ int fd; //文件描述符 short events; //等待的事件 short revents; //实际发生的事件 };
每一个pollfd结构体指定了一个被监视的文件描述符。第一个参数是一个数组,即poll函数能够监视多个文件描述符。每一个结构体的events是监视该文件描述符的事件掩码,由用户来设置。revents是文件描述符的操做结果事件,内核在调用返回时设置。events中请求的任何事件均可能在revents中返回3d
问题:使用select,咱们有O(n)的无差异轮询复杂度,随着处理的流越多,无差异轮询时间就越长
此时epoll产生,epoll能够理解为event poll,不一样于(select/poll)无差异轮询,epoll之会把哪一个流发生了怎样的I/O事件通知咱们。此时咱们对这些流的操做都是有意义的。代理