(转)Linux网络编程(5):I/O模型

来源:互联网 发布:python实现rfm模型 编辑:程序博客网 时间:2024/06/01 09:18

    这一部分的内容本来应该作为第四部分内容,置于上一讲之中的。由于当时自己学习时也存在很大的困惑,边学边用,因此造成了知识体系的不连贯性。我们开始学习吧。

(1)什么是I/O复用(I/O multiplexing)呢?

        当你编写的程序需要同时处理多个描述符(socket、file、device),你又不知道什么时候(比方说有数据可以读了)应该去操作(读/写)哪个描述符。这时候我们就要用到I/O复用。其实,I/O复用是一种让进程预先“警告”内核能力,使得内核一旦发现进程预先告知时指定的一个或多个I/O条件(就是描述符)就绪(可以读/写了),内核就通知进程。
(2)I/O复用运用场合
1、如果一个TCP服务器既要处理监听套接字,又要处理已连接套接字,一般就要使用I/O复用;
2、当客户端处理多个描述符(通常是交互式输入和网络套接字)时,就必须使用I/O复用;
3、如果一个服务器既要处理TCP,又要处理UDP,一般就要使用I/O复用;
4、如果一个服务器要处理多个服务或多个协议,一般就要使用I/O复用。
(3)I/O模型
1、阻塞式I/O

        UDP函数recvfrom的内核到应用层、应用层到内核的调用过程是这样的:首先把描述符、接受数据缓冲地址、大小传递给内核,但是如果此时与该套接口相应的缓冲区没有数据,这个时候就recvfrom就会卡(阻塞)在这里,知道数据到来的时候,再把数据拷贝到应用层,也就是传进来的地址空间,如果没有数据到来,就会使该函数阻塞在那里,这就叫做阻塞I/O模型,如下图:


2、非阻塞式I/O

        如果recvfrom从应用层到内核的时候,如果该缓冲区没有数据的话,就直接给我返回,并且返回一个EWOULDBLOCK错误,一般都对非阻塞I/O模型进行轮询,就是一直在检查这个状态,看内核是不是有数据到来调用,过程如下图:


3、I/O复用(select和poll)

        设置一组套接字,如果这些套接字有一个以上出现了可读、可写、或者异常,select都会返回,这个时候,可以检查室哪个套接字状态达到了,因为select函数的套接字集是 值=结果 的,当select返回的时候,集合中的套接字是变化的,这个返回的套接字是满足要求的,通常程序的做法是,对想要了解的套接字,进行分开处理。使用select的好处是:能够等待多个套接字准备好。 使用select需要两个而不是单个系统调用,其优势在于我们可以等待多个描述符就绪。另外,与I/O复用密切相关的另一种I/O模型是在多线程中使用阻塞式I/O,它没有使用select阻塞在多个文件描述符上,而是使用多个线程(每个文件描述符一个线程),这样每个线程都可以自由地调用诸如recvfrom之类的阻塞式I/O系统调用了。


4、信号驱动式I/O

       当内核为我们准备好数据的时候,就会发送 SIGIO 信号,我们可以调用 sigaction 安装 SIGIO 信号的处理函数,这个时候就可以在 SIGIO 信号处理函数中进行 recvfrom 函数来接受数据报。


5、异步I/O

      让内核拷贝完之后通知我们。信号驱动I/O是当内核准备好数据的时候,通知我们可以调用recvfrom了,而异步I/O模型是内核通知我们I/O操作完成的时候通知我们。



参考资源:http://www.linuxidc.com/Linux/2012-08/66976.htm

0 0
原创粉丝点击