Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO
背景
整理之前学习socket编程的时候复习到了多路复用,搜索了有关资料,了解到多路复用也有局限性,本着打破砂锅问到底的精神,最终找到了关于IO模型的知识点。
在《Unix网络编程》一书中提到了五种IO模型,分别是:阻塞IO、非阻塞IO、多路复用IO、信号驱动IO以及异步IO。
我们在这里就介绍并实现这5种模型。介绍之前,请允许我引用某段比喻
阻塞IO, 给女神发一条短信, 说我来找你了, 然后就默默的一直等着女神下楼, 这个期间除了等待你不会做其他事情, 属于备胎做法.
非阻塞IO, 给女神发短信, 如果不回, 接着再发, 一直发到女神下楼, 这个期间你除了发短信等待不会做其他事情, 属于专一做法.
IO多路复用, 是找一个宿管大妈来帮你监视下楼的女生, 这个期间你可以些其他的事情. 例如可以顺便看看其他妹子,玩玩王者荣耀, 上个厕所等等. IO复用又包括 select, poll, epoll 模式. 那么它们的区别是什么?
1) select大妈 每一个女生下楼, select大妈都不知道这个是不是你的女神, 她需要一个一个询问, 并且select大妈能力还有限, 最多一次帮你监视1024个妹子
2) poll大妈不限制盯着女生的数量, 只要是经过宿舍楼门口的女生, 都会帮你去问是不是你女神
3) epoll大妈不限制盯着女生的数量, 并且也不需要一个一个去问. 那么如何做呢? epoll大妈会为每个进宿舍楼的女生脸上贴上一个大字条,上面写上女生自己的名字, 只要女生下楼了, epoll大妈就知道这个是不是你女神了, 然后大妈再通知你.
上面这些同步IO有一个共同点就是, 当女神走出宿舍门口的时候, 你已经站在宿舍门口等着女神的, 此时你属于阻塞状态接下来是异步IO的情况:
你告诉女神我来了, 然后你就去打游戏了, 一直到女神下楼了, 发现找不见你了, 女神再给你打电话通知你, 说我下楼了, 你在哪呢? 这时候你才来到宿舍门口。 此时属于逆袭做法
阻塞IO 与 非阻塞IO
在Linux 系统编程中,我们 在 有关概念 章节中介绍了阻塞的概念。那么也很容易理解什么是阻塞IO与非阻塞IO。直接看图
阻塞IO
最传统的一种IO模型,即在读写数据过程中会发生阻塞现象。
当用户线程发出IO请求之后,内核会去查看数据是否就绪,如果没有就绪就会等待数据就绪,而用户线程就会处于阻塞状态,用户线程交出CPU。当数据就绪之后,内核会将数据拷贝到用户线程,并返回结果给用户线程,用户线程才解除block状态。
sequenceDiagram
title : 阻塞IO
participant application
participant kernel
Note right of application: 应用程序调用系统调用
application ->> kernel: recv()
kernel ->> kernel: 判断数据是否就绪(否则等待)
kernel ->> kernel: 准备好数据,拷贝到用户空间
kernel ->> application: 拷贝完成,唤醒应用程序
代码如下:
printf("Calling recv(). \n");
ret = recv(socket, recv_buf, sizeof(recv_buf), 0);
printf("Had called recv(). \n");
也许有人会说,可以采用多线程+ 阻塞IO 来解决效率问题,但是由于在多线程 + 阻塞IO 中,每个socket对应一个线程,这样会造成很大的资源占用,并且尤其是对于长连接来说,线程的资源一直不会释放,如果后面陆续有很多连接的话,就会造成性能上的瓶颈。
非阻塞IO
当用户线程发起一个IO操作后,并不需要等待,而是马上就得到了一个结果。如果结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送IO操作。一旦内核中的数据准备好了,并且又再次收到了用户线程的请求,那么它马上就将数据拷贝到了用户线程,然后返回。
在非阻塞IO模型中,用户线程需要不断地询问内核数据是否就绪,也就说非阻塞IO不会交出CPU,而会一直占用CPU。
对于非阻塞IO就有一个非常严重的问题,在while循环中需要不断地去询问内核数据是否就绪,这样会导致CPU占用率非常高,因此一般情况下很少使用while循环这种方式来读取数据。
sequenceDiagram
title : 非阻塞IO
participant application
participant kernel
Note right of application: 应用程序调用系统调用
application ->> kernel: fread
kernel ->> kernel: 数据未就绪
kernel ->> application: 返回EAGAIN
application ->> application: 判断返回值
application ->> kernel: fread
kernel ->> kernel: 准备好数据,拷贝到用户空间
kernel ->> application: 拷贝完成,返回成功
代码如下:
while(1)
{
printf("Calling recv(). \n");
ret = recv(socket, recv_buf, sizeof(recv_buf), 0);
if (EAGAIN == ret) {continue;}
else if(ret > -1) { break;}
printf("Had called recv(), retry.\n");
}
Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO的更多相关文章
- Linux 网络编程的5种IO模型:多路复用(select/poll/epoll)
Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 背景 我们在上一讲 Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO中,对于其中的 阻塞/非阻塞IO 进行了 ...
- Linux 网络编程的5种IO模型:信号驱动IO模型
Linux 网络编程的5种IO模型:信号驱动IO模型 背景 上一讲 Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 我们讲解了多路复用等方面的知识,以及有关例程. ...
- Linux 网络编程的5种IO模型:异步IO模型
Linux 网络编程的5种IO模型:异步IO模型 资料已经整理好,但是还有未竟之业:复习多路复用epoll 阅读例程, 异步IO 函数实现 背景 上一讲< Linux 网络编程的5种IO模型:信 ...
- Netty学习第三章 Linux网络编程使用的I/O模型
一.同步阻塞IO:blocking IO(BIO) 1.过程分析: 当进程进行系统调用时,内核就会去准备数据,当数据准备好后就复制数据到内核缓冲器,复制完成后将数据拷贝到用户进程内存,整个过程都是阻塞 ...
- IO模型《三》非阻塞IO
非阻塞IO(non-blocking IO) Linux下,可以通过设置socket使其变为non-blocking.当对一个non-blocking socket执行读操作时,流程是这个样子: 从图 ...
- 【Linux 网络编程】OSI七层模型
OSI(Open System Interconnection)开放系统互联模型(1)应用层: 应用层与应用程序界面沟通,以达到展示给用户的目的.(2)表示层: 表示层对网络传输的数据进行交换,使得多 ...
- 【Linux 网络编程】TCP/IP四层模型
应用层.传输层.网络层.链路层 链路层:常用协议 ARP(将物理地址转化为IP地址) RARP(将IP地址转换为物理地址) 网络层(IP层):重要协议ICMP IP IGMP 传输层:重要的协议TCP ...
- Linux 网络编程(IO模型)
针对linux 操作系统的5类IO模型,阻塞式.非阻塞式.多路复用.信号驱动和异步IO进行整理,参考<linux网络编程>及相关网络资料. 阻塞模式 在socket编程(如下图)中调用如下 ...
- linux网络编程IO模型
同步与异步: 同步就是一个任务的完成需要依赖另外一个任务时,只有等待被依赖的任务完成后,依赖的任务才能算完成. 异步是不需要等待被依赖的任务完成,只是通知被依赖的任务要 ...
随机推荐
- Activiti工作流系统环境搭建
一.创建Activiti工程,并导入Activiti包及数据库驱动包 二.用代码方式创建 流程引擎 1 @Test 2 public void createProcessEngineWithCode( ...
- Go-err is shadowed during return
where? Go程序函数中在通过 return关键字返回的时候,报错 why? 变量作用域的问题,在子作用域定义一个上层作用域的同名的变量 package main import ( "e ...
- Feedforward neural networks前馈神经网络
Feedforward neural networks or deep feedforward networks or multilayer perceptrons Pass input throug ...
- JD-GUI反编译jar包为Java源代码
程序员难免要借鉴其他java工程的代码.可有时只能拿到.calss文件,jar包或者war包,这个时候要求程序员能熟练的将这些类型文件反编译为Java代码并形成可编译运行的项目.本文介绍的反编译工具是 ...
- MDK内的KEEP关键字以及$$Base $$Limit
使用mdk编程,假如有一个有用的函数你定义了但是没有显式的调用,mdk在默认方式下,将会把这个函数从整个程序总删除掉,以节省ROM. 比如,你在ROM的0x00002000处定位了一个函数,假设为vo ...
- [iTyran原创]iPhone中OpenGL ES显示3DS MAX模型之一:OBJ格式分析
[iTyran原创]iPhone中OpenGL ES显示3DS MAX模型之一:OBJ文件格式分析作者:yuezang - iTyran 在iOS的3D开发中常常需要导入通过3DS MAX之类 ...
- 如何学习iOS开发?iOS Developer Library足矣!
记得上高中的时候,寄信请教二哥学习经验,二哥来信介绍学习经验说:资料书要快速阅读,把书上的题做完,然后再买几套资料书(习题集)继续练习. 这是二哥的经验,因为他自学能力强,可以消化多套资料书. 我仿照 ...
- 排序算法:归并排序(Merge Sort)
归并排序 归并排序采用了分治策略(divide-and-conquer),就是将原问题分解为一些规模较小的相似子问题,然后递归解决这些子问题,最后合并其结果作为原问题的解. 归并排序将排序数组A[1. ...
- 【题解】[USACO12JAN]Video Game G
第一道\(AC\)自动机\(+DP.\) 首先,一个自动机上\(DP\)的套路是设\(dp[i][j]\)表示长度为\(i\)匹配到\(j\)节点的最优得分. 那么,由于我们已经建好了\(Trie\) ...
- vue 下载jquery 下载layui-layer 下载vue-router
1.下载jquery cmd:语句 npm install jquery 然后在main.js文件里面写 import $ from 'jquery' 2.下载layui-layer 在vue里面的l ...