付何山+原创作品转载请注明出处+《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000;
导读:本文分为两个部分。第一部分将对孟宁老师课程内容分章节进行总结,第二部分是个人的心得总结。
章节博客链接
本章先介绍了冯诺依曼体系结构,而后从一个简单的有调用子函数的C语言程序入手,先将之使用gcc命令(-S)生成为汇编代码,从而介绍了计算机的汇编指令(如mov,call,ret等),以及一些寄存器的作用(如esp,ebp)等。
这章的博客中我自己手画了函数调用过程中堆栈的变化过程,对于更深入了解这个过程有了很大的帮助。
章节博客链接
本章的内容可以归结为两个词:三个法宝(存储程序计算机、函数调用堆栈、中断机制)和两把宝剑(中断上下文的切换、进程上下文的切换)。
在本章的实验中,我使用了老师的github上提供的部署方案,在自己的系统上部署了实验环境,于是实验的速度就大幅度的提高了。具体的部署方案,可以参见我上方提供的本章的博客链接。
本章的mykernel代码实际上是仿照linux内核写的一个简单版的关于进程切换的部分。代码的主要难点在于进程切换时,当把esp替换以后实际上已经进入了要调入的进程的环境中了。而前一个进程在其后保存完eip后已经保存完整了。代码中当然还有一些细节(比如针对从未被调用过的进程和已被调用过的进程其切换方式不同),详情请参阅上方的博客。
章节博客链接
本章的主要内容正如题目所说就是分析Linux内核的启动过程,重点在0、1、2号进程的生成,使用的是gdb(后面的实验几乎离不开它)对Linux代码进行跟踪。跟踪的过程相对来说不算太复杂,只要知道断点(do_fork,start_kernel等)设在哪儿就好办了(虽然一开始没头脑的找起来其实还是有点难的)。
章节博客链接
本章的主要内容既如题目所说是使用库函数API和嵌入汇编代码两种方式使用同一个系统调用,观察结果,并弄清二者的内部实现。在本次实验中,我选择了输出进程号(getpid)的方法,在同一个文件中使用上述两种方式进行输出得到了相同的结果,证明二者可以得到相同的结果。(注意:如果放在两个文件分次执行是不太可能会得到相同的进程号的)系统调用的三个层次可以用孟宁老师的下图来描述:
章节博客链接
本章的内容相比起上一章更加底层,上一章像是框架性的东西,而这一章则是弄清楚system_call究竟是怎么实现的,这对于描述整个linux的运行过程是很有必要的(毕竟跟第三章讲的三大法宝、两把宝剑都有关系)。主要的内容要点如下:
章节博客链接
本章的一开始我先将部署内核到自己电脑的步骤进行了梳理,给出了较为详细的部署方案。
本章的具体内容其实也是对前面章节的深化,在第三章我们提到了对do_fork设置断点观察Linux内核的启动过程,而这一章节则是深入do_fork,了解do_fork的究竟干了些啥。然而其实这个实现我们是见过的,最关键的点还是在于之前第二章mykernel中提到的在一段嵌入式汇编代码中其实进去跟出去是两个不同的进程环境这一件事儿。了解了上面这点以后,剩下的就是对进程里面有什么的探究(PCB的结构等),以及哪些复制函数或宏对哪一部分进行了复制。
章节博客链接
上一章实际上是对fork进行的探究,这一章则是对exec一族函数进行探究了。主要需要理解的就是,当一个进程执行完exec一族函数成功调用一段新程序时,旧进程的环境就已经被替换掉了。也就是说其实这个进程金蝉脱壳换了个壳重新复活了。至于静态链接和动态链接只是在执行这一族函数时是直接使用elf文件elf_entry的值还是使用ld进行链接的区别了。
章节博客链接
本章是课程的最后一章,其实也算是一个集大成的章节,描述的是整个Linux的一般执行过程。
首先讲了三种调度的时机(包括内核线程和用户进程,当然用户进程只能是被动调度):
而后主要通过对关键函数switch_to的跟踪分析以及函数解读清晰地展示了堆栈如何变化的。至于调度算法则不是课程的重点,只需要知道有这么一个调度算法选出下一个进程即可。
通过半个学期的学习,我觉得我还是不能说我掌握了Linux内核的东西(甚至也不能说我入了门,因为我现在看ULK还是有想撕书的感觉),但是我可以说我好像get到了一些能够帮助我去了解内核的工具(源码,qemu,gdb等)。
这个课程的内容实际上完全可以看成是一般操作系统课程进程那一章的一个深入,感觉比操作系统更充实一些的地方就在于它让你真真正正的看到了实现,而不是滞留于理论。
个人感觉课程设置上还是有一些奇怪的地方:
1、比如后半部分有些课程的前引部分太多了,实际上最希望我们掌握的重点是A,但可能视频篇幅有1/3是在讲B。
2、写博客虽然是一个很好的检验方法,能够帮助你理清思路,弄明白你在干什么,但是全课程都用写博客的方式,感觉就像是要教会一个程序员一定要会表达自己一样。(当然我不是说表达不重要,我只是觉得表达对于某些人来说他不一定是必要的成功因素)希望老师能有更加好的作业考核方式(可能对于我来说……因为我真的很懒)。
当然啦,瑕不掩瑜(以上只是我的一些偏见),孟宁老师的课我还是很喜欢的(因为我这个人比较懒,探究心比较弱,对于比较详细的视频讲解实际上比较偏爱),今后也会一如既往的支持孟宁老师,希望老师加油!
P.S. 顺便吐槽一句,csdn的markdown编辑器也是不一般的坑 =-=
全部课程博客链接
[网易云课堂]Linux内核分析(一)——简单C程序汇编代码分析
[网易云课堂]Linux内核分析(二)—— mykernel内核部署及简单时间片轮转程序分析
[网易云课堂]Linux内核分析(三)—— 跟踪分析Linux内核的启动过程
[网易云课堂]Linux内核分析(四)—— 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
[网易云课堂]Linux内核分析(五)—— 分析system_call中断处理过程
[网易云课堂]Linux内核分析(六)—— 分析Linux内核创建一个新进程的过程
[网易云课堂]Linux内核分析(七)—— Linux内核如何装载和启动一个可执行程序
[网易云课堂]Linux内核分析(八)—— 理解进程调度时机跟踪分析进程调度与进程切换的过程