Linux内核学习总结

来源:互联网 发布:芒果tv会员账号淘宝 编辑:程序博客网 时间:2024/06/03 16:37

周恺祺+原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

一、学习目录

  1. 计算机是如何工作的——通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的
  2. 操作系统是如何工作的——完成一个简单的时间片轮转多道程序内核代码
  3. 构造一个简单的Linux系统MenuOS——追踪分析Linux启动过程
  4. 扒开系统调用的三层皮(上)——使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
  5. 扒开系统调用的三层皮(下)——分析system_call中断处理过程
  6. 进程的描述和进程的创建——分析Linux内核创建一个新进程的过程
  7. 可执行程序的装载——Linux内核如何装载和启动一个可执行程序
  8. 进程的切换和系统的一般执行过程——理解进程调度时机跟踪分析进程调度与进程切换的过程

二、学习总结

本课程从理解计算机硬件的核心工作机制(存储程序计算机和函数调用堆栈)和用户态程序如何通过系统调用陷入内核(中断异常)入手,通过上下两个方向双向夹击的策略,并利用实际可运行程序的反汇编代码从实践的角度理解操作系统内核,然后开始分析Linux内核源代码,从系统调用陷入内核,进程调度与进程切换,最后返回到用户态进程,通过仔细分析梳理这一过程,并推广到硬件中断、缺页异常等内核执行路径,最终能从本质上把握Linux内核的实质,乃至在头脑中演绎Linux系统的运行过程。(摘自课程引言)。
下面对每次课程做一次简单的回顾

1、 计算机是如何工作的

(1)作为Linux系统分析的第一节课,孟老师以一段简单的汇编代码为例,介绍了CPU计算模块、寄存器和内存是如何配合工作的。
冯诺依曼体系结构的计算机,又叫存储程序计算机,从硬件的角度来看,其工作模型是CPU依次读取内存中的指令来完成工作。
(2)计算机工作的基本原理?
计算机的基本原理是存储程序和程序控制。预先要把指挥计算机如何进行操作的指令序列(称为程序)和原始数据通过输入设备输送到计算机内存贮器中。每一条指令中明确规定了计算机从哪个地址取数,进行什么操作,然后送到什么地址去等步骤。
计算机在运行时,先从内存中取出第一条指令,通过控制器的译码,按指令的要求,从存储器中取出数据进行指定的运算和逻辑操作等加工,然后再按地址把结果送到内存中去。接下来,再取出第二条指令,在控制器的指挥下完成规定操作。依此进行下去。直至遇到停止指令。

2、 操作系统是如何工作的

(1)本次课简单的模拟了内核代码。主要包括函数调用堆栈、函数堆栈框架、内核的初始化、中断、进程上下文切换过程的简述以及基于时间片轮转的多道程序模拟
(2)课程总结:
操作系统的三大法宝:存储程序计算机、函数调用堆栈、中断机制。
操作系统的两把宝剑:中断赏析文、进程上下文的切换
操作系统的核心功能:进程调度和中断机制,通过与硬件的配合实现多任处理,再加上上层应用软件的支持,最终变成可以使用户容易操作的计算机系统
中断:可以多个程序同时运行,中断发生时,由CPU和内核代码同时实现了保存现场和恢复现场
进程切换:当正在运行的进程等待其他的系统资源时,Linux内核将取得CPU的控制权,并将CPU分配给其他正在等待的进程,进程切换机制包括esp的切换、堆栈的切换

3、构造一个简单的Linux系统MenuOS

(1)本周学习了内核源码和构造Linux 系统MenuOS,分析了内核的源码、内核的启动过程以及start_kernel
总结:道生一(start_kernel -> cpu_idle),一生二(kernel_init和kthread),二生三(生成0、1、2号进程)、三生万物(1号进程是所有用户态进程的祖先,2号进程是所有内核线程的祖先)
(2)通过这节课,以跟踪LInux启动过程为例,我还学习到了如何通过冻结CPU的启动,来进行跟踪调试代码。虽然这次实验耗时较长,因为调试研究了很长时间,但是为后续的实验打下了良好的基础

4、 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用)

(1)系统调用的三层皮:xyz(API)、system_call(中断向量)、sys_xyz(中断向量所对应的中断服务程序)
(2)系统调用过程
当用户态进程调用一个系统调用时,CPU切换到内核态开始执行一个内核函数。在Linux中通过执行$0x80来执行系统调用的。中断向量0x80将system_call 联系起来。系统调用号就可以调用中断服务程序了。系统调用号将xyz和sys_xyz关联起来,system_call是Linux中所有系统调用的入口点,每个系统调用至少有一个参数,即由eax传递的系统调用号。
这里写图片描述

