嵌入式开发之IO多路复用(一)
目录
1、IO模型和多路复用模型
1.1、阻塞I/O模式
1.1.1、读阻塞
1.1.2、写阻塞
1.2、非阻塞模式I/O
1.3、信号驱动I/O
1.4、多路复用I/O
1.4.1、IO多路复用步骤:
1.4.2、伪代码示例讲解
1、IO模型和多路复用模型
在UNIX、Linux下主要有4种I/O模型:
- 阻塞I/O: 最常用
- 非阻塞I/O:可防止进程阻塞在I/O操作上,需要沦陷
- I/O多路复用:允许同时对多个I/O进行控制
- 信号驱动I/O:一种异步通信模型
1.1、阻塞I/O模式
在阻塞模式下,如果设备不可读写,进程会休眠等待,此时CPU资源会被释放给其他进程使用。当设备可读写时,进程被唤醒继续执行。
阻塞I/O模式是最普遍使用的I/O模式,大部分程序使用的都是阻塞模式的I/O。
缺省情况下,套接字建立后所处于的模式就是阻塞I/O模式。
前面学习的很多读写函数在调用过程中会发生阻塞。
- 读操作中的read、recv、recvfrom
- 写操作中的write、send,但是sendto不阻塞
- 其他操作:accept、connect
1.1.1、读阻塞
以read函数为例:
- 进程调用read函数从套接字上读取数据,当套接字的接收缓冲区中还没有数据可读,函数read将发生阻塞。
- 他会一直阻塞下去,等待套接字的接收缓冲区中有数据可读。
- 经过一段时间后,缓冲区内接收到数据,于是内核便去唤醒该进程,通过read访问这些数据。
- 如果在进程阻塞过程中,对方发生故障,那这个进程将永远阻塞下去。
1.1.2、写阻塞
- 在写操作时发生阻塞的情况要比读操作少。主要发生在要写入的缓冲区的大小小于要写入的数据量的情况下。
- 这时,写操作不进行任何拷贝工作,将发生阻塞。
- 一量发送缓冲区内有足够的空间,内核将唤醒进程,将数据从用户缓冲区中拷贝到相应的发生数据缓冲区。
- UDP不用等待确认,没有实际的发送缓冲区,所以UDP协议中不存在发送缓冲区满的情况,在UDP套接字上执行的写操作永远都不会阻塞(sendto)。
1.2、非阻塞模式I/O
- 当我们将一个套接字设置为非阻塞模式,我们相当于告诉了系统内核:"当我请求的I/O操作不能够马上完成,你想让我的进程进行休眠等待的时候,不要这么做,请马上返回一个错误给我"。
- 当一个应用程序使用了非阻塞模式的套接字,它需要使用一个循环来不停地测试是否一个文件描述符有数据可读(称作polling)。
- 应用程序不停的polling内核来检查是否I/O操作已经就绪。这将是一个极浪费CPU资源的操作。
- 这种模式使用中不普遍。