网络编程之五种I/O模型




一.概述:

在网络编程中,阻塞、非阻塞、同步、异步经常被提到,下面我先谈以下我所理解的在I/O中的阻塞、非阻塞、同步、异步。

五种I/O模型分别是阻塞式I/O,非阻塞式I/O,信号驱动,I/O复用(这四种是同步I/O),异步I/O。

我来举一个例子来解释这五种I/O模型:

有A,B,C,D,E五个人在钓鱼:
A用的是最老式的鱼竿,所以呢,得一直守着,等到鱼上钩了再拉杆。(阻塞式I/O)

B呢,它的鱼竿比较新,不怕鱼上钩后把鱼竿拽走,所以他一边看手机,一边时不时看一下鱼竿是否有鱼上钩,有的话就迅速拉鱼竿。(非阻塞式I/O)

C的鱼竿有个功能,能够显示是否有鱼上钩,所以呢,B就和旁边的MM聊天,隔会再看看有没有鱼上钩,有的话就迅速拉杆。(信号驱动)

D用的鱼竿和C差不多,但他想了一个好办法,就是同时放好几根鱼竿,然后守在旁边,一旦有显示说鱼上钩了,它就将对应的鱼竿拉起来;(I/O复用)

E是个有钱人(有钱人了不起啊),干脆雇了一个人帮他钓鱼,一旦那个人把鱼钓上来了,就给E发个短信。(异步I/O)

下面我先谈以下我所理解的在I/O中的阻塞、非阻塞、同步、异步。




二.I/O操作过程:

首先,进行I/O操作涉及到了硬件,所以就会和操作系统打交道。(从网卡这两个读取/发送数据到网络中是操作系统做的)所以,先解释以下我理解的I/O过程(总的来说是   等数据 和  数据搬迁   这两个过程)

首先,通过系统给我们的API函数调用I/O操作(此时在用户态),这个函数先等待I/O缓存中有数据,操作系统会监测I/O缓存(此时在内核态),当I/O缓存中接收到数据时,操作系统先通知这个函数调用(进入用户态),然后这个函数的实现中会调用一些已经包装好的函数,“ 这些 ”函数会把数据从内核中拷贝到用户缓存区(先到内核态,再到用户态),然后这个函数就会返回。

具体如下图:




三.I/O操作中的阻塞、非阻塞、同步、异步:

(1).同步:同步就是在一个功能调用时,在这个调用没有得到结果之前,这个调用不会返回。(在I/O操作中,如调用read函数,这个函数会被阻塞在read函数调用处,但内核一直在做与read相关的事情,也就是这个函数是激活的(会占用cpu),只是从表面上看函数还没有返回而已)。

(2).阻塞:阻塞调用就是调用一个函数,这个调用结果没有得到结果之前,执行这个函数的线程会被挂起(这个状态下,cpu不会给该函数分配时间片),直到得到结果后才返回。

(3).非阻塞:是指如果一个函数不能立刻得到结果,这个函数不会阻塞该线程而立即返回。

(4).异步:是指在一个功能调用时,这个调用不会立即得到结果,也不会阻塞该线程,这个调用所在的线程会继续执行其它事情,而这个功能是由其它执行部件来完成,当这个部件执行完该功能时,通过状态,通知来通知调用者,或通过回调函数处理这个调用。

执行部件和调用者可以通过三种途径返回结果:
a.   状态、
b.   通知、
c.   回调函数。
使用哪一种依赖于执行部件的实现,除非执行部件提供多种选择,否则不受调用者控制。

a. 如果执行部件用状态来通知,
    那么调用者就需要每隔一定时间检查一次,效率就很低

b. 如果是使用通知的方式,
    效率则很高,因为执行部件几乎不需要做额外的操作。

c. 至于回调函数,
    和通知没太多区别。




四.五种I/O模型:(理解了上面的知识,下面应该比较容易理解了)

(1).阻塞式I/O:

应用程序调用一个IO函数,导致应用程序阻塞,等待数据准备好。 如果数据没有准备好,一直等待….数据准备好了,从内核拷贝到用户空间,IO函数返回成功指示。

如下图:

(2).非阻塞式I/O:

在非阻塞I/O中,一定要把一个I/O操作函数放在一个死循环中,直到这个I/O函数返回一个正确值时才跳出这个循环。

我们把一个SOCKET接口设置为非阻塞就是告诉内核,当所请求的I/O操作无法完成时,不要将线程睡眠,而是返回一个错误。这样我们的I/O操作函数将不断的测试数据是否已经准备好,如果没有准备好,继续测试,直到数据准备好为止。在这个不断测试的过程中,会大量的占用CPU的时间。

如下图:

(3).信号驱动:

首先要允许接口进行信号驱动I/O,然后安装一个信号处理函数,线程继续运行并不阻塞。当数据准备好时,线程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。

如下图:

(4).I/O复用:

I/O
复用模型会用到select、poll、epoll函数,这几个函数也会使进程阻塞,但是和阻塞I/O所不同的,这几个函数可以同时阻塞多个I/O操
作。而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写时,才真正调用I/O操作函数。(比阻塞式I/O并没有上面优越性,但它实现了对多个I/O端口的监听)

如下图:

(5).异步I/O:

当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者的输入输出操作。

如下图:




六.五种I/O模型比较:




七.总结:

理解五种I/O模型应该先理解I/O操作过程,并理解阻塞,非阻塞,同步,异步的一些知识。

I/O操作要和硬件打交道,所以会I/O操作过程会涉及到操作系统。

处理I/O操作分为两个过程,一是等待数据,二是把数据从内核中搬到用户空间。

