Unix下可用的5种I/O模型:
阻塞I/O
非阻塞I/O
I/O复用(select和poll)
信号驱动I/O(SIGIO)
异步I/O(POSIX的aio_系列函数)
一个输入操作通常包括两个不同的阶段:
1)等待数据准备好;
2)从内核向进程复制数据;
对于一个套接字的输入操作,第一步通常涉及等待数据从网络中到达。当所等待分组到达时,它被复制到内核中某个缓冲区。第二步就是把数据从内核缓冲区复制到应用进程缓冲区。
阻塞I/O
最流行的I/O模型是阻塞式I/O(blocking I/O) 模型,默认情况下,所有的套接字都是阻塞的。
阻塞调用是指调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,在这个状态下,cpu不会给线程分配时间片,即线程暂停运行)。函数只有在得到结果之后才会返回。
以数据包套接字为例,如图
进程调用recvfrom,其
系统调用直到数据报到达且被
拷贝到应用进程的缓冲区或者发生错误才返回。最常见的错误是系统调用被信号中断。我们说进程从调用recvfrom开始到它返回的整段时间内是被阻塞的,recvfrom成功返回后,进程开始处理数据报。
非阻塞I/O
非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。
进程把一个套接口设置成非阻塞是在通知内核:当所请求的I/O操作非得把本进程投入睡眠才能完成时,不要把本进程投入睡眠,而是返回一个错误。
前三次调用recvfrom 时没有数据可返回,因此内核转而立即返回一个EWOULDBLOCK 错误。第四次调用 recvfrom 时已有一个数据报准备好,它被复制到应用程序缓冲区,于是recvfrom 成功返回。我们接着处理数据。
当一个应用进程像这样对一个非阻塞描述符循环调用 recvfrom 时,我们称之为轮询(polling)。应用程序持续轮询内核,以查看某个操作是否就绪。这样做往往耗费大量CPU 时间。
I/O复用
主要可以调用
select和epoll;对一个IO端口,两次调用,两次返回,
比阻塞IO并没有什么优越性;关键是能实