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_系列函数)

阻塞式I/O模型:

阻塞式I/O模型是用的比较多的一种I/O模型。socket的默认状态是阻塞的,即就是发出一个不能立即完成的套接字调用时,该进程被睡眠,直到相应的调用操作完成。可能会发生阻塞的套接字调用有以下几种可能:

  • 1.输入操作(read、readv、recv、recvfrom和recvmsg函数),进程调用这几个函数时读取套接字缓冲区,没有数据可读就会进入睡眠状态,直到有数据到达为止。
  • 2.输出操作(write、writev、send、sendto和sendmsg函数),对于一个tcp套接字,内核将从应用进程的缓冲区中复制数据到该套接字的发送缓冲区,若发送缓冲区没有可用空间,进程将被睡眠,直到有可用空间为止。
  • 3.接受外来连接(accept函数),默认调用accept函数,若无新的连接到达时,调用进程一直处于阻塞(睡眠)状态。
  • 4.发起外出连接(即TCP的connect函数),进程调用connect函数也就是建立一个TCP连接的过程,涉及TCP/IP的三次握手,connect函数只有在收到对端对于自己连接请求SYN的确认ACK时才返回。

以recvfrom函数调用阻塞为例,有如下图过程; 
 
从进程开始调用recvfrom函数时就开始阻塞,直到recvfrom成功返回后(也就是直到数据报到达且被复制到应用进程的缓冲区中(用户空间)或者发生错误),应用进程接收到数据开始处理。recvfrom最常见的错误就是系统调用被信号中断。

非阻塞式I/O模型:

非阻塞I/O就是将套接字设置成非阻塞的(可使用fcntl函数完成),在可能发生阻塞的套接字函数相应操作不能满足时(阻塞是将进程投入睡眠),不让进程进入睡眠状态,而是返回一个EWOULDBLOCK错误。这种方式可以让我们周期性的检查某个或者多个文件描述符上是否可执行I/O操作。 
非阻塞I/O方式周期性的轮询也是存在一些问题的,若轮询的间隔时间较长的话,则应用程序相应I/O事件可能会出现非常大的延时;如果延时间隔很小的话,又会浪费CPU时间。 
如下图所示,为一个非阻塞I/O模型过程图: 
 
调用recvfrom函数时,没有数据准备好,内核立即返回一个EWOULDBLOCK错误,进程反复轮询(polling),直到已有数据准备好,内核将数据拷贝至用户空间进程缓冲区,recvfrom函数返回。

相比于非阻塞I/O的局限性,接下来的I/O复用和信号驱动I/O方式往往更可取。

I/O复用模型:

I/O复用是一种让进程预先告知内核的能力,使得内核一旦发现进程指定的一个或多个I/O条件就绪(如可以读/写了),内核就通知进程。主要有4中函数支持,select、poll、pselect和epoll。调用这几个函数,阻塞在这四个系统调用的某一个之上,而不是阻塞在真正的I/O系统调用上,如下图所示:

 
阻塞于select,等待多个套接字中的一个变为可读,内核数据准备好,select返回可读条件,然后调用recvfrom把所读数据报复制到应用进程缓冲区中。

信号驱动I/O模型:

信号驱动式I/O是指进程预先告知内核,在某个描述符上发生某事时,让内核发送SIGIO信号通知相关进程。大致过程如下图: 
 
开启套接字的信号驱动I/O功能,sigaction系统调用安装信号处理函数成功则返回,进程继续工作(即就是不阻塞)。当数据报准备好读取时,内核就产生一个SIGIO信号调用信号处理函数使用recvfrom读取数据。

针对一个套接字使用信号驱动式I/O要求进程执行以下3个步骤: 
(1)建立SIGIO信号的信号处理函数。 
(2)设置该套接字的属主,通常使用那个fcntl的F_SETOWN设置。 
(3)开启该套接字的信号驱动式I/O,通常使用fcntl的F_SETFL打开O_ASYNC标志完成。

当同时检查大量的文件描述符时,信号驱动I/O相比select()和poll(0有显著的性能提升。

异步I/O模型:

告知内核启动某个操作,并让内核在整个操作完成后通知进程。信号驱动式I/O是由内核通知进程何时可以启动一个I/O操作,而异步I/O模型是由内核通知进程I/O操作何时完成。 
 
调用aio_read函数给内核传递描述符、缓冲区指针、缓冲区大小和文件偏移,并告知内核当整个操作完成时如何通知进程。

一个输入操作通常包括两个不同的阶段: 
(1) 等待数据准备好; 
(2) 从内核向进程复制数据。 
对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达。当所等待分组到达时,它被复制到内核中的某个缓冲区。第二步就是把数据从内核缓冲区复制到应用进程缓冲区。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值