写点什么

Linux 内核分析学习路线总结(内核人员必看)

发布于: 1 小时前

1、Linux 体系架构(文末附上学习思维导图)

如上图所示,从宏观上来看,Linux 操作系统的体系架构分为用户态和内核态。

  内核从本质上看是一种软件——控制计算机的硬件资源,并提供上层应用程序运行的环境。

  用户态即上层应用程序的活动空间,应用程序的执行必须依托于内核提供的资源,包括 CPU 资源、存储资源、I/O 资源等。

用户态的应用程序可以通过三种方式来访问内核态的资源:

1)系统调用

2)库函数

3)Shell 脚本

这三种方式也在上图中有所体现。

二、Linux 内核的启动过程

从该图可以看出,start_kernel 是初始化内核的起点,该函数在 init 目录下的 main.c 文件里。

start_kernel 函数做了大量的初始化,比如 CPU、内存等各种硬件设备进行初始化

而它的最后一项初始化 rest_init 函数,会对进程空间做初始化,至此,Linux 内核就启动起来了。

三、进程管理

进程是已启动的可执行程序的运行实例,进程有以下组成部分:

• 已分配内存的地址空间;

• 安全属性,包括所有权凭据和特权;

• 程序代码的一个或多个执行线程;

• 进程状态

进程的生命周期

进程的状态

Linux 的进程总共有 6 种状态

1、new(初始状态,刚创建的一个进程,需要等待被调度)

2、Runnable(就绪状态)

3、RUNNING(可执行状态)

4、Sleeping(睡眠状态)

5、STOPPED(暂停状态)

6、ZOMBIE(退出状态,进程成为僵尸进程)

它们之间的切换如下:

有了这么多状态,自然就少不了进程切换

比如说一个进程执行完了进入僵死状态,CPU 就会重新从就绪队列里取出一个进程让其进入运行状态,又或者一个进程缺少资源进入睡眠状态,需要等待它需要的资源到来等等

进程切换本质上说有两步组成:

1.切换页全局目录以安装一个新的地址空间。

2.切换内核态堆栈和硬件上下文。

四、中断管理

  前面说了用户态和内核态,那肯定也少不了用户态和内核态的切换,

  比如说 C 函数库中的内存分配函数 malloc(),它具体是使用 sbrk()系统调用来分配内存,当 malloc 调用 sbrk()的时候就涉及一次从用户态到内核态的切换,类似的函数还有 printf(),调用的是 wirte()系统调用来输出字符串,等等

  到底在什么情况下会发生从用户态到内核态的切换,一般存在以下三种情况:

  1)即上面说的用户态到内核态的切换的三种方式:库函数、系统调用或者 shell 命令。

  2)异常事件: 当 CPU 正在执行运行在用户态的程序时,突然发生某些预先不可知的异常事件,这个时候就会触发从当前用户态执行的进程转向内核态执行相关的异常事件,典型的如缺页异常。

  3)外围设备的中断:当外围设备完成用户的请求操作后,会像 CPU 发出中断信号,此时,CPU 就会暂停执行下一条即将要执行的指令,转而去执行中断信号对应的处理程序,如果先前执行的指令是在用户态下,则自然就发生从用户态到内核态的转换。

  其实说白了就是通过中断(系统调用也是一种中断,软中断的陷阱)

  CPU 级别的中断信号处理过程如下:

    1、确定与中断或异常相关联的向量 i

    2、读取 idtr 寄存器的值,找到 IDT 的基址,通过查询 IDT,找到 第 i 项对应的内容。

    3、从 gdtr 寄存器获得 GDT 的基地址,并在 GDT 中查找,以读取 IDT 表项中的段选择符所标识的段描述符。

    4、确定中断是由授权的发生源发出的。

      中断:需要比较 CPL 和 GDT 中的 DPL。中断处理程序的特 权不能低于引起中断的程序的特权。

      编程异常:需要比较 CPL 和 IDT 中的 DPL。

    5、检查是否发生了特权级的变化,一般指的是用户态陷入内核 态。      如果是用户态陷入内核态,控制单元要使用新的特权级堆栈。      保存 ss 和 esp,并用新的堆栈的值填充。

    6、如果是故障,用引起故障的指令修改 cs 和 eip,以便异常处理 后再次执行。

    7、在堆栈中保存 eflags/cs/eip 的内容。

    8、如果有硬件出错码,则保存。

    9、使用 IDT 中第 i 项中的段描述符和偏移量填充 cs 和 eip。

