我们看到TCP客户同时处理两个输入:标准输入和TCP套接字。我们遇到的问题是就在客户阻塞于(标准输入上)fgets调用,服务器进程会被杀死。服务器TCP虽然正确的给客户TCP发送了一个FIN,但是既然客户进程正阻塞于从标准输入读入的过程,它将看不到这个EOF,直到从套接字读时为止(可能额已过了很长时间)。这样的进程需要一种预先告知内核的能力,使得内核一旦发现进程指定的一个或多个I/O条件就绪(也就是说输入已准备好被读入,或者描述符已能承接更多的输出),它就通知进程。这个能力称为I/O复用,是由select和poll这两个函数支持的。
I/O复用典型使用在下列网络应用场合:
当客户处理多个描述符(通常是交互式输入和网络套接字)时,必须使用I/O复用;
如果一个TCP服务器即要处理监听套接字,又要处理已连接套接字,一般使用I/O复用;
一个客户同时处理多个套接字时可能的,不过比较少见;
如果一个服务器即要处理TCP,又要处理UDP,一般就要使用I/O复用。
如果一个服务器要处理多个服务或者多个协议,一般就要使用I/O复用。
I/O复用并非只限于网络编程,许多重要的应用程序也需要使用这项技术。
UNIX下可用的5种I/O模型的基本区别:
1.阻塞式I/O;
2.非阻塞式I/O;
3.I/O复用(select和poll);
4.信号驱动式I/O(SIGIO);
5.异步I/O(POSIX的aio_系列函数)
一个输入操作通常包括两个不同的阶段:
(1)等待数据准备好;
(2)从内核向进城复制数据。
对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达。当所等待分组到达时,它被复制到内核中的某个缓冲区。第二步就是把数据从内核缓冲区复制到应用进程缓冲区。
1.阻塞式I/O模型
我们在前面所说的I/O模型都是阻塞I/O,即调用recv系统调用,如果没有数据则阻塞等待,当数据到来则将数据从内核空间(套接口缓冲区)拷贝到用户空间(recv函数提供的buf),然后recv返回,进行数据处理。
查看本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/OS/unix/