| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 网络协议 -> 从解决问题的思路去理解IO复用的由来 -> 正文阅读 |
|
[网络协议]从解决问题的思路去理解IO复用的由来 |
写在前面近日一直在学习理解IO多路复用的相关概念。协程,epoll,阻塞非阻塞等等概念看了很多资料,博客,视频,感觉总是差点意思,直到刚才看了这篇文章才有一点融会贯通的感觉。很多底层概念是相互依赖的,只说其一就会分裂,只说用法不说原因就会莫名其妙。我一向喜欢从提出问题,解决问题的思路来去理解概念。下面讲讲我的一些个人理解 一些浅显的知识(或者说常识
下面回归正题: 阻塞式IO
这是服务端处理客户端请求的代码 显然,accept函数,read函数都可能会发生阻塞。
这样每一个连接请求用一个线程来处理:主线程接收到连接请求就建立一个子线程来处理它,然后继续监听请求。这样就避免了read函数阻塞带来的问题。 **但是带来新的问题:**比方说现在有线程A,分配到了CPU的时间片,然后他去执行doWork函数,走到read函数,发现客户端没给发数据,所以只能阻塞,阻塞就要挂起,就要由用户态切换到内核态,就要进行线程上下文切换,就有开销。 所以read函数阻塞的问题一定要解决 非阻塞式IO操作系统为我们提供非阻塞的read系统调用,如果当前没有可读的内容,read函数就返回-1,然后线程去干其他事情,而不是导致整个线程阻塞挂起。
刚才,操作系统是在不停地切换线程,切换用户态与内核态;现在没有频繁切换线程,但是仍然在频繁地切换内核态与用户态。 比方说,现在某个线程分配到了CPU的时间片,美滋滋去doWork,使用一次read系统调用,发现返回为-1,然后就去干其他的,每隔一会儿轮询使用一次read,每次都会从用户态切换到内核态,检查fd,再切回去。好好一个时间片啥也没干,全用在系统调用,切换状态上了。 如果IO等待时间不长,倒问题不大;如果等待时间长,CPU就处于空耗状态。 IO多路复用相比于**“一线程,一连接”的方式,我们能不能“一线程,多连接”**呢?(这里可以引入协程的概念) 你会想问,那非阻塞轮询导致用户态与内核态频繁切换的问题还是没解决啊? 这三个方法的核心都是,将轮询导致无意义的check,转交给内核来完成(用户态轮询->内核态轮询),这样只需要一次内核-用户态切换就行了。
我们用一个线程A,不断地监听客户端的请求,并将生成的fd添加到一个集合当中。 我们用另外一个线程B,调用select函数,将bitmap传入到内核,由内核轮询check各个fd的状态,如果fd可读,则将相应的位图置为1,否则为0. 此时B是阻塞状态的。
poll方案的进步在于声明了一个数据结构来表示fd,打破了select只能监听1024个fd的限制(因为这个数据结构的数组,想开多大就开多大)
epoll方案将文件描述符的集合变成了内核态与用户态共享。这样省去了select调用时由用户态切换为内核态的开销。 此外,epoll会告诉用户有多少个fd是已经准备好的,并将它们放到列表的最前面(底层用红黑树来组织),这样epoll返回后,就不再需要遍历整个集合,而只需要遍历准备好的n个,并调用read即可。 内核也不再通过轮询的方式找到就绪的文件描述符,而是谁准备好了就通知一声,内核就把它的fd放到列表前面,也就是异步的方式。 到这里似乎所有问题都得到了完美的解决,其实不然。 只要阻塞,就会涉及到线程切换。 这里引入协程的概念。协程本质是一些函数,能够在用户态进行切换,所以代价比线程切换要小得多。因此协程也叫做用户态线程。这里我们将read函数做一步封装,封装成一个函数,也就是一个协程。如果当前协程A的read被阻塞了,就会切换到另一个协程B去read,当A read完之后,自动切换回A,恢复协程的上下文。 这样,就解决了阻塞的问题。 感觉看别人的博客,视频终归很难形成自己的理解。还是要多多结合源码 |
|
网络协议 最新文章 |
使用Easyswoole 搭建简单的Websoket服务 |
常见的数据通信方式有哪些? |
Openssl 1024bit RSA算法---公私钥获取和处 |
HTTPS协议的密钥交换流程 |
《小白WEB安全入门》03. 漏洞篇 |
HttpRunner4.x 安装与使用 |
2021-07-04 |
手写RPC学习笔记 |
K8S高可用版本部署 |
mySQL计算IP地址范围 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 4:44:02- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |