学习Linux内核的心得

自从学习了Linux内核之后,我开始对linux系统是怎样运行的有了初步的了解,并开始对linux产生了浓厚的兴趣。以下是我学习linux的一些总结:

1、关于计算机将c代码转换成汇编代码的过程秒速

2、基于时间片轮转多道程序内核代码分析操作系统的工作过程  

3、跟踪分析Linux内核的启动过程

4、使用API和C代码中嵌入汇编实现同一个系统的调用

5、基于从system_call到iret的过程分析系统调用过程

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

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

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

在学习了这么多课程之后,我了解了Linux内核启动通过start_kernel这个函数分为两部分,在此之前是汇编代码完成初始化和环境配置;在此之后是按照c让内核中的模块初始化,初始化完毕就是启动init进程,紧接着start_kernel就会调用rest_init函数,产生1号进程(此处需要注意:因为init_task是静态制造出来的,pid=0)。此时init_task的任务基本已经结束了,它会沦为一个idle task,在init_idle中将会把init_task加入到CPU运行队列中,当运行队列中没有别的就绪进程时,init_task将会被调用,它的核心是一个while(1)循环,在循环中它将会调用schedule函数以便在运行队列中有新的进程加入时切换到该新进程上。

而系统调用可以用API函数直接调用或者在C语言中嵌入汇编代码来进行调用,但两者的本质是一样的,都需要使用系统调用号,只不过API函数已经把系统调用号封装起来了,与内核系统调用形成了映射关系。

当然进程的创建也是相当重要的,fork创建的新进程是和父进程一样的副本(除了pid和ppid),都包含有效的uid和gid,进程组合会话id,环境,资源等等。通过  实验以及代码分析,可以得出:在do_fork中:copy_process管理子进程运行的准备,wake_up_new_task作为子进程forking完成。 linux为每个由父进程复制而来的进程创建子进程; linux为每个新创建的进程动态的分配一个task_struct结构;fork被调用一次,返回两次。

最重要的还是了解进程调度的时机以及进程切换的过程,学习完这门课程之后,我是这么总结的:

1、Linux中进程调度与进程切换过程:
schedule——(sched_submit_work;__schedule)——(preempt_disable;context_switch;sched_preempt_enable_no_resched)—(prepare_task_switch;switch_mm;switch_to;barrier;finish_task_switch)——__switch_to。
2、Linux系统一般执行过程
(1) 正在运行的用户态进程X
(2) 发生中断----save cs:eip/esp/eflags(current) to kernel stack,then load cs:eip(entry of a specific ISR)
add ss:esp(point to kernel stack)
(3) SAVE_ALL //保存现场
(4) 中断处理过程中或中断返回前调用了schedule(),其中的switch_to做了关键的进程上下文切换
(5) 标号1之后开始运行用户态进程Y(这里Y曾经通过以上步骤被切换出去过因此可以从标号1继续执行)
(6) restore_all //恢复现场
(7) iret - pop cs:eip/ss:esp/eflag from kernel stack
(8) 继续运行用户态进程Y


实验总结

在学习完此课程后,我对linux系统内核又有了更深刻的了解,我觉得我最大的收获就是窥探了linux内核运作的机制,系统是怎么进行进程创建的,堆栈是怎么工作的,系统调用是怎么实现的等等。但是学习完课程后还是有点遗憾的,就是始终没怎么弄懂任务切换的详细过程,只是知道大概流程,比如为何每次将1f存入到prev->thread.ip中,即保存前一个任务的eip值,那样岂不是每次切换任务时都是将1f存入到prev->thread.ip中,而切换回来时都得从1f开始。



庄华健

《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

你可能感兴趣的:(学习Linux内核的心得)