武进网站建设哪家好,从事网站建,形象墙设计公司,wordpress评论框优化基础概念IO分为几种#xff1a;同步阻塞的BIO#xff0c;同步非阻塞的NIO#xff0c;异步非阻塞AIO#xff0c;IO多路复用#xff0c;信号驱动IO#xff08;不常用#xff09;对于一个network IO#xff0c;它会涉及到两个系统对象#xff0c;一个是调用这个IO的proce…基础概念IO分为几种同步阻塞的BIO同步非阻塞的NIO异步非阻塞AIOIO多路复用信号驱动IO不常用对于一个network IO它会涉及到两个系统对象一个是调用这个IO的processThread另一个是系统内核。当一个read/recv读数据的操作发生时该操作会经历两个阶段 1等待数据准备 2将数据从内核拷贝到进程中BIO同步并阻塞服务端处理请求是串联的。也就是说如果这个请求被阻塞了那么剩下的请求都要被阻塞等待上一个请求处理完成才行。所以我们上面说在 服务器读数据的时候数据还没到数据还没读到用户态那么服务器被阻塞然后其他客户端的请求也不能被处理。比如小明和小红两个人访问同一个服务然后小明先点但是数据没被处理完成然后小红在进行发送请求此时服务器就将小红的请求挂起等待小明的处理完成在进行处理。而且小明发了申请服务器没有返回响应之前小明也不能动阻塞在那里等待到应答才能继续做别的事情.NIO:同步非阻塞用户线程发起IO请求后立即返回这时候可以干点别的过一会再查但需要不断地调用read尝试读取socket中的数据直到读取成功后才继续处理接收的数据。虽然用户线程每次发起IO请求后可以立即返回但是为了等到数据仍需要不断地轮询、重复请求消耗了大量的CPU的资源。一般很少直接使用这种模型而是在其他IO模型中使用非阻塞IO这一特性。当用户进程发出read操作时如果kernel中的数据还没准备好那么它并不会block用户进程而是立刻返回一个error。当用户进程接收到一个error就会知道数据还没准备于是用户就可以做点其他的过一段时间再次发送read操作一旦kernel的数据准备好了他就会立马把数据拷贝到了用户内存然后返回。 在这种非阻塞IO模式下用户进程就不断的询问kernel的数据准备好了没若没有返回给 用户一个error在两次询问期间用户进程可以干点其他的若数据准备好了就直接拷贝这个询问过程叫轮询。在拷贝数据整个过程进程任仍然处于阻塞状态IO多路复用一个线程内同时处理多个IO请求这就是IO多路复用相当于select\epoll这种IO方式也称为事件驱动IOselect\epoll的好处在于单个process就可以同时处理多个网络连接的IO。它的基本原理就是select\epoll这个function会不断的轮询所负责的所有socket当某个socket有数据响应了就通知用户进程。当用户进程调用了select那么整个进程会被block而同时kernel会“监视”所有select负责的socket当任何一个socket中的数据准备好了select就会返回。这个时候用户进程再调用read操作将数据从kernel拷贝到用户进程。 这个图和blocking IO的图其实并没有太大的不同事实上还更差一些。因为它不仅阻塞了还多需要使用两个系统调用(select和recvfrom)而blocking IO只调用了一个系统调用(recvfrom)当只有一个连接请求的时候这个模型还不如阻塞IO效率高。但是用select的优势在于它可以同时处理多个connection而阻塞IO那里不能我不管阻塞不阻塞你所有的连接包括recv等操作我都帮你监听着以什么形式监听的呢先不要考虑下面会讲的~~其中任何一个有变动有链接有数据我就告诉你用户那么你就可以去调用这个数据了这就是他的NB之处。 select模块及使用方法select的优势在于处理多个连接不适用于单个连接虽然上述方式允许单线程内处理多个IO请求但是每个IO请求的过程还是阻塞的在select函数上阻塞平均时间甚至比同步阻塞IO模型还要长。如果用户线程只注册自己感兴趣的socket或者IO请求然后去做自己的事情等到数据到来时再进行处理则可以提高CPU的利用率。以下是改良版reactor设计模式就是基于IO多路复用可以参考https://blog.csdn.net/coldstarry/article/details/129433822AIO异步IO 用户进程发起read操作之后立刻就可以开始去做其它的事。而另一方面从kernel的角度当它受到一个asynchronous read之后首先它会立刻返回所以不会对用户进程产生任何block。然后kernel操作系统会等待数据阻塞准备完成然后将数据拷贝到用户内存当这一切都完成之后kernel会给用户进程发送一个signal告诉它read操作完成了。 貌似异步IO这个模型很牛~~但是你发现没有这不是我们自己代码控制的都是操作系统完成的而python在copy数据这个阶段没有提供操纵操作系统的接口所以用python没法实现这套异步IO机制其他几个IO模型都没有解决第二阶段的阻塞用户态和内核态之间copy数据但是C语言是可以实现的因为大家都知道C语言是最接近底层的虽然我们用python实现不了但是python仍然有异步的模块和框架tornado、twstied高并发需求的时候用这些模块和框架很多都是用底层的C语言实现的它帮我们实现了异步你只要使用就可以了但是你要知道这个异步是不是很好呀不需要你自己等待了操作系统帮你做了所有的事情你就直接收数据就行了就像你有一张银行卡银行定期给你打钱一样。信号驱动IO信号驱动IO: 内核将数据准备好的时候, 使用SIGIO信号通知应用程序进行IO操作通知应用程序处理IO, 是开始处理IO, 这个时候还是存在阻塞的将数据从内核态拷贝进入到用户态的过程至少是阻塞住的 (应用程序将数据从内核态拷贝到用户态的过程是阻塞等待的, 和异步IO的区别) (此处是区分信号驱动IO和异步IO的关键所在)信号驱动IO, 我们提前在信号集合中设置好IO信号等待 注册好对应的IO处理函数 handlerIO数据准备就绪后会递交SIGIO信号通知应用程序中断然后开始进行对应的IO处理逻辑. 但是通知处理IO的时候存在将数据从 内核空间拷贝到用户空间的过程(而异步IO是数据拷贝完成之后内核再通知应用程序直接开始处理 应用程序直接处理不需要拷贝数据阻塞等待)各IO对比参考文章https://blog.csdn.net/guorui_java/article/details/107081776https://www.cnblogs.com/zhangxiaoji/p/16152141.htmlhttps://zhuanlan.zhihu.com/p/555459665https://www.cnblogs.com/12345huangchun/p/10066840.htmlhttps://blog.csdn.net/leftfist/article/details/105020228