这篇文章主要讲解了“怎么理解UNIX的网络I/O模型”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解UNIX的网络I/O模型”吧!
从策划到设计制作,每一步都追求做到细腻,制作可持续发展的企业网站。为客户提供网站设计、网站制作、网站策划、网页设计、域名注册、虚拟空间、网络营销、VI设计、 网站改版、漏洞修补等服务。为客户提供更好的一站式互联网解决方案,以客户的口碑塑造优易品牌,携手广大客户,共同发展进步。
UNIX的网络I/O模型:
概念:
1)linux内核对一个文件的读写操作会调用内核提供的系统命令,返回一个文件描述符(file discriptor,简称fd)。
描述符就是一个数字,它指向内核中的一个结构体,这个结构体包含了文件路径等信息。 eg:对socket的读写会返回一个描述符 socketfd
2)一次⽹络I/O的读操作会包含下面这两个阶段:1)等待数据准备就绪 2)数据从内核复制到用户空间(即用户进程)。
1)阻塞I/O模型:blocking I/O
概念:用户进程从阻塞的socket中读取数据时,只有当数据包到达该socket的接收缓存区且数据被复制到进程空间的缓存区中 或 发生错误时 才返回,在此期间进程会一直阻塞等待。
说明:默认情况下,所有的文件操作都是阻塞的。
缺点:客户端的并发访问量比较高时,服务端需要创建大量的线程来响应请求,当线程的数量膨胀后,系统的性能会急剧下降甚至宕机。
伪异步I/O模型:
概念:为了解决阻塞I/O模型中需要为每一个请求都创建一个线程的问题,服务端可以使用线程池来实现一个伪异步I/O模型。
伪异步I/O模型可能导致的级联故障:某台服务器故障导致响应缓慢 -> 线程读取故障服务节点的响应 -> 所有线程被故障节点阻塞,后续IO消息都在队列中 -> 队列积满 -> 新的客户端请求被拒绝,服务器无响应
2)非阻塞I/O模型:nonblocking I/O
概念:用户进程从非阻塞的socket中读取数据时,若该套接字的接收缓存区中没有数据,则内核会直接返回一个错误。
说明:一般当socket设为非阻塞状态时,用户进程会轮询内核(eg:循环调用recvfrom函数),直到内核有数据返回为止,因此会导致大量cpu资源被占用。
3)I/O复用模型:I/O multiplexing
概念:将多个待监听的fd注册到多路复用器(selector)中,注册的时候需要指定该fd上待监听的事件,selector会一直监听注册的fd,当fd上有事件发生时,selector会做出相应的处理。
说明:
与阻塞I/O模型相比,I/O复用模型是阻塞在select调用(或poll调用、或epoll调用)上,而不是阻塞在真正的I/O操作上。注意:阻塞是针对发起方而言的。
获取fd的状态:内核把fd的信息通知给用户空间。
水平触发:若就绪的fd未被用户进程处理,则该fd在下一次查询时依旧会返回。
边缘触发:无论就绪的fd是否被用户进程处理,该fd在下一次查询时将不再返回。
优点:
客户端发起的连接操作是异步的,故单线程可以同时处理多个客户端的IO请求。系统不需要为每个客户端请求都创建一个线程,这样大大降低了系统的开销,
缺点:
select调用:
概念:多路复用器(selector)由select函数实现。
监听机制:
轮询注册的fd,并根据fd的状态做相应的处理:
读就绪状态 -> 读数据 并 删除该读就绪事件
写就绪状态 -> 写数据 并 删除该写就绪事件
接收(accept)就绪状态 -> 注册新的读就绪事件 并 删除该接收就绪事件
...
获取fd的状态:内核把所有监听的fd的信息整体复制到用户空间。
触发方式:水平触发。
优点:与非阻塞式I/O模式相比,select调用不需要客户端不断地发出请求。
缺点:
单个进程可以打开的fd数量有限,默认1024个,如果要修改这个默认值,需要重新编译内核。
每次select调用都会线性地扫描所有监听的fd(即:无论fd是否就绪,select都会去检查它的状态),当监听的fd数量比较多时,I/O效率呈线性下降。
poll调用:
概念:多路复用器(selector)由poll函数实现。
监听机制:同select调用。
触发方式:水平触发。
优点:
单个进程可以打开的fd数量不受限制。
缺点:
线性地扫描所有监听的fd,当监听的fd数量比较多时,I/O效率呈线性下降。
epoll调用:
概念:selector由一系列epoll_函数实现。
监听机制:
当fd就绪时,fd会立即回调rollback函数。而那些没有就绪的fd则不会回调rollback函数。
获取fd的状态:使用内存映射,不需要把fd的信息从内核复制到用户空间。
触发方式:默认是水平触发,支持边缘触发。
优点:
单个进程可以打开的fd数量不受限制。(仅受限于操作系统的最大文件句柄数,1g内存的最大文件句柄数为10w左右)
由于epoll采用的是回调函数的方式,而不是线性扫描的方式,故I/O效率不会随着fd数量的增加而线性下降。
使用内存映射,避免了内存复制的开销,加速了内核与用户空间的消息传递。
缺点:
在连接数少并且连接都十分活跃的情况下,epoll的性能可能比select和poll的性能差,毕竟epoll的通知机制需要很多函数回调。
4)信号驱动式I/O模型:SIGIO
开启套接字信号驱动IO功能,并通过sigaction系统调用,执行一个信号处理函数,当数据报准备好时,内核就为该进程产生一个SIGIO信号,用户进程收到这个信号后,就可以开始进行I/O操作了。
该系统调用会立即返回,在等待数据报到达期间,用户进程不会被阻塞。
说明:信号驱动式I/O模型使用的场景比较少。
5)异步I/O模型:POSIX定义的异步IO函数
调用异步IO函数,让内核在整个I/O操作(包括将数据从内核复制到用户自己的缓冲区)完成后通知用户进程。
该系统调用会立即返回,在等待I/O操作期间,用户进程不被阻塞。
说明:同步/异步是针对执行方而言的。
感谢各位的阅读,以上就是“怎么理解UNIX的网络I/O模型”的内容了,经过本文的学习后,相信大家对怎么理解UNIX的网络I/O模型这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是创新互联,小编将为大家推送更多相关知识点的文章,欢迎关注!
分享名称:怎么理解UNIX的网络I/O模型
网站路径:http://scpingwu.com/article/ipjspp.html