5、 分析system_call中断处理过程

(1)本周使用gdb跟踪分析一个系统调用内核函数(即我上一周使用的get_ppid)系统调用
(2)中断处理过程
第一步:SAVE_ALL保存现场
第二步:确定中断信息,将系统调用号通过eax传入,通过sys_call_table查询到调用的系统调用函数,然后跳转到相应的程序进行处理
第三步:处理中断
第四步:RESTORE_ALL恢复系统调用时的现场,iret返回到用户态
(3)下图为当时做的系统调用中断的流程图
这里写图片描述

6、分析Linux内核创建一个新进程的过程

(1)Linux中创建进程一共三个函数:
fork:创建子进程
vfork:与fork类似,但是父子进程共享地址空间,而且子进程先于父进程运行
clone:主要用于创建线程
(2)进程描述符提供了内核所需要的进程信息。其中可以通过fork\vfork\sys_clone等API来创建一个子进程,他们在linux内核中对应的系统调用分别是sys_fork sys_vfork sys_clone函数。这些函数最终都会调用do_fork完成子进程的创建。
(3)do_fork主要是赋值了父进程的task_struct,然后修改必要的信息。从而得到子进程的task_struct

7、 Linux内核如何装载和启动一个可执行程序

Linux内核装载和启动一个可执行程序:
(1)首先需要创建新进程,新进程调用execve()系统调用执行指定的ELF文件,之后再调用内核的入口函数sys_execve(),sys_execve()服务例程修改当前进程的执行上下文;
(2)系统调用终止后,新进程开始执行放在可执行文件中的代码,也就是执行在当前目录下显示文件的功能。 当ELF被load_elf_binary()装载完成后,函数返回至do_execve(),再返回至sys_execve()。
(3) ELF可执行文件的入口点取决于程序的链接方式,对于静态链接的可执行文件,elf_entry就是指向可执行文件里边规定的那个头部,即main函数对应的位置,若这个可执行文件是需要依赖其它动态链接库的话,则elf_entry就是指向动态链接器的起点

8、 理解进程调度时机跟踪分析进程调度与进程切换的过程

本次课主要学习了关于进程切换和整体执行过程。包括Linux
进程调度算法简介、进程切换代码分析、switch_to理解、进程相关数据结构分析(摘自我的实验报告)
最一般的情况:正在运行的用户态进程X切换到运行用户态进程Y的过程

正在运行的用户态进程X
1. 发生中断——save cs:eip/esp/eflags(current) to kernel stack,then load cs:eip(entry of a specific ISR) and ss:esp(point to kernel stack).
2. SAVE_ALL //保存现场
3. 中断处理过程中或中断返回前调用了schedule(),其中的switch_to做了关键的进程上下文切换
4. 标号1之后开始运行用户态进程Y(这里Y曾经通过以上步骤被切换出去过因此可以从标号1继续执行)
5. restore_all //恢复现场
iret - pop cs:eip/ss:esp/eflags from kernel stack
6. 继续运行用户态进程Y

几种特殊情况

通过中断处理过程中的调度时机,用户态进程与内核线程之间互相切换和内核线程之间互相切换,与最一般的情况非常类似,只是内核线程运行过程中发生中断没有进程用户态和内核态的转换;
内核线程主动调用schedule(),只有进程上下文的切换,没有发生中断上下文的切换,与最一般的情况略简略;
创建子进程的系统调用在子进程中的执行起点及返回用户态,如fork;
加载一个新的可执行程序后返回到用户态的情况,如execve;

三、学习感想

  1. 通过本次学习,我对之前学习到的Linux内核的知识有了更深一步的了解,也更熟悉了Linux操作系统的一些使用方法技巧。对以后的应用打下了很好的基础
  2. 视频课堂的教学方式延续了上学期高软的教学方法,适合同学们反复学习,巩固知识点,如果老师能够再充分利用课堂时间,再传授一些好的学习方法及您对这门课程的学习感悟就更好了。相信我们能够收获的更多!
  3. 虽然课程学习结束了,但是我仍然有很多欠缺的知识点需要在后续的学习过程中补全,不断的完善自我,多向老师同学们学习,和大家一起进步,再次感谢老师的精彩讲授和负责的教学态度!
0 0
原创粉丝点击