标签:rcv owa pch https 命令 时间 计算 一般来说 ldb
由于IO操作涉及到系统调用,涉及到用户空间和内核空间的切换,所以理解系统的IO模型,对于需要进入到系统调用层面进行编程来说是很重要的。
从程序编写的角度来看,I/O就是调用一个或多个系统函数,完成对输入输出设备的操作。输入输出设置可以是显示器、字符终端命令行、网络适配器、磁盘等。操作系统在这些设备与用户程序之间完成一个衔接,称为驱动程序,驱动程序向下驱动硬件,向上提供抽象的函数调用入口。
一般来说I/O操作是需要时间的,因为这涉及到系统、硬件等计算器模块的互相配合,所以必然不像普通的函数调用那样能够按照既定的方式立即返回。从用户代码的角度,I/O操作的系统调用分为“阻塞”和“非阻塞”两种。
那么我们以网络IO为例,看一下对于一个服务器,“阻塞”和“非阻塞”两种模式,该如何设计。由于服务器要同时服务多个客户端,所以需要同时操作多个Socket。
可以看到,如果使用阻塞的IO方式,因为每个Socket都会阻塞,为了同时服务多个客户端,需要多个线程同时挂起;而如果采用非阻塞的调用方式,则需要在一个线程中不断轮训每个客户端是否有数据到来。
显然纯粹阻塞式的调用不可取,非阻塞式的调用看起来不错,但是仍不够好,因为轮询实际也是通过某种系统调用完成的,相当于在用户空间进行的,效率不高,如果能够在内核空间进行这种类似轮询,然后让内核通知用户空间哪个IO就绪了,就更好了。于是引出接下来的概念:IO多路复用
IO多路复用是一种系统调用,内核能够同时对多个IO描述符进行就绪检查。当所有被监听的IO都没有就绪时,调用将阻塞;当至少有一个IO描述符就绪时,调用将返回,用户代码可通过检查究竟是哪个IO就绪来进一步处理业务。显然,IO多路复用是解决系统里面存在N个IO描述符的问题的,这里必须明确IO复用和IO阻塞与否并不是一个概念,IO复用只检测IO是否就绪(读就绪或者写就绪等),具体的数据的输入输出还是需要依靠具体的IO操作完成(阻塞操作或非阻塞操作)。最典型的IO多路复用技术有select
、poll
、epoll
等。select
具有最大数量描述符限制,而epoll
则没有,并且在机制上,epoll
也更为高效。select
的优势仅仅是跨平台支持性,所有平台和较低版本的内核都支持select
模式,epoll
则不是。
在IO相关的编程中,IO复用起到的作用相当于一个阀门,让后续IO操作更为精准高效。
综上讨论,我们在进行实际的Socket编程的时候,无论是客户端还是服务端,大致有几种模式可以选择:
下面以select为例,整理 在select下,socket的阻塞和非阻塞的一些问题。这些细节在编写基于Socket的网络程序时,尤其是底层数据收发时,是十分重要的。
socket读就绪:
SO_RCVLOWAT
水位(默认是0)。此时调用recv
将返回>0(即读到的字节数)。recv
将返回=0。accept
到一个新的连接,此时accept通常不会阻塞。getsockopt
得到相应的待处理错误。socket写就绪:
SO_SNDLOWAT
水位(默认是2048)。这种就绪是水平触发的,只要有空间就会触发写就绪,即如果保持对这种套接字的就绪检查将使得select
每次都认为有描述符写就绪。所以应当对描述符进行写状态管理,一旦某个描述符可写,应立即停止对该描述符的写状态检查,直到写缓冲区满后,再次select写状态。SIGPIPE
信号。connect
完成。由于非阻的connect将不会阻塞握手过程,所以,当握手在后续时刻完成后,在此保持写状态检查,将触发一次就绪,表示connect完成。send
将返回-1,并应通过getsockopt
得到相应的待处理错误。补充:
非阻的调用recv
、send
、accept
,分别地,如果收缓冲中无数据、发送缓冲不够空间发、没有外来连接,将立即返回,此时全局errno
将得到EWOULDBLOCK
或EAGIAN
,表示“本应阻塞的调用,由于采用了非阻塞模式,而返回”。非阻的调用connect
将立即返回,此时全局errno
将得到EINPROGRESS
,表示连接正在进行。
转自:http://www.pchou.info/c-cpp/2016/02/29/socket-io.html
https://segmentfault.com/a/1190000004537204
标签:rcv owa pch https 命令 时间 计算 一般来说 ldb
原文地址:http://www.cnblogs.com/liushui-sky/p/7799624.html