Linux网络编程学习(十一) ----- 五种I/O模式(第六章)

时间:2023-12-21 15:13:08

1、五种I/O模式是哪几个?

阻塞I/O,非阻塞I/O,I/O多路复用,信号驱动I/O(SIGIO),异步I/O

一般来讲程序进行输入操作有两个步骤,一是等待有数据可读,二是将数据从系统内核中拷贝到程序的数据集区。

对于一个套接字的数据操作,第一步就是等待数据从网络上传到本地,当数据包到达时,数据将会从网络层拷贝到内核的缓冲中,第二步就是从内核中将数据拷贝到程序的数据区中。

2、五种阻塞模式简介

1)阻塞I/O模式

套接字建立后默认的模式就是阻塞I/O模式,对于UDP而言,数据就绪的标志比较简单:已经收到了一整个数据报或者没有收到。比如说一个进程调用recvfrom()函数时,数据并有就绪,这个时候,进程将会等待数据就绪,数据到后拷贝到程序数据区,然后正常返回,所以,进程调用recvfrom()到该函数返回这段时间是阻塞的。

2)非阻塞I/O

一个套接字设置为非阻塞时,就相当于告诉内核"当我请求的I/O操作不能马上完成时,你想让我的进程休眠等待的时候,不要这么做,请马上返回一个错误给我"。就是调用recvfrom()时数据未就绪,这时内核立即返回一个错误给进程,所以非阻塞时,需要循环不停测试是否有数据可读,也就是polling,应用程序不停的polling内核来检查I/O操作是否就绪,这将极大浪费CPU资源

3)I/O多路复用

使用I/O多路技术时,调用select()或poll()函数,这时读取数据时先阻塞模式调用select()/poll(),也就是数据未就绪就等待直到数据就绪返回,然后调用recvfrom()函数将数据拷贝到程序缓冲区,和阻塞模式相比,还多调用了一个函数,但是多路复用优势在于select()可以等待多个套接字描述符,只要有一个就绪,select()函数就可以返回。

多路技术使用情况有:

  • 当一个客户端需要同时处理多个文件描述符的输入输出操作的时候(一般来说是标准的输入输出和网络套接字), I/O 多路复用技术将会有机会得到使用

  • 当程序需要同时进行多个套接字的操作的时候
  • 如果一个 TCP 服务器程序同时处理正在侦听网络连接的套接字和已经连接好的套接字

  • 如果一个服务器程序同时使用 TCP 和UDP 协议
  • 如果一个服务器同时使用多种服务并且每种服务可能使用不同的协议(比如inetd就是这样的)

4)信号驱动I/O模式

内核在文件描述符就绪的时候使用信号来通知进程,这种模式就是信号驱动I/O模式,首先需要允许套接字使用信号驱动I/O,还需要安装一个SIGIO的处理函数。这种模式下,系统调用将会立即返回,程序可以继续做其他事情,在数据就绪的时候发送一个SIGIO信号,这样在信号处理函数中进行I/O操作,有点像中断处理。优势在于等待数据时不会阻塞,程序可以做自己的时期,数据到达时发送SIGIO信号进行通知,很大的灵活性,不必为等待数据进行额外的编码。

信号驱动I/O操作使用前提:

  • 一个SIGIO信号的处理函数必须设定
  • 套接字拥有者必须被设定,一般使用fcntl函数的F_SETOWN参数来进行设定拥有者
  • 套接字必须被允许使用一部I/O,一般用fcntl函数的F_SETFL命令,O_ASYNC为参数来实现
  • 先调用信号是这号的SIGIO信号处理函数,然后使用fcntl函数设置套接字的属主

A.    UDP套接字的SIGIO信号:信号产生的时刻点,一是套接字收到了一个数据报的数据包,二是套接字发生了异步错误,使用UDP套接字异步I/O的时候,我们使用recvfrom()函数来读取数据报数据或是异步I/O错误信息

B.    TCP套接字的SIGIO信号:信号产生的时刻点很多,包括在一个监听了某个端口的套接字上成功建立了一个新的连接,一个断线的请求被成功初始化,一个断线的请求成功结束,套接字的某个通道被关闭,套接字接收到新数据,套接字将数据发送出去,发生了一个异步I/O错误

一个对信号驱动I/O 比较实用的方面是NTP(网络时间协议Network Time Protocol)服务器,它使用UDP。这个服务器的主循环用来接收从客户端发送过来的数据报数据包,然后再发送请求。对于这个服务器来说,记录下收到每一个数据包的具体时间是很重要的。因为那将是返回给客户端的值,客户端要使用这个数据来计算数据报在网络上来回所花费的时间。

5)异步I/O模式

异步I/O模式下,如果想进行I/O操作,只需要告诉内核我们要进行I/O操作,然后内核会马上返回。具体的I/O和数据拷贝全部由内核完成,我们的程序可以继续向下执行,当内核完成I/O操作和数据拷贝后,内核将通知我们的程序。其与信号驱动I/O区别是:信号驱动I/O模式下,内核在操作可以被操作的时候通知给我们的应用程序发送SIGIO信号,也就是在数据就绪的时候通知进程,完成数据拷贝后的步骤。而异步I/O模式下,内核在所有的操作都已经被内核操作结束后才通知应用程序,也就是在数据就绪以及数据拷贝完成后通知进程。

3. 几种I/O模式的比较

I/O模式 等待数据就绪 数据从内核拷贝到程序缓冲区
阻塞 初始化                 ----------------------->结束
非阻塞   检查/检查/检查/检查----------------------->结束
多路复用 检查----阻塞--->就绪                  初始化----->结束
信号驱动                                                信号通知  初始化----->结束
异步 初始化                                                                 信号通知

4.带外数据

带外数据是一种可以快速的通知网络的另一端计算机信息的一种方法.带外数据甚至可以只告诉远程计算机它的存在而不必将它的具体数据传输过去.带外数据并不是建立两个连接来传送数据(至少在TCP 中不是这样),它是将所谓的"带外数据"影射到已经存在的套接字连接中