什么是 I/O?
I/O 可以理解为在内存和外设之间搬迁数据。而 I 就是将外设数据搬迁到内存, O 即将内存数据搬迁到外设。
一次 I/O 事件主要分两步,等数据和搬数据。
- 等数据:等数据就绪
- 搬数据:将就绪的数据从内存写到外设,或将数据从外设读到内存。
I/O 复用
I/O 复用是通过一种机制,可以监视多个描述符(或句柄),一但描述符有关心的时间就绪,既可以进行下一步搬数据。 本质任是同步 I/O ,都需要在事件就绪后自己负责进行数据的搬迁,也就是说这个搬迁过程是阻塞的,而效率之所以提高,是因为等待数据就绪的时间大大减少。
select 、poll
select :
- 其参数是输入输出型参数,每次调用都重新将添加关心的描述符集。
- 监视文件描述符有上限,默认只有1024。
- 每次调用都会在用户空间和内核空间之间拷贝 fd 集。
- 每次调用内核和开发者都要变量所有fd,复杂度 O(N),当数量很多时,开销比较大。
- 性能高于多线程或多进程版本。
poll :
- poll 解决的 select 的文件描述符上限问题,上限是最大可以打开文件的数目,这个数字一般远大于2048,举个例子,在1GB内存的机器上大约是10万左右,具体数目可以cat /proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大。。
- 同 select一样, 不论文件描述符是否就绪,都会将大量文件描述符的数组被整体复制于用户态和内核的地址空间之间。
- 将关心事件与发生事件在 不同的 event中,避免了像 select一样每次都要重新赋值。
- 每次调用内核和开发者都要遍历所有fd,复杂度 O(N),当数量很多时,开销比较大。
- 可以说poll是加强版的 select,其使用模型也十分相似。
epoll
epoll:
- 上限和 poll 一样,不再受限于文件描述符的限制。
- 不必在内核和用户空间多次拷贝fd 集合,只需要在使用前添加到集合即可,在不关心时删除即可。
- 内核操作描述符从线性的