回顾
不知不觉中Linux内核课程已经结束,孟宁老师用幽默、探讨式的教学方法以Linux源码为依据,围绕系统调用、进程创建、进程切换,系统性的巧妙的讲述了Linux内核中最为核心的知识。下面对每周的课程进行简要的回顾
计算机是如何工作的?
更准确的说这部分是描述程序是怎样借助堆栈和寄存器运行起来的,以及如何对一简单程序进行汇编和分析该程序的堆栈变化。这部分还大量的介绍了汇编指令的作用,如ret 操作:相当于 pop %ip ,call操作:相当于 push %ip; mov $address, %ip leave操作:相当于movl %bp, %sp; popl %bp等等。
把.c文件转为汇编,并分析堆栈操作系统是如何工作的?
这部分中孟宁老师详细生动的讲述了函数自己是如何借助堆栈进行调用和返回的,同时还教授了如何在C程序中内嵌汇编代码,最后借助mykernel让大家获得一个关于进程如何切换的整体认识。
mykernel的运行与初步分析构造一个简单的Linux系统MenuOS
这部分主要分析了start_kernel函数的执行过程,如何使用gdb进行跟踪,pid=0进程和pid=1进程是如何来的,及idel进程是由那个进程变化来的。
跟踪内核从start_kernel到init进程启动扒开系统调用的三层皮(上)
这部分主要分析了用户态、内核态,用户态如何切换到内核态,以及API与系统调用的关系,程序如何实现系统调用。
使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用扒开系统调用的三层皮(下)
这部分主要分析系统调用在内核中的处理过程,如图
分析system_call中断处理过程进程的描述和进程的创建
这部分主要分析了内核中的进程控制块PCB它的数据结构task_struct,以及fork的系统调用的执行过程,实验部分要求使用gdb追踪fork的执行过程;
分析Linux内核创建一个新进程的过程可执行程序的装载
这部分把前面的进程创建、系统调用知识整合起来, Linux通过fork系统调用创建一个新进程,在通过sys_execve系统调用,负责将新的程序代码和数据替换到新的进程中,在内核的 start_thread函数中,设置 给新进程设置新的ip ,接下来返回执行新的进程代码。
Linux内核如何装载和启动一个可执行程序进程的切换和一般程序的执行
这里与第二周的课程进程首尾呼应,有了中间关于进程创建和系统调用的知识后,可以比较好的理解进程的切换。进程切换的核心函数是switch_to,进程调度的顺序是schedule–>_schedule–>pick_next_task,context_switch–>switch_to。Linux系统的一般执行过程主要在进程X切换到进程Y:
正在运行的用户态进程X–>发生中断–>SAVE_ALL–>中断处理过程中或中断返回前调用了schedule()–>开始运行用户态进程Y–>restore_all–>iret–>继续运行用户态进程Y
理解进程调度时机跟踪分析进程调度与进程切换的过程
总结
从Linux内核这门课中学到的东西比较多,同时遇到的问题也比较多,孟宁老师十分鼓励我们在内核的源码中找到猜想的证据,不管课堂上教授的实用的技能,比如gdb追踪,内嵌汇编,分析堆栈等等,至少对Linux内核源码没有第一次见到的那种恐惧,偶尔还会为Linux解决问题的方法感到惊叹,可以说这门课对改善动手能力比较有帮助。
黄 玉 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000