当前位置: 首页 > news >正文

学校免费网站建设安徽省建设工程造价管理网站

学校免费网站建设,安徽省建设工程造价管理网站,html5 微网站,朋友圈推广文案高性能IO模型浅析 服务器端编程经常需要构造高性能的IO模型#xff0c;常见的IO模型有四种#xff1a; #xff08;1#xff09;同步阻塞IO#xff08;Blocking IO#xff09;#xff1a;即传统的IO模型。 #xff08;2#xff09;同步非阻塞IO#xff08;Non-blo…高性能IO模型浅析 服务器端编程经常需要构造高性能的IO模型常见的IO模型有四种 1同步阻塞IOBlocking IO即传统的IO模型。 2同步非阻塞IONon-blocking IO默认创建的socket都是阻塞的非阻塞IO要求socket被设置为NONBLOCK。注意这里所说的NIO并非Java的NIONew IO库。 3IO多路复用IO Multiplexing即经典的Reactor设计模式有时也称为异步阻塞IOJava中的Selector和Linux中的epoll都是这种模型。 4异步IOAsynchronous IO即经典的Proactor设计模式也称为异步非阻塞IO。 同步和异步的概念描述的是用户线程与内核的交互方式同步是指用户线程发起IO请求后需要等待或者轮询内核IO操作完成后才能继续执行而异步是指用户线程发起IO请求后仍继续执行当内核IO操作完成后会通知用户线程或者调用用户线程注册的回调函数。 阻塞和非阻塞的概念描述的是用户线程调用内核IO操作的方式阻塞是指IO操作需要彻底完成后才返回到用户空间而非阻塞是指IO操作被调用后立即返回给用户一个状态值无需等到IO操作彻底完成。 另外Richard Stevens 在《Unix 网络编程》卷1中提到的基于信号驱动的IOSignal Driven IO模型由于该模型并不常用本文不作涉及。接下来我们详细分析四种常见的IO模型的实现原理。为了方便描述我们统一使用IO的读操作作为示例。 一、同步阻塞IO 同步阻塞IO模型是最简单的IO模型用户线程在内核进行IO操作时被阻塞。 图1 同步阻塞IO 如图1所示用户线程通过系统调用read发起IO读操作由用户空间转到内核空间。内核等到数据包到达后然后将接收的数据拷贝到用户空间完成read操作。 用户线程使用同步阻塞IO模型的伪代码描述为 { read(socket, buffer); process(buffer); } 即用户需要等待read将socket中的数据读取到buffer后才继续处理接收的数据。整个IO请求的过程中用户线程是被阻塞的这导致用户在发起IO请求时不能做任何事情对CPU的资源利用率不够。 二、同步非阻塞IO 同步非阻塞IO是在同步阻塞IO的基础上将socket设置为NONBLOCK。这样做用户线程可以在发起IO请求后可以立即返回。 图2 同步非阻塞IO 如图2所示由于socket是非阻塞的方式因此用户线程发起IO请求时立即返回。但并未读取到任何数据用户线程需要不断地发起IO请求直到数据到达后才真正读取到数据继续执行。 用户线程使用同步非阻塞IO模型的伪代码描述为 { while(read(socket, buffer) ! SUCCESS); process(buffer); } 即用户需要不断地调用read尝试读取socket中的数据直到读取成功后才继续处理接收的数据。整个IO请求的过程中虽然用户线程每次发起IO请求后可以立即返回但是为了等到数据仍需要不断地轮询、重复请求消耗了大量的CPU的资源。一般很少直接使用这种模型而是在其他IO模型中使用非阻塞IO这一特性。 三、IO多路复用 IO多路复用模型是建立在内核提供的多路分离函数select基础之上的使用select函数可以避免同步非阻塞IO模型中轮询等待的问题。 图3 多路分离函数select 如图3所示用户首先将需要进行IO操作的socket添加到select中然后阻塞等待select系统调用返回。当数据到达时socket被激活select函数返回。用户线程正式发起read请求读取数据并继续执行。 从流程上来看使用select函数进行IO请求和同步阻塞模型没有太大的区别甚至还多了添加监视socket以及调用select函数的额外操作效率更差。但是使用select以后最大的优势是用户可以在一个线程内同时处理多个socket的IO请求。用户可以注册多个socket然后不断地调用select读取被激活的socket即可达到在同一个线程内同时处理多个IO请求的目的。而在同步阻塞模型中必须通过多线程的方式才能达到这个目的。 用户线程使用select函数的伪代码描述为 {select(socket);while(1) {sockets  select();for(socket in sockets) {if(can_read(socket)) {read(socket, buffer);process(buffer);}}}} 其中while循环前将socket添加到select监视中然后在while内一直调用select获取被激活的socket一旦socket可读便调用read函数将socket中的数据读取出来。 然而使用select函数的优点并不仅限于此。虽然上述方式允许单线程内处理多个IO请求但是每个IO请求的过程还是阻塞的在select函数上阻塞平均时间甚至比同步阻塞IO模型还要长。如果用户线程只注册自己感兴趣的socket或者IO请求然后去做自己的事情等到数据到来时再进行处理则可以提高CPU的利用率。 IO多路复用模型使用了Reactor设计模式实现了这一机制。 图4 Reactor设计模式 如图4所示EventHandler抽象类表示IO事件处理器它拥有IO文件句柄Handle通过get_handle获取以及对Handle的操作handle_event读/写等。继承于EventHandler的子类可以对事件处理器的行为进行定制。Reactor类用于管理EventHandler注册、删除等并使用handle_events实现事件循环不断调用同步事件多路分离器一般是内核的多路分离函数select只要某个文件句柄被激活可读/写等select就返回阻塞handle_events就会调用与文件句柄关联的事件处理器的handle_event进行相关操作。 图5 IO多路复用 如图5所示通过Reactor的方式可以将用户线程轮询IO操作状态的工作统一交给handle_events事件循环进行处理。用户线程注册事件处理器之后可以继续执行做其他的工作异步而Reactor线程负责调用内核的select函数检查socket状态。当有socket被激活时则通知相应的用户线程或执行用户线程的回调函数执行handle_event进行数据读取、处理的工作。由于select函数是阻塞的因此多路IO复用模型也被称为异步阻塞IO模型。注意这里的所说的阻塞是指select函数执行时线程被阻塞而不是指socket。一般在使用IO多路复用模型时socket都是设置为NONBLOCK的不过这并不会产生影响因为用户发起IO请求时数据已经到达了用户线程一定不会被阻塞。 用户线程使用IO多路复用模型的伪代码描述为 void UserEventHandler::handle_event() { if(can_read(socket)) { read(socket, buffer); process(buffer); }} { Reactor.register(new UserEventHandler(socket)); } 用户需要重写EventHandler的handle_event函数进行读取数据、处理数据的工作用户线程只需要将自己的EventHandler注册到Reactor即可。Reactor中handle_events事件循环的伪代码大致如下。 Reactor::handle_events() { while(1) { sockets  select(); for(socket in sockets) { get_event_handler(socket).handle_event(); }}} 事件循环不断地调用select获取被激活的socket然后根据获取socket对应的EventHandler执行器handle_event函数即可。 IO多路复用是最常使用的IO模型但是其异步程度还不够“彻底”因为它使用了会阻塞线程的select系统调用。因此IO多路复用只能称为异步阻塞IO而非真正的异步IO。 四、异步IO “真正”的异步IO需要操作系统更强的支持。在IO多路复用模型中事件循环将文件句柄的状态事件通知给用户线程由用户线程自行读取数据、处理数据。而在异步IO模型中当用户线程收到通知时数据已经被内核读取完毕并放在了用户线程指定的缓冲区内内核在IO完成后通知用户线程直接使用即可。 异步IO模型使用了Proactor设计模式实现了这一机制。 图6 Proactor设计模式 如图6Proactor模式和Reactor模式在结构上比较相似不过在用户Client使用方式上差别较大。Reactor模式中用户线程通过向Reactor对象注册感兴趣的事件监听然后事件触发时调用事件处理函数。而Proactor模式中用户线程将AsynchronousOperation读/写等、Proactor以及操作完成时的CompletionHandler注册到AsynchronousOperationProcessor。AsynchronousOperationProcessor使用Facade模式提供了一组异步操作API读/写等供用户使用当用户线程调用异步API后便继续执行自己的任务。AsynchronousOperationProcessor 会开启独立的内核线程执行异步操作实现真正的异步。当异步IO操作完成时AsynchronousOperationProcessor将用户线程与AsynchronousOperation一起注册的Proactor和CompletionHandler取出然后将CompletionHandler与IO操作的结果数据一起转发给ProactorProactor负责回调每一个异步操作的事件完成处理函数handle_event。虽然Proactor模式中每个异步操作都可以绑定一个Proactor对象但是一般在操作系统中Proactor被实现为Singleton模式以便于集中化分发操作完成事件。 图7 异步IO 如图7所示异步IO模型中用户线程直接使用内核提供的异步IO API发起read请求且发起后立即返回继续执行用户线程代码。不过此时用户线程已经将调用的AsynchronousOperation和CompletionHandler注册到内核然后操作系统开启独立的内核线程去处理IO操作。当read请求的数据到达时由内核负责读取socket中的数据并写入用户指定的缓冲区中。最后内核将read的数据和用户线程注册的CompletionHandler分发给内部ProactorProactor将IO完成的信息通知给用户线程一般通过调用用户线程注册的完成事件处理函数完成异步IO。 用户线程使用异步IO模型的伪代码描述为 void UserCompletionHandler::handle_event(buffer) { process(buffer); } { aio_read(socket, new UserCompletionHandler); } 用户需要重写CompletionHandler的handle_event函数进行处理数据的工作参数buffer表示Proactor已经准备好的数据用户线程直接调用内核提供的异步IO API并将重写的CompletionHandler注册即可。 相比于IO多路复用模型异步IO并不十分常用不少高性能并发服务程序使用IO多路复用模型多线程任务处理的架构基本可以满足需求。况且目前操作系统对异步IO的支持并非特别完善更多的是采用IO多路复用模型模拟异步IO的方式IO事件触发时不直接通知用户线程而是将数据读写完毕后放到用户指定的缓冲区中。 由于在看redis看到了I/O多路复用补一下原理知识。
http://www.hkea.cn/news/14256150/

