Quantcast
Channel: Sam的技术Blog
Viewing all articles
Browse latest Browse all 158

Linux下IO多路复用Linux下的IO模型

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

0. Linux下的IO模型
I/O操作, I/O操作通常包括两个阶段:
A. 等待数据准备好。
B. 和内核交换数据。(读写)
对socket上的输入操作来说,
A步骤就是等待数据从网络中到达,此时,数据被存放在内核缓冲区。
B操作则是利用系统调用read, 把数据从内核缓冲区读取到应用程序层。

0.1: Linux下各I/O模型: 
Linux下的I/O模型有以下几种:
阻塞式I/O.
非阻塞I/O.
I/O复用。
信号驱动I/O。
异步I/O。

0.1.1: 阻塞式I/O模型
在低并发情况下,最常用的I/O模型,缺省条件下,所有Socket都是阻塞的。因为逻辑最清晰。

调用recvfrom ,read等系统调用时,如果数据还未准备好,就会一直阻塞,直到有了数据,并获取到数据才返回。

0.1.2: 非阻塞式I/O
在打开socket时,可以指定为非阻塞式I/O, 此时,会告知Kernel, 当数据没有准备好时,不要阻塞(进程不要被放入休眠队列)。 而是立刻返回错误码。

recvfrom调用时,若没有数据,则立刻返回EWOULDBLOCK. 若有数据,则反正Success,并复制数据。

0.1.3: I/O复用:
I/O复用的意思是: 多个设备同时监控,哪个设备准备好了,就对它进行数据处理和交换。
Linux2.4时代,有select() poll()两个系统调用。 linux2.6则引入了epoll.
select(), poll()本身是阻塞的。它们像Kernel注册要关注那些文件描述符的哪些状况(如有数据可读写,断连,异常)。 若发生注册的状况。则返回。此时调用对应系统调用来处理。
注意:阻塞是在select()或者poll()上,而非阻塞在I/O系统调用上。



它最大的优势,在于可以等待多个描述符就绪。


0.1.4: 信号驱动I/O。
可以用信号,让内核在描述符就绪时发送SIGIO信号通知我们。称为信号驱动式I/O .我们首先开启套接字的信号驱动式I/O功能,并通过sigaction系统调用安装一个信号处理函数。该系统调用将立即返回,我们的进程继续工作,也就是说它没有被阻塞。当数据报准备好读取时,内核就为该进程产生一个SIGIO信号。我们随后既可以在信号处理函数中调用recvfrom读取数据报,并通知主循环数据已准备好待处理。也可以立即通知循环,让它读取数据报。



         无论如何处理SIGIO信号,这种模型的优势在于等待数据报到达期间进程不被阻塞。主循环可以继续执行,只要等待来自信号处理函数的通知:既可以是数据已准备好被处理,也可以是数据报已准备好被读取。



0.1.5: 异步I/O
告知内核启动某个操作,并让内核在整个操作(包括将数据从内核复制到我们自己的缓冲区)完成后通知我们。这种模型与前一节介绍的信号驱动模型的主要区别在于:信号驱动I/O是由内核通知我们如何启动一个I/O操作,而异步I/O模型是由内核通知我们IO操作何时完成:











 

Viewing all articles
Browse latest Browse all 158

Trending Articles