在IO过程中分为两个阶段:
等待
拷贝
内核将数据注备好之前,系统一直处于等待状态,等待完毕可以拷贝的时候称为就绪状态。
五种IO模型:
- 为了应付各种情况下提升效率,五种模型在等待阶段上存在差异。
1.阻塞IO
在内核将数据准备好之前,系统会一直等待,所有的套接字,默认都是阻塞等待。阻塞等待是最常见的IO模型。
2.非阻塞等待IO
如果内核为将数据准备好,系统调用仍然会直接返回,并且返回EWOULDBLOCK错误码。非阻塞IO往往需要程序员循环的方式反复读写文件描述符,这个过程成位轮询,这对CPU来说是比较大的浪费,一般只有特定的场景下使用。
3.信号驱动IO:
内核将数据准备好的时候,使用SIGIO信号通知程序进行IO操作
4.异步IO
由内核在数据拷贝完成时,通知应用程序(而信号驱动式应该告诉程序员可视开始拷贝数据)
5.IO多路复用(IO多路转接)
一个线程处理多个客户端的连接,将客户端之间的等待时间重叠
重要的IO概念:
同步通信和异步通信:
- 所谓同步就是在发出一个调用时,没有得到结果之前,该调用就不会,但是一旦调用返回,就得到返回值了。调用者主动等待调用的结果;
- 异步则恰恰相反,调用在发出去之后就直接返回了,所以返回没有结果。当一个异步过程调用发出后,调用者不会立刻得到结果,而是在调用发出之后,调用者通过状态,通知来通知调用者,或通过回调函数处理这个调用。
阻塞和非阻塞
- 阻塞调用是指调用结果返回之前,当前线程会被挂起,调用线程只有在得到结果之后才能返回。
- 非阻塞等待是指不能立刻得到返回结果之前,该调用不会阻塞当前线程。
- 为了应付各种情况下提升效率,五种模型在等待阶段上存在差异。
IO多路转换之select VS epoll
select
select实现网络字典- select系统调用是用来然我们的程序监视多个文件秒师符的状态变换的;
- 程序会停在select这里等待,直到被监视的文件描述符有一个挥着多个发送了状态改变;
select的特点
- 可监控的文件描述符个数取决与sizeof(fd_set)的值. 我这边服务器上sizeof(fd_set)=512,每bit表示一个文件描述符,则我服务器上支持的最大文件描述符是512*8=4096.
- 将fd加入select监控集的同时,还要再使用一个数据结构array保存放到select监控集中的fd,
- 一是用于再select 返回后,array作为源数据和fd_set进行FD_ISSET判断。
- 二是select返回后会把以前加入的但并无事件发生的fd清空,则每次开始select前都要重新从array取得
fd逐一加入(FD_ZERO最先),扫描array的同时取得fd最大值maxfd,用于select的第一个参数。
2.epoll
epoll实现网络字典
按照man手册的说法: 是为处理大批量句柄而作了改进的poll.
它是在2.5.44内核中被引进的(epoll(4) is a new API introduced in Linux kernel 2.5.44)
它几乎具备了之前所说的一切优点,被公认为Linux2.6下性能最好的多路I/O就绪通知方法.
epoll工作原理
epoll的优点(和 select 的缺点对应)
接口使用方便: 虽然拆分成了三个函数, 但是反而使用起来更方便高效. 不需要每次循环都设置关注的文
件描述符, 也做到了输入输出参数分离开数据拷贝轻量: 只在合适的时候调用 EPOLL_CTL_ADD 将文件描述符结构拷贝到内核中, 这个操作并不频繁(而select/poll都是每次循环都要进行拷贝)
事件回调机制: 避免使用遍历, 而是使用回调函数的方式, 将就绪的文件描述符结构加入到就绪队列中,
epoll_wait 返回直接访问就绪队列就知道哪些文件描述符就绪. 这个操作时间复杂度O(1). 即使文件描述
符数目很多, 效率也不会受到影响.没有数量限制: 文件描述符数目无上限
两者最本质的区别:
- epoll 采用回电方式通知就绪,当某个文件描述符就绪,就会立刻加入就绪队列中。
- select 采用遍历方式通知就绪。
epollde 两种工作模式
LT水平触发:代码写起来简单(默认方式)
E