IO多路复用机制-以及相关基础

 


> **如果你想深入了解Linux中IO多路复用,则你需要知道的基础以及内部的一些机制就在这里**


## 一、基础概念
1、Linux系统一切皆文件,如socket、pid等
- 如查看某个进程打开的文件: ll /proc/[进程ID]/fd
- 文件描述符限制:系统、用户
- 系统限制设置的是:系统中所有用户的文件描述符总的最大值
- 用户限制是:用户所能打开的最大文件描述符的大小
- 用户限制设置(查看设置-ulimit -n): vim /etc/security/limits.con
~~~
* - nofile 65535
* soft nofile 65536
* hard nofile 131072
* soft nproc 2048
* hard nproc 409
~~~
- 查看系统文件描述符限制:sysctl -a| grep fs.file-max

 


2、用户空间、内核空间

- 内核:操作系统的核心就是内核,它可以访问受保护的内存空间,也可以访问硬件设备
- 为了保证内核安全-用户进程不能直接访问内核,操作系统将内存划分为内核空间(内核使用)、用户空间(用户进程使用),
- 用户态:进程运行在用户空间,则为用户态
- 内核态:进程运行在内核空间,则为内核态
- 说明:所有的系统资源管理都是内核空间中完成,如磁盘读写,分配回收内存,网络读写数据,我们的应用是通过内核提供的接口进行来完成的。

3、 文件描述符
- 对网络和文件的读写都会返回文件描述符(一切皆文件,统一了操作的API)

4、文件缓存(pageCache)
- 解决内存和硬盘性能差异的问题
- 文件读取,先把文件拷贝到内核Page Cache中,然后拷贝到用户态内存
- 写文件,先把内容写入到内核的Page Cache中,然后线程就返回,Page中的数据会被内核线程pbflush异步写入到硬盘上

5、磁盘IO种类
- 标准访问:用户读写-用户空间-内核空间(PageCache)-磁盘(写入磁盘时间取决于系统)
- 直接IO(跳过内核Page缓存,用户自己缓存):用户读写-用户空间-用户自己缓存-磁盘
- 内存映射-mmap:把用户的内存和文件进行关联,操作内存就是操作文件(个人理解,以后在详细学习)
- 零拷贝-sendfile:磁盘->内核buffer->socketbuffer(这个不保存数据,只保存数据的内存地址)-> 网卡-> 网络传输流程,正常的数据流转流程为:内核缓存->用户内存->socketbuffer-> 网卡,那零拷贝相比减少了用户内存和socketbuffer两个流程

6、数据在各阶段延迟说明 - Latency Numbers Matter
https://www.dazhuanlan.com/2019/12/11/5df09ea27c7bc/

- 打开一个网站 几秒
- 在数据库中查询一条记录-有索引十几毫秒
- 机械硬盘寻址定位- 4毫秒
- 从机械磁盘顺序读取1M数据- 2毫秒
- 从SSD磁盘顺序读取1MB数据 - 0.3毫秒
- 从远程Redis读取一条数据- 0.5毫秒
- 从内存中读取1MB的数据- 十几微妙
- Java程序本地方法调用- 几微妙
- 网络传输2K数据 - 1微妙


7、 网络IO缓存(在对网络进行读写的时候,都会经过一层缓存),socket(本质上是流,也是文件)
8、网络IO过程中,数据读取分为两个阶段
- 数据准备阶段:等待socket接收数据,并从socket读取数据,然后写入内核空间的过程
- 数据拷贝阶段:数据从内核空间拷贝到用户空间的过程

9、进程切换(使进程阻塞)

10、Linux 的IO模型(主要以下面几个常用的学习)-纯个人理解
- 同步阻塞:一个客户端访问到服务端,服务端启动一个线程等待客户端数据写入,服务端的线程是阻塞的(**不能做任何事情**),直到超时或者人为停止
- 同步非阻塞:一个客户端访问到服务端,服务端启动一个线程等待客户端数据写入,服务端线程是非阻塞的(**等待过程中可以做其他事情**,但每隔一段时间要查询是否有数据进行处理),这个相对于同步阻塞来说,服务端线程可以做其他事情,但是依然需要大量线程来等待处理客户端请求
- IO多路复用(同步阻塞的升级,数据拷贝过程是阻塞的):很多客户端访问到服务端,服务端仅启动**一个线程来监控多个客户端数据写入**,一旦有数据写入则服务端启动新线程处理,相比同步非阻塞减少了创建线程的数量,**多路复用**指的是复用一个线程来监控多个socket的写入


11、在Linux中IO多路复用机制区别 select poll epoll

- select :底层结构为数组,存储的文件描述符大小有限制,并且监控socket采用的是不断扫描整个数组,当数组比较大的时候,效率低下
- poll :底层结构为连表,监控方式同select
- epoll :基于事件通知机制,当某个socket有事件的时候,会调用callback来通知那个文件描述符活跃,然后通知服务端启动线程处理,减少了循环扫描对于资源的消耗

12、参考:

> - https://www.cnblogs.com/sunsky303/p/8962628.html
> - https://www.jianshu.com/p/486b0965c296

posted @ 2020-08-25 14:35  码来  阅读(304)  评论(0编辑  收藏  举报