这五中I/O模型的不同之处是在等待数据的方式上,在第二个过程中是一样的,都是把数据从内核中搬到用户空间,然后进行相关操作。

时间: 2024-10-13 04:00:30

网络编程之五种I/O模型的相关文章

Linux网络编程 五种I/O 模式及select、epoll方法的理解

Linux网络编程 五种I/O 模式及select.epoll方法的理解 web优化必须了解的原理之I/o的五种模型和web的三种工作模式 五种I/O 模式--阻塞(默认IO模式),非阻塞(常用语管道),I/O多路复用(IO多路复用的应用场景),信号I/O,异步I/OLinux网络编程 五种I/O 模式及select.epoll方法的理解

(50)LINUX应用编程和网络编程之五 Linux信号(进程间通信)

信号实现进程间的通信 3.5.1.什么是信号 3.5.1.1.信号是内容受限(只是一个int型的数字)的一种异步通信机制 (1)信号的目的:用来通信(进程与进程之间的通信) (2)信号是异步的(对比硬件中断),信号好像就是一种软件中断. (3)信号本质上是int型数字编号(事先定义好的) 3.5.1.2.信号由谁发出 (1)用户在终端按下按键 (2)硬件异常后由操作系统内核发出信号 (3)用户使用kill命令向其他进程发出信号 (4)某种软件条件满足后也会发出信号,如alarm闹钟时间到会产生S

unix网络编程几种模型比较

1.阻塞式IO:套接字默认是阻塞式的,该模型会一直阻塞在系统调用上,直到数据到达内核区并且完成从内核区到用户进程区的数据拷贝. 2.非阻塞式IO:该模型将套接字的状态设置为非阻塞,会一直轮询套接字的状态,直到数据到达内核区并且完成内核区到用户区的数据拷贝,个人感觉类似于linux下的自旋锁. 3.IO复用:该模型通常阻塞在select/poll系统调用,当内核区数据到达时,select系统调用返回,再次调用recvfrom等系统调用同步完成内核区到用户区的数据拷贝 4.信号驱动IO:当数据到达内

linux编程---网络编程之复用I/O模型

模型一:阻塞模型---进程效率低:CPU利用低 模型二:非阻塞模型---进程效率高:但是CPU利用率低: 模型三:复用I/O模型---CPU利用率提高 思想:对于任何一个套接字描述符发生事件时才由系统去唤醒进程,从而不需要因轮询而占用CPU: 对于I/O复用典型的应用如下: (1)当客户处理多个描述字时(一般是交互式输入和网络套接口),必须使用I/O复用. (2)当一个客户同时处理多个套接口时,而这种情况是可能的,但很少出现. (3)如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,

Windows 网络编程(2)--重叠I/0模型

5).重叠I/O模式(overlapped) 常用函素: 1.WSASocket : 创建套接字 2.TCP WSASend WSARecv 3.UDP: WSASendTo WSARecvFrom 4.AccepEx (Mswsock.lib库导出) WSAIoctl 5.数据类型 WSAOVERLAPPED (wsaoverlapped) 函数: WSAGetOverlappedResult 使用: 缓冲区对象 typedef struct _BUFFER_OBJ { OVERLAPPED

Linux 系统应用编程——网络编程(利用TCP/IP 模型分析数据传输过程)

TCP/IP参考模型是一个非常基础,而且也非常重要的基础框架,要想入门数通这是个必须掌握的基本概念,本文档通过一个简单的示例,结合参考模型来分析一下数通的基本过程. 网络环境非常简单,如下图所示,我们现在来分析一下PC去访问Webserver的WEB服务,整个数据通信过程是如何发生的,为了简化描述,我们这里暂时忽略DNS.ARP.帧校验等等机制的工作细节,只考虑较为宏观的层面. 1)PC访问WebServer的WEB服务,实际上是访问Webserver的HTTP服务.这个过程对于人来说,就是在P

Windows网络编程--选择(select)模型

选择模型是I/O模型中最简单的一个.Server端通过创建两个套接字集合fdOld和fdNew,在循环中通过事件添加和移除未决IO套接字句柄.测试的时候先启动服务端再启动客户端. 以下为Server端源代码(在VS2010下测试通过): #include "stdafx.h"#include<WinSock2.h>#include<Windows.h> #include<iostream> #pragma comment(lib,"ws2_

linux socket网络编程详解

一.系统调用和应用编程接口 在讨论网络通信之前, 首先明确两个概念:系统调用(system call) 和 应用编程接口(Application Programming Interface,API). 操作系统使用 系统调用 机制来实现 在应用程序 与 操作系统 之间进行控制权传递. 当某个应用进程启动了系统调用时,控制权就从应用程序传递给操作系统.操作系统执行某个内部过程之后,把控制权返回给应用程序. 对程序员来说,每一个系统调用和一般程序设计中的函数调用非常相似,只是系统调用是将控制权传递给

Unix网络编程中的五种I/O模型_转

转自:Unix网络编程中的的五种I/O模型 下面主要是把unp第六章介绍的五种I/O模型. 1. 阻塞I/O模型 例如UDP函数recvfrom的内核到应用层.应用层到内核的调用过程是这样的:首先把描述符.接受数据缓冲地址.大小传递给内核,但是如果此时 该与该套接口相应的缓冲区没有数据,这个时候就recvfrom就会卡(阻塞)在这里,知道数据到来的时候,再把数据拷贝到应用层,也就是传进来的地址空 间,如果没有数据到来,就会使该函数阻塞在那里,这就叫做阻塞I/O模型,如下图: 2. 非阻塞I/O模