标签:阶段 它的 href for 缺点 读写 syn 概念 locking
先说明一下IO发生时涉及到的对象和步骤,对于一个network IO,它会涉及到两个阶段
在linux中,默认情况下所有的socket都是blocking,一个典型的读操作流程大概如下图:
当用户进程调用了recvfrom这个系统调用,kernel就开始了IO的第一个阶段:准备数据。对于network IO来说,很多时候数据在一开始还没有到达(比如,还没有收到一个完整的UDP包),这个时候kernel就要等待足够的数据到来。而在用户进程这边,整个进程会被阻塞。当kernel一直等到数据准备好了,它就会将数据从kernel中拷贝到用户内存,然后kernel返回结果,用户进程才解除block的状态,重新运行起来。
当用户进程发出recvfrom这个系统调用后,如果kernel中的数据还没有准备好,那么它并不会block用户进程,而是立刻返回一个结果(no datagram ready)。从用户进程角度讲 ,它发起一个操作后,并没有等待,而是马上就得到了一个结果。用户进程得知数据还没有准备好后,它可以每隔一段时间再次发送recvfrom操作。一旦kernel中的数据准备好了,并且又再次收到了用户进程的system call,那么它马上就将数据拷贝到了用户内存,然后返回。
看起来它与blocking I/O很相似,两个阶段都阻塞。但它与blocking I/O的一个重要区别就是它可以等待多个数据报就绪(datagram ready),即可以处理多个连接。这里的select相当于一个“代理”,调用select以后进程会被select阻塞,这时候在内核空间内select会监听指定的多个datagram (如socket连接),如果其中任意一个数据就绪了就返回。此时程序再进行数据读取操作,将数据拷贝至当前进程内。由于select可以监听多个socket,我们可以用它来处理多个连接。
在select模型中每个socket一般都设置成non-blocking,虽然等待数据阶段仍然是阻塞状态,但是它是被select调用阻塞的,而不是直接被I/O阻塞的。select底层通过轮询机制来判断每个socket读写是否就绪。
当然select也有一些缺点,比如底层轮询机制会增加开销、支持的文件描述符数量过少等。为此,Linux引入了epoll作为select的改进版本。
这里面的读取操作的语义与上面的几种模型都不同。这里的读取操作(aio_read)会通知内核进行读取操作并将数据拷贝至进程中,完事后通知进程整个操作全部完成(绑定一个回调函数处理数据)。读取操作会立刻返回,程序可以进行其它的操作,所有的读取、拷贝工作都由内核去做,做完以后通知进程,进程调用绑定的回调函数来处理数据。
总结一下阻塞、非阻塞,同步和异步这两组概念。
标签:阶段 它的 href for 缺点 读写 syn 概念 locking
原文地址:https://www.cnblogs.com/weiweng/p/13377799.html