Linux内核知识 (详解在注释里面,图片加载需要时间)
2023-07-04 08:48:55 0 举报
AI智能生成
知识要点和原理解析,详细信息和图片均在黄色图标的注释中,鼠标移动到黄色图标上即会显示,图片加载有时较慢。
作者其他创作
大纲/内容
用户态、内核态<br>
C P U 指令集
C P U 指令集 权限分级
用户态与内核态简介<br>
用户态与内核态的空间<br>
虚拟内存<br>
用户态与内核态的切换<br>
内核架构图<br>
什么情况会导致用户态到内核态切换
系统调用<br>
异常<br>
中断<br>
文件系统<br>
一切皆文件<br>
磁盘结构<br>
盘面
磁道<br>
扇区
磁盘的基本单位<br>
块
文件系统操作文件的最小单位
页(并非磁盘的概念,属于内存层面)
内存的基本单位
Linux文件系统<br>
分为两层
<font color="#f44336"><b>VFS(虚拟文件系统)</b></font>
VFS在linux架构中的位置<br>
具体文件系统
虚拟文件系统四大对象<br>
1、超级块<br>
2、索引节点:inode<br>
inode描述<br>
一个inode可以有多个文件名(<b>目录项:dentry</b>)来对应它
inode能描述文件占用的块数<br>
inode描述了文件大小和指向数据块的指针<br>
通过inode实现文件的逻辑结构和物理结构的转换
inode怎样生成的?<br>
inode和文件的关系?<br>
3、目录项:dentry<br>
目录项和索引节点的关系:<font color="#f44336">多对一</font>
目录项和目录是一个东西吗?<br>
4、逻辑块<br>
文件数据是如何存储在磁盘的?<br>
inode保存指向逻辑块的指针:一对多
文件分配方式<br>
连续分配<br>
优点<br>
缺点
链式分配<br>
隐式链接<br>
优点
缺点<br>
显式链接<br>
优点
缺点
索引分配<br>
优点
文件的创建、增大、缩小很方便<br>
不会有碎片的问题<br>
支持顺序读写和随机读写
缺点<br>
如果文件很大
链式索引块
多级索引块<br>
空闲空间的管理<br>
空闲表法<br>
优点<br>
缺点<br>
碎片空间
空闲链表法<br>
优点
无碎片空间
缺点<br>
不能随机访问,工作效率低<br>
数据块的指针消耗了一定的存储空间
位图法<br>
索引节点、目录项以及文件数据关系图<br>
文件的存储<br>
块组<br>
目录的存储<br>
内存管理<br>
<b><font color="#f44336">虚拟内存</font></b>、内存管理单元(MMU)、物理内存<br>
映射关系管理<br>
分段<br>
分段机制会把程序的虚拟地址分成 4 个段<br>
好处
能产生连续的内存空间
不足之处<br>
内存碎片<br>
内存交换的效率低<br>
分页<br>
怎么解决分段的内存碎片、内存交换效率低的问题?<br>
如果内存空间不够:<font color="#f44336"><b>LRU</b></font>
虚拟地址和物理地址是如何映射的?
举例<br>
<b>简单的分页</b>有什么缺陷呢?<br>
多级页表<br>
二级页表空间分析
局部性原理<br>
不分级为何无法节省内存<br>
页表缓存TLB(Translation Lookaside Buffer)<br>
页、页表、和页表元素 PTE 的概念和关系<br>
虚拟页为何有会是否已经被缓存在主内存中一说?<br>
分析 PTE 的内部构造<br>
CPU 内存访问过程<br>
内存回收<br>
三种回收方式<br>
1、回收内核中的缓存<br>
2、swap 机制<br>
3、触发 OOM(Out Of Memory) 机制<br>
swap机制原理<br>
哪些进程的内存交换到硬盘中?<br>
<b><font color="#f44336">匿名内存页(数据段、堆段 和 栈段)</font></b>
LRU 内存淘汰算法<br>
主要构成
active_list<br>
inactive_list<br>
PG_referenced标志位<br>
流程<br>
申请一个匿名内存页<br>
匿名内存页被进程访问<br>
内存淘汰过程<br>
活跃链表 的内存页也有衰退的过程<br>
DMA<br>
没有DMA以前的数据获取<br>
整个数据的传输过程,都要需要 CPU 亲自参与搬运数据的过程,CPU阻塞
DMA:直接内存访问(Direct Memory Access)<br>
弊端:四次上下文切换 + 四次拷贝。<br>
Page cache与Buffer cache<br>
Page Cache<br>
缓存<b><font color="#f44336">文件的页</font></b>以优化文件IO<br>
以Page为单位,每页4k,缓存文件内容
文件读写流程<br>
读Cache<br>
写Cache<br>
触发脏数据刷新到磁盘的条件<br>
超时<br>
脏数据占用内存空间过大<br>
Buffer cache<br>
缓存<b><font color="#f44336">块设备的块</font></b>以优化块设备IO
两类缓存的逻辑关系<br>
内存不够用时<br>
两类缓存的演进历史
第一阶段:仅有Buffer Cache<br>
第二阶段:Page Cache、Buffer Cache两者并存<br>
问题:<font color="#f44336"><b>冗余存储</b></font><br>
第三阶段:Page Cache、Buffer Cache两者融合
零拷贝
Zero-copy 能做什么<br>
<b>减少</b>甚至完全避免操作系统内核和用户应用程序地址空间这两者之间进行<b>数据拷贝</b>操作,从而<b><font color="#f44336">减少用户态 -- 内核态上下文切换带来的系统开销</font></b><br>
<b>减少甚至完全避免</b>操作系统<b><font color="#f44336">内核缓冲区之间进行数据拷贝</font></b>操作
帮助<b>用户进程</b>绕开操作系统内核空间<b>直接访问硬件存储接口操作数据</b>
<b><font color="#f44336">利用 DMA</font></b> 而非 CPU 来<b><font color="#f44336">完成硬件接口和内核缓冲区之间的数据拷贝</font></b>,从而解放 CPU,使之能去执行其他的任务,提升系统性能。
主要分为三类<br>
减少甚至避免用户空间和内核空间之间的数据拷贝
绕过内核的直接 I/O<br>
内核缓冲区和用户缓冲区之间的传输优化<br>
传统的 I/O 读写<br>
四次用户态/内核态切换,四次数据拷贝(两次CPU、两次DMA)
应用场景<br>
java的NIO<br>
Netty<br>
kafka<br>
零拷贝计术<br>
mmap<br>
mmap原理<br>
读写操作
读
写<br>
mmap 具体原理<br>
1、<b>分配地址</b>:进程启动映射过程,并在虚拟地址空间中为映射创建虚拟映射区域<br>
2、<b>完成映射</b>:调用内核空间的系统调用函数mmap(不同于用户空间函数),实现文件物理地址和进程虚拟地址的一一映射关系<br>
3、<b>进程读写</b>:进程发起对这片映射空间的访问,引发缺页异常,实现文件内容到物理内存(主存)的拷贝
特征
4次用户态和内核态切换
3次数据拷贝<br>
优缺点
优点<br>
简化用户进程编程<br>
读写效率提高:避免内核空间到用户空间的数据拷贝<br>
避免只读操作时的 swap 操作<br>
节约内存<br>
什么情况下使用去访问文件会更高效<br>
对文件执行随机访问时<br>
多个进程同时访问同一个文件时<br>
缺点<br>
数据传输过程中依然需要一次 CPU 拷贝<br>
内存映射技术是一个开销很大的虚拟存储操作<br>
由于 mmap 使用时必须实现指定好内存映射的大小,因此 mmap 并不适合变长文件<br>
特殊情况<br>
尽管可以减少一次 I/O 拷贝,但由于的实现很复杂,调用将会带来额外的开销,因此在一些情况下,没有使用的必要
访问小文件时,直接使用传统io或将更加高效
单个进程对文件执行顺序访问时(sequential access),使用几乎不会带来性能上的提升
mmap 的主要额外开销为<br>
mmap 等调用的开销<br>
缺页中断的开销<br>
页面首次使用触发的分配和清零开销
场景<br>
<b><font color="#f44336">多个线程</font></b>以只读的方式同时访问一个文件<br>
mmap 非常适合用于<font color="#f44336"><b>进程间通信</b></font><br>
mmap 虽然比 sendfile 等机制多了一次 CPU 全程参与的内存拷贝,但是用户空间与内核空间并不需要数据拷贝,因此在正确使用情况下并不比 sendfile 效率差;
代码
sendfile<br>
<b>DMA</b>的四次切换+及四次拷贝<br>
问题:<b>如果数据没有发生修改,只是传输</b>
sendfile函数<br>
避免了内核缓冲区和用户缓冲区之间的拷贝
流程
sendfile+DMA scatter/gather<br>
流程<br>
正在的零拷贝
Socket缓冲区<br>
进程和线程<br>
进程<br>
进程的概念<br>
进程的状态<br>
五状态模型<br>
七状态模型<br>
进程的控制结构
PCB
每个 PCB 是如何组织的?<br>
进程的切换<br>
进程上下文切换有的场景<br>
线程<br>
线程的上下文切换<br>
线程是不是属于同一个进程<br>
不属于同一进程
同一进程<br>
进程调度<br>
什么时候调度进程<br>
以什么原则来调度进程<br>
进程调度算法(可以采用的调度策略)<br>
先来先服服务<br>
时间片轮转<br>
需根据业务场景配置合适的时间片
最短作业优先<br>
最短剩余时间优先<br>
优先级调度<br>
多级反馈队列调度<br>
CFS:Linux的完全公平调度<br>
那CFS应该什么时候进行任务切换呢?<br>
示例<br>
任务最小时间片:min_granularity<br>
给任务分配权重<br>
进程间通讯<br>
多路复用<br>
文件描述符<br>
fd 与 socket 关系<br>
从阻塞 I/O 到 I/O 多路复用
同步/异步、阻塞/非阻塞<br>
阻塞非阻塞<br>
同步异步<br>
简单的记忆方法
Java 中的BIO,NIO和AIO<br>
BIO同步阻塞<br>
NIO同步非阻塞<br>
AIO异步非阻塞<br>
小结<br>
IO模型详解<br>
IO操作<br>
IO操作分为两种动作<br>
IO调用:IO调用是由进程(应用程序的运行态)发起<br>
IO执行:IO执行是操作系统内核的工作<br>
两个过程<br>
准备数据阶段<br>
拷贝数据阶段<br>
IO过程包括以下几个步骤<br>
阻塞IO模型<br>
非阻塞IO模型(NIO)
非阻塞IO的流程
存在问题<br>
IO多路复用模型<br>
核心思路<br>
IO多路复用之select<br>
优点
缺点<br>
IO多路复用之poll<br>
poll解决了连接数限制问题
IO多路复用之epoll<br>
函数
epoll_create是创建一个epoll句柄,每个进程只调用一次<br>
epoll_ctl是注册要监听的事件类型,每个socket事件创建只调用一次<br>
epoll_wait则是等待事件的产生。类似select,等待有就绪的fd,需要调用多次<br>
epoll惊群现象(重要)<br>
信号驱动IO模型<br>
关于ET、LT两种工作模式(重要)<br>
水平触发level trigger LT(状态达到)<br>
边缘触发edge trigger ET(状态改变)<br>
选择<br>
IO 模型之异步IO(AIO)<br>
<b>同步</b>阻塞IO<br>
适合的场景<br>
优缺点<br>
优点<br>
并发量较少的网络通信场景较高效<br>
应用程序开发简单<br>
缺点<br>
不适合并发量较大的网络通信场景<br>
当使用阻塞 I/O 时,需要使用多线程来处理多个文件描述符
<b>同步</b>非阻塞IO<br>
优缺点<br>
优点
在内核IO数据准备阶段不会阻塞应用线程,适合对线程阻塞敏感的网络应用<br>
缺点
轮询查询内核IO数据状态,耗费大量CPU,效率低
需要不断轮序,增加开发难度
<font color="#f44336">每次发起系统调用,只能检查一个文件描述符是否就绪</font>。当文件描述符很多时,系统调用的成本很高(遍历、每次都要用户态-内核态切换)
多路复用<br>
多路复用的基本工作流程<br>
linux三种状态管理器<br>
select<br>
poll<br>
epoll
并发连接不高的情况下,多线程+阻塞I/O方式可能性能更好
主要优点<br>
可以通过一次系统调用,检查多个文件描述符的状态
缺点<br>
I/O 多路复用引入了一些额外的操作和开销,性能更差
优点
但是好处是用户可以在一个线程内同时处理多个 I/O 请求。如果不采用 I/O 多路复用,则必须通过多线程的方式,每个线程处理一个 I/O 请求。后者线程切换也是有一定的开销的。
进程阻塞是否占用cpu?
创建socket
工作队列<br>
等待队列<br>
唤醒进程<br>
内核接收网络数据全过程<br>
接收数据
唤醒进程<br>
<b><font color="#f44336">多路复用</font></b>-SELECT
源码<br>
select函数<br>
select的流程<br>
优缺点<br>
优点<br>
跨平台,几乎所有平台都支持<br>
时间精度高,ns 级别<br>
缺点
单个进程能够监视的文件描述符的数量存在最大限制<br>
时间复杂度<br>
内存拷贝<br>
<b><font color="#f44336">多路复用</font></b>-poll<br>
<b><font color="#f44336">多路复用</font></b>-epoll
基于<b><font color="#f44336">事件驱动</font></b>的I/O方式
API<br>
int <b>epoll_create</b>(int size)<br>
int <b>epoll_ctl</b>(int epfd, int op, int fd, struct epoll_event *event)<br>
int <b>epoll_wait</b>(int epfd, struct epoll_event * events, int maxevents, int timeout);
epoll比select/poll的优越之处<br>
epoll初始化时<br>
epoll高效主要原因之一<br>
流程简介<br>
原理和流程<br>
1、epoll_create<br>
2、epoll_ctl
3、接收数据
4、epoll_wait<br>
实现细节<br>
就绪队列数据结构<br>
epoll_wait两种触发方式(<b><font color="#f44336">有事件发生时触发</font></b>)<br>
水平触发(LT)<br>
边缘触发(ET)<br>
select、poll、epoll对比<br>
使用MMAP内存映射技术
0 条评论
下一页