我要投搞

标签云

收藏小站

爱尚经典语录、名言、句子、散文、日志、唯美图片

当前位置:万喜彩票 > 反向复用 >

IO常见模型-详解io多路复用

归档日期:04-30       文本归类:反向复用      文章编辑:爱尚语录

  对于一个network IO(这里我们以read举例),它会涉及到两个系统对象:

  在linux中,默认情况下所有的socket都是blocking, 一个典型的读流程大概是这样的:

  当用户进程调用了recvfrom这个系统调用,kernel就开始了IO的第一个阶段: 准备数据(对于网络IO来说,很多时候数据在一开始还没有到达.比如,还没有收到一个完整的UDP包.这个时候kernel就要等待足够的数据到来). 这个过程需要等待,也就是说数据被拷贝到操作系统内核的缓冲区是需要一个过程的.

  而用户进程这边,整个进程会被阻塞(当然,是进程自己选择的阻塞).当kernel一直等到数据准备好了,它就会将数据从kernel拷贝到用户内存,然后kernel返回结果,用户进程才解除block的状态,重新运行起来.

  当用户进程发出read操作时,如果kernel中的数据还没有准备好,那么它并不会block用户进程,而是立即返回一个error.从用户进程角度来讲,它发起一个read操作后,并不需要等待,而是马上就得到一个结果.用户进程判断结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送read操作.一旦kernel中的数据准备好了,并且又再次收到用户进程的system call, 那么它马上就将数据拷贝到用户内容, 然后返回.

  所以,nonblockingIO的特点是用户进程需要不断的主动询问kernel数据好了没有

  值得注意的是,此时的非阻塞IO只是应用到等待数据上,当真正有数据到达执行的时候,还是同步阻塞IO来的,从途中的 copy data from kernel to user 可以看出

  select/epoll的优势并不是对单个连接能处理的更快,而是在于能处理更多的连接

  当用户进程调用了select,那么整个进程会被block,而同时,所有进来的连接socket,都会加入到select监视列表里面,由kernel会’监视’所有select负责的socket,而之后select(poll, epoll等)函数会不断的轮训所负责的所有socket,这些socket都是非阻塞的存在与select的监视列表,select使用某种监视机制检查某个socket是否有数据到达了,当任何一个socket中的数据准备好了,select就会返回.这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程.

  I/O多路服用的特点是通过一种机制一个进程能同事等待多个文件描述符,而这些文件描述符(套接字描述符)其中的任意一个进入就读就绪状态,select()函数就可以返回.

  所有,IO多路服用,本质上不会有并发的功能,因为任何时候还是只有一个进程或者线程在进行工作,它之所以能提高效率是因为select/epoll把进来的socket放到它们’监视’的列表里面,当任何socket有可读可写数据立马处理.select/epoll手里同事检测着很多socket,一有动静马上返回给进程处理,总比一个一个socket过来,阻塞等待,处理的效率高

  当然也可以多线程/多进程方式,一个连接过来开一个进程/线程处理,这样消耗的内存和进程切换会耗掉更多的系统资源.

  所以,我们可以结合IO多路复用和多进程/多线程来提高性能并发,IO服用负责提高接受socket的通知效率,收到请求后,交给进程池/线程池来处理逻辑

  用户进程发起read操作后,立即就可以开始去做其它的事. 而另一方面,从kernel的角度,当它收到一个asynchronous read之后,首先它会立即返回,所以不会对用户进程产生任何block. 然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发一个signal,告诉它read操作完成了.

  阻塞调用是指调用结果返回之前,当前线程会被挂起. 调用线程只有在得到结果之后才会返回.非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程.

  例子: 你打电话问书店老板有没有深入理解计算机操作系统这本书, 如果你是阻塞式调用,你会一直把自己’挂起’,直到得到这本书有还是没有的这个结果, 如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边玩去了,当然你也要偶尔过几分钟check一下老板有没有返回结果. 在这里阻塞与非阻塞与是否同步异步无关.跟老板通过什么方式回答你结果无关.

  阻塞IO会一直block住对应的进程直到操作完成,而非阻塞在kernel还在准备数据的情况下会立刻返回

  同步和异步关注的是**消息通信机制(synchronous communication/asynchronous communication)**所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回.但是一旦调用返回,就得到返回值了.换句话,就是由调用者主动等待这个调用的结果. 而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果.换句话,当一个异步过程调用发出后,调用者不会立刻得到结果.而是在调用发出来后,被调用者通过状态,通知等来通知调用者,或通过回调函数处理这个调用.

  举个通俗的例子: 你打电话问书店老板有没有深入理解计算机操作系统这本书,如果是同步通讯机制,书店老板会说,你稍等一下,‘我查一下’,然后开始查呀查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果).而异步通讯机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果).然后查好了,他会主动打电话给你. 这里老板通过’回电’这种方式来回调.

  在说明同步IO和异步IO的区别之前,需要先给出两者的定义.Stevens给出的定义(其实是POSIX的定义)是这样子的:

  两者的区别就在于同步IO做’IO operation’的时候会将process阻塞.按照这个定义,之前所述的阻塞IO,非阻塞IO,IO复用都属于同步IO.

  有人可能会说,非阻塞IO并没有被block啊.这里有个非常’狡猾’的地方,定义中所指的’IO operation’是指真实的IO操作,就是例子中的recvfrom这个system call. 非阻塞IO在执行recvfrom这个system call的时候,如果kernel的数据没有准备好,这时候会不block进程.但是,当kernel中数据准备好的时候,recvfrom会将数据从kernel拷贝到用户内存中,这个时候进程是被block了,在这段时间内,进程是被block的.

  而异步IO则不一样,当进程发起IO操作之后,就直接返回再也不理睬了,知道kernel发送一个信号,告诉进程说IO已经完成. 在这个过程中,进程完全没有被block.

  B的鱼竿有个功能,能显示是否有鱼上钩,所以呢,B就和旁边的MM聊天,个会再次看看有没有鱼上钩,有的话就迅速拉杆;

  C用的鱼竿和B差不多,但他想到了一个好办法,就是同时放好几根鱼竿,让后找一个小孩来帮他看着,一旦有显示说鱼上钩了,小孩就告诉它哪个鱼竿上钩了,C就将对应的鱼竿拉起来;

  D是个有钱人,干脆雇了一个人帮他钓鱼,一旦那个人把鱼钓上来了,就给D发短信.

  select, poll, epoll本质都是同步IO(自己阻塞这,将准备好的数据,从kernel拷贝到自己的进程中),因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞.

  Select/Poll/Epoll都是IO复用的实现方式, 上面说了使用IO复用,会把socket设置成non-blocking,然后放进Select/Poll/Epoll各自的监视列表里面,那么,他们的对socket是否有数据到达的监视机制又分别是怎么样的?效率又如何?我们应该使用那种方式实现IO复用比较好?下面列出他们各自的实现方式,效率,优缺点:

  select, poll实现需要自己不断轮询所有fd集合,知道设备就绪,期间可能要睡眠和唤醒多次交替. 而epoll其实也需要调用epoll_wait不断轮训就续链表,期间也可能多次睡眠和唤醒交替,但是它是设备就绪时,调用回调函数,把就绪fd放到就绪链表中,并唤醒在epoll_wait总会给你进入睡眠的进程.虽然都要睡眠和交替,但是select和poll在’醒着’的时候都要遍历整个fd集合,而epll’醒着’的时候只要判断一下就绪链表是否为空就行了,这节省了大量的CPU时间. 这就是回调机制带来的性能提升.

  select, poll每次调用都要把fd集合从用户态往内核态拷贝一次,并且要把current往设备等待队列中挂一次,而epoll只要一次拷贝,而且把current往等待队列上也只挂一次(在epoll_wait的开始,注意这里的等待队列并不是设备等待队列只是一个epoll内部定义的等待队列).这也能节省不少的开销.

  老李去火车站买票,隔12小时去火车站问有没有退票,三天后买到一张票。耗费:往返车站6次,路上6小时,其他时间做了好多事。

  老李去火车站买票,委托黄牛,然后每隔6小时电话黄牛询问,黄牛三天内买到票,然后老李去火车站交钱领票。

  老李去火车站买票,委托黄牛,黄牛买到后即通知老李去领,然后老李去火车站交钱领票。

  老李去火车站买票,给售票员留下电话,有票后,售票员电话通知老李,然后老李去火车站交钱领票。

  老李去火车站买票,给售票员留下电话,有票后,售票员电话通知老李并快递送票上门。

  服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种:(1)同步阻塞IO(Blocking IO):即传统的IO模型。(2)同步非阻塞IO(Non-blocking IO):默认创建的soc...博文来自:怪盗基德

  select select:开始是1983年的时候出现在4.2BSD中,用select可以让程序监视多个文件句柄(filedescriptor)的状态,当被监视的文件句柄有某一个或多个发生状态改变时,...博文来自:ni_day_e的博客

  这是网上找到的比较全的ReidsIO多路复用资料,此部分其实和Redis的键失效机制有一定的衔接。最近在看UNIX网络编程并研究了一下Redis的实现,感觉Redis的源代码十分适合阅读和分析,其中I...博文来自:Happy_wu的专栏

  高性能IO模型浅析 服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种:(1)同步阻塞IO(Blocking IO):即传统的IO模型。(2)同步非阻塞IO(Non-blocking IO...博文来自:baixiaoshi的专栏

  在I/O编程过程中,当需要同时处理多个客户端接入请求时,可以利用多线程或者I/O多路复用技术进行处理。I/O多路复用技术通过把多个I/O的阻塞复用到同一个select的阻塞上,从而使得系统在单线程的情...博文来自:junli_chen的博客

  一、什么是socket?什么是I/O操作?我们都知道unix(like)世界里,一切皆文件,而文件是什么呢?文件就是一串二进制流而已,不管socket,还是FIFO、管道、终端,对我们来说,一切都是文...博文来自:sherry0k的博客

  参考及网络编程卷1第6章网络IO模型详细分析常见的IO模型有阻塞、非阻塞、IO多路复用,异步。以一个生动形象的...博文来自:leiting_imecas的博客

  一、IO多路复用定义IO多路复用允许应用在多个文件描述符上阻塞,并在某一个可以读写时通知,一般遵循下面的设计原则:、IO多路复用:任何文件描述符准备好IO时进行通知在文件描述符就绪前进行睡眠。唤醒:哪...博文来自:mr253727942的专栏

  注:本文是对众多博客的学习和总结,可能存在理解错误。请带着怀疑的眼光,同时如果有错误希望能指出。同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案是...博文来自:京东放养的爬虫

  五种IO模型在冯诺依曼计算机体系结构中,输入输出设备是其中的两大组件,那么今天我们就来谈谈计算机中IO(输入输出)模型IO分为阻塞IO、非阻塞IO、信号驱动IO、IO多路转接、异步IO阻塞IO阻塞IO...博文来自:GangStudyIT的博客

  转载:、基本概念IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。IO多路复用适用如下场...博文来自:sinat_35297665的博客

  最近在看UNIX网络编程并研究了一下Redis的实现,感觉Redis的源代码十分适合阅读和分析,其中I/O多路复用(mutiplexing)部分的实现非常干净和优雅,在这里想对这部分的内容进行简单的整...博文来自:吹雪的专栏

  03-08阅读数 615假如我调用了一个select函数,并且关注了几个描述字,select函数就会一直阻塞直到我关注的事件发生.假如当有套接口可读时,select函数就返回了,告诉我们套接口已经可读,然后我们去读这个套接口...

  IO多路复用(多线.简述本篇文章延续上一篇网络编程基础(3):IO多路复用(单线程)之内容,做出了进一步的改善。IO复用网路模型中的角色Handler,将以状态模式(StatePattern)实现,并且将Handle...博文

  使用poll实现的io多路复用服务端和客户端。客户端通过子进程创建多个客户端连接。客户端每隔1秒向服务端发送一个时间戳,服务端接收到时间戳以后,保存在本地的文件中,一个客户端对应一个存储文件,并将接收...博文

  pollpoll的机制与select类似,与select在本质上没有多大差别,管理多个描述符也是进行轮询,根据描述符的状态进行处理,但是poll没有最大文件描述符数量的限制。poll和sele...

  感觉很好的一片文章,转载了 一、             主流程几乎所有的服务器程序的工作模式都是:(1)      初始化一些参数;(2)      开启监听socket;(3)      在主线程...博文

  本文基于Linux2.6.32内核版本。一、基本概念IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。IO多路复用适用如下场合:(1)当客户处理多个描述字时(...博文

  事件驱动模型协程:遇到IO操作就切换。 但什么时候切回去呢?怎么确定IO操作完了? 很多程序员可能会考虑使用“线程池”或“连接池”。“线程池”旨在减少创建和销毁线程的频率,其维持一定合理数量的线程,并...

  C#技术分享【PDF转换成图片——10种方案】(2013-07-25重新整理)

本文链接:http://apps-n-tabs.com/fanxiangfuyong/98.html