五、时钟管理

时钟一般分为两个部分:实时时钟和计时器/定时器。实时时钟: 一般靠电池供电,即使系统断电,也可以维持日期和时间。 实时时钟独立于操作系统,所以也被称为硬件时钟,为整个系统提供一个计时标准。定时器/计数器: 实时内核需要一个定时器作为系统时钟(或称 OS 时钟),并由实时内核控制系统时钟工作。 一 般情况下,系统时钟的最小粒度是由应用和操作系统的特点决定的。实时时钟是系统时钟的时间基准,实时内核通过读取实时时钟来初始化系统时钟,此后二者保持同步运行,共同维系系统时间。

当时钟初始化(即 tick_init、Time_init)后,系统就会周期性的调用 tick_periodic 这个函数,该函数的功能为:

  • 更新自系统启动以来所经过的时间(Jiffies)

  • 更新时间和日期(RTC)

  • 确定当前进程的执行时间,考虑是否要抢占

  • 更新资源使用统计计数

  • 检查到期的软定时器

六、文件系统

  Linux 系统启动时,首先挂载根文件系统,之后可以自动或手动挂载其他的文件系统,这些文件系统要挂载到挂载点上,与虚拟文件系统(Virtual File System)和通用块设备层(General Block Device Layer)建立联系。因此,一个系统中可以同时存在不同的文件系统。

  虚拟文件系统 VFS 的作用即屏蔽底层各个文件系统之间的实现差异,给用户提供统一的接口。

  它的主要数据结构如下:

  • 超级块对象:保存文件系统信息

  • 文件对象:保存已打开的文件和进程的交互信息。

  • 目录项对象:存放目录项和文件链接的信息。

  • 索引结点对象:存放具体文件的一般信息。

  • 在磁盘中的数据结构:

  • 引导控制块:操作系统的初始引导块

  • 盘控制块:磁盘信息等

  • 文件控制块:文件属性。

  • 目录结构:组织管理文件。

  • 在内存中的数据结构:

  • 系统打开文件表

  • 进程打开文件表

  文件打开流程:

    1、打开文件即使用 open 函数,它首先通过按名查找,看在高速缓存中有没有查找的 inode,如果有那么对其进行引用并加 1。如果没有将创建新的 vfs 的 inode 对象和目录项对象等。

    2、 Open 函数调用的系统服务例程是 sys_open 函数,其接受的参数为文件目录和访问的模式。如果文件存在则返回一个文件描述符 fd,如果不存在则返回-1.

    3、 Read 和 write 函数分调用的服务例程是 sys_read 和 sys_write,接受三个参数。分别是一个文件描述符 fd,一个对数据缓存的地方 buf,和需要传输的数据的多少 count。Read 对将文件读入缓存区。Write 则相反。

  文件关闭流程:

    1、用户程序通过 close ( )系统调用关闭打开的文件,该函数接收的参数为要关闭文件的文件描述符。

    2、内核调用 sys_close ( )函数。

七:学习思维导图以及 Linux 内核相关学习视频,清晰版导图可以点击:linux内核学习资料 获取



用户头像

Linux服务器开发qun720209036,欢迎来交流 2020.11.26 加入

专注C/C++ Linux后台服务器开发。

评论

发布
暂无评论
Linux内核分析学习路线总结(内核人员必看)