相关文章:

  • 卡密提取网站怎么做网站建设的功能定位
  • iis 多网站安全设置本机建的网站打开却很慢
  • 南部县网站建设励志网站织梦源码
  • 公司营业执照可以做几个网站交友高端网站建设
  • 邢台集团网站建设报价网站建设用阿里还是华为云
  • 重庆平台网站建设哪家有写wordpress导航
  • 建筑网站开发大理高端网站建设
  • wordpress主题发布短视频排名seo
  • 建一个个人网站asp网站用什么软件
  • 二维码网站建设东营网站建设铭盛信息
  • 佛山建站网站模板南宁建筑规划设计集团有限公司
  • 陕西网站制作定制网站 签约
  • 可以制作h5的网站怎么建立自己的网站域名
  • 网站开发计划怎么写wordpress自定义分类面包屑导航
  • 黄山网站建设电话wordpress站做app
  • 网站 云建站在上面网站上可以做统计图
  • 网站建设的目标与期望贵阳网站开发工程师招聘网
  • 微商城网站建设报价seo网站推广招聘
  • 微网站 免费怎么做织梦网站
  • 网站流量做那些好网上哪个网站做的系统好用吗
  • 建网站的意义万商惠网站建设系统开发
  • 医院网站的建设哪里可以买到便宜的域名
  • 制作网站比较大的几家公司网站建设高校
  • 社交网站有哪些如何做常熟建设局网站首页
  • 写作网站大全深圳建网站多少钱
  • 学做西点的网站深圳哪家做网站
  • 哪里可以做网站开发搭建小程序
  • 沈阳网站设计定制我的网站域名
  • 装饰设计公司网站合肥百度快照优化排名
  • 新手学做网站txt网课如何推广