【万子惠 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000】
计算机是如何工作的
这部分从最简单的汇编代码以及堆栈调用开始引入
大部分是曾经学过的内容,这一块比较特别的是冯诺依曼原理。
基本思想:存储程序与程序控制。
计算机工作的三个法宝:
-
存储程序计算机工作模型
-
函数调用堆栈
-
中断
操作系统是如何工作的
堆栈调用:
有压栈必有出栈,有生必有死
main开始执行=>调用p1=>压栈参数
=>压栈eip
=>ret
操作系统的两把剑:
中断上下文
进程上下文切换
构造一个简单的Linux系统MenuOS
- 实验中的menu程序以及跟踪分析的方法
- 一些重要的内核代码(都在原博客中啦)
扒开系统调用的三层皮(上)
-
用户态,内核态,和中断以及他们的关系
中断的完整过程:
1)inter rupt(ex: int 0x80)_save cs:eip/ss:eip(当前栈顶)/eflcgs(标志寄存器)(current) to kernel stack , then load cs:eip lentry of a specific ISR (加载新入口内核信息)) and ss:eip (point to kernel stack) 2)SAVE_ALL | /*进程调度(不是必经)*/ | 3)RESTORE_ALL(内核代码完成中断服务,发生进程调度) 4)iret
-
系统调用
三层皮:
1)API 2)中断向量 3)中断服务程序
具体调用过程
-
使用库函数API和C代码中嵌入汇编代码触发同一个系统调用(在实验部分可以具体找到)
扒开应用系统的三层皮(下)
实验中:
- 给MenuOS增加time和time-asm命令
- 使用gdb跟踪系统调用内核函数sys_time
系统调用在内核代码中的处理过程
从system_call到iret的过程
system_call的处理过程中:
xyz<=系统调用号=>sys_xyz()
int 0x80<=中断向量=>system_call
进程的描述和进程的创建
实验部分:gdb跟踪调试fork中的sys_ clone
内核三大功能:
进程管理
文件管理
内核系统
task_struct的代码分析查看
进程创建:
-
0号进程(手写)->1号进程(复制0号进程的PCB,根据其修改pid加载init可执行程序)
-
在fork中,两个进程,fork系统调用在父子进程个返回一次
1)子 pid=0 2)父 pid=子进程的id
新进程是从ret_ from_ fork开始执行
可执行程序的装载
-
可执行文件的创建——预处理、编译和链接
c代码——>1.编译器预处理.cpp(把.h文件宏替换)——>2.汇编代码.s——>3.目标代码.o——4.链接称为可执行文件a.out——>5.memory
-
三种主要文件
可重定位文件:【主要为.o文件】 可执行文件:保存一个用来执行的程序,指出exec(BA_OS)如何创建程序映像(如何加载?执行?) 共享Object文件:保存着两个连接器用来链接的数据
-
两个链接器:
链接编辑器 动态链接器
-
可执行程序、共享库和动态链接
装载可执行程序之前的工作 两种动态链接 可执行程序的装载 execve
-
庄生梦蝶
庄周(调用execve的可执行程序)入睡(调用execve陷入内核),醒来(系统调用execve返回用户态)发现自己是蝴蝶(被execve加载的可执行程序)
修改int 0x80压入内核堆栈的EIP
进程的切换和系统的一般执行过程
-
进程进度与进程调度的时机
原因:各类不同的切换需求(两种调度需求分类方式) 时机:中断处理过程
此处分为相对于
a)内核线程(只有内核态,没有用户态) b)用户进程(只能被动)
-
进程上下文切换相关代码分析
schedule细节查看
-
Linux系统的一般执行过程
最一般的情况:正在运行的用户态进程X切换到运行用户态进程Y的过程 正在运行的用户态进程X | 发生中断——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). | SAVE_ALL //保存现场 | 中断处理过程中或中断返回前调用了schedule(),其中的switch_to做了关键的进程上下文切换 标号1之后开始运行用户态进程Y(这里Y曾经通过以上步骤被切换出去过因此可以从标号1继续执行) | restore_all //恢复现场 | iret - pop cs:eip/ss:esp/eflags from kernel stack | 继续运行用户态进程Y
-
几个特殊情况
1.通过中断处理过程中的调度时机,用户态进程与内核线程之间互相切换和内核线程之间互相切换,与最一般的情况非常类似,只是内核线程运行过程中发生中断没有进程用户态和内核态的转换; 2.内核线程主动调用schedule(),只有进程上下文的切换,没有发生中断上下文的切换,与最一般的情况略简略; 3.创建子进程的系统调用在子进程中的执行起点及返回用户态,如fork; 3.内核与舞女
-
Linux系统架构和执行过程
各章读书笔记链接:
个人总结:
这一部分的慕课学习以来,自己有好好抓紧的时候,也有松懈的时候,具体情况竟然从学生作业互评的分数中就能看出来。整个课程我可以说思考是一定有收获的,本来略感散乱的章节也在最后一节课的Linux系统结构和执行过程的总览里看到了紧紧联系在一起的意味。
内核中进程管理,进程调度,内存管理...很多很多架构和处理机制联系在一起,在发挥了操作系统中对各类进程执行及处理的能力,真不能说是学懂了,但能知道是个了不起的伟大结果。
这课其实还是有难度的,有一头雾水学不下去的时候,这种时候看一看优秀的同学的学习笔记,也能够吸收更多,并且在学生互评的时候,就能看到人和人的差距。然后此处应该展望一下未来,课程还没有结束,在后半部分的学习过程当中,也希望自己学到更多。