linux网络IO模型——阻塞非阻塞和同步异步
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux网络IO模型——阻塞非阻塞和同步异步相关的知识,希望对你有一定的参考价值。
最近几天在学习nginx的时候了解了一下linux网络IO模型,在此谈谈我自己的理解,如有错误请多多指教。本文参考书籍Richard Stevens的“UNIX® Network Programming Volume 1, Third Edition: The Sockets Networking ”,6.2节“I/O Models ”。
Linux网络IO请求数据分为两段:
1.数据准备
2.将数据从内核拷贝到进程空间
其实,阻塞、非阻塞和同步、异步的不同就在于这两个阶段的不同。
同步和异步关注的是消息通信机制
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态
阻塞(blocking IO)
linux中,默认情况下socket都是阻塞的,大致过程如下:
如图,进程发起recvform后,内核进行第一阶段准备数据,但是很多时候数据开始时不会全部到达,对于进程来说就处于blocking状态,数据准备好后,内核将数据拷贝到进程空间,拷贝完毕后kernel返回结果,进程结束阻塞状态。即blocking IO两个阶段全部处于blocking状态。
非阻塞(non-blocking IO)
linux中我们可以设置socket为non-blocking,当发出的IO请求没有完成时,不是把进程转为睡眠态,而是返回一个error。
如图所示,当用户发起read时,数据若没有准备好,kernel会立即返回一个error,不需要等待。当进程收到error(EWOULDBLOCK)后,知道数据还没有准备好,之后继续发送read请求。kernel会继续收到进程的system call请求,直到数据准备好,内核会将数据拷贝到用户进程空间。这种模型需要进程不间断的发起system call请求,这会造成cpu时间的浪费。
IO复用(IO Multiplexing)
IO复用多数人所知的是select,poll。select/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。它的基本原理就是select/poll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。大致过程如下:
当用户进程调用了select,整个进程就会被阻塞。同时内核会轮询查看所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用system call,将数据从kernel拷贝到用户进程空间。
这个模型和blocking IO相比,并没有多大的优势,甚至有时候还不如blocking IO。select/poll的优势是可以同时处理多个connection,并不是单个connection处理得更快。
异步IO(Asynchronous I/O Model)
用户进程发起system call调用之后,就可以去做其他事了。从kernel的角度,当它收到一个aio_read之后,它会立刻返回,所以不会对用户进程产生blocking。kernel会等待数据准备完成,然后将数据拷贝到用户内存,拷贝完成后,kernel会给用户进程发送一个signal,告诉它read操作完成了。
blocking和non-blocking的区别:
blocking会一直阻塞进程直到操作完成,non-blocking在内核准备数据的时候会立即返回。
同步synchronous I/O 和异步asynchronous I/O的区别
synchronous io在请求数据的过程中存在阻塞,asynchronous io在请求数据的过程中不存在阻塞。
各种IO模型比较:
如图,blocking,non-blocking,I/O multiplexing均属于synchronous IO。
以上是关于linux网络IO模型——阻塞非阻塞和同步异步的主要内容,如果未能解决你的问题,请参考以下文章