【李行之 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 】
《Linux内核分析》 第四周
PART ONE 知识点梳理 之 基础:用户态&内核态与系统调用的关系
1.用户态、内核态区别
- 在高级别的状态下,代码可以执行特权指令,访问任意的物理地址;一般在Linux中,0xc0000000以上的地址(指的是逻辑地址)空间只能在内核态下访问;
- 在相应的低级别执行状态下,代码的掌控范围会受到限制;
2.中断处理程序
- 中断指令会在寄存器上保存一些寄存器的值放入内核堆栈,比如:用户态栈顶地址,标志寄存器,cs:eip。同时,将相关联的中端服务历程的入口加载到cs:eip,把当前的堆栈段esp也加载到CPU里面
- 中断发生之后第一件事就是保存现场;中断处理结束前的最后一件事情就是恢复现场
3.系统调用
-
系统调用的三层皮
-
xyz,system_call,sys_xyz。即:API,中断向量,服务程序
PART TWO 使用库函数API和C代码中嵌入汇编代码触发同一个系统调用
1.知识储备
-
嵌入式汇编代码的参数传递过程
-
关于系统调用号
- 通过查表可以得到API对应的系统调用号,这个参数是固定传递给eax寄存器的。如果函数有参数的话,可以利用ebx传递
2.实验过程
- 选取系统调用
- nice函数系统调用号是34,作用是改变当前进程的优先级。其参数是一个int型的变量,作为当前进程要增加的优先级级数(级数越大,优先级越小)。如果调用成功的话,返回的是当前进程改变之后的优先级(这个数值的范围只能在-20——19之间);否则返回-1
- 实验过程
-
使用函数API获取当前进程的优先级;
-
进行编译,得到结果:1
-
然后进行嵌入式汇编代码的编写
-
结果如下:
-
结果发现两次得到的结果不一样。这是为什么呢?
- 其实是因为开始的时候没有注意到nice函数返回值的意义:它返回的是当前进程被改变的优先级,也就是在原有级数的基础上加上传进去的参数。所以,两次进程的原有优先级不同,得到的结果也不同
- 第二次汇编如下:
- 其实是因为开始的时候没有注意到nice函数返回值的意义:它返回的是当前进程被改变的优先级,也就是在原有级数的基础上加上传进去的参数。所以,两次进程的原有优先级不同,得到的结果也不同
PART THREE 总结
本周的自学过程与前两周比较更能锻炼自学能力:其一,在编写C代码以及嵌入式汇编代码的过程中,我查阅了很多系统调用的作用、参数值和返回结果,并且筛选出了我认为比较有代表性的(传递一个参数、返回一个int型变量的nice()函数);其二,对于前后两次代码意义相同但是结果不同的情况,我最初以为是自己编写错误,还误打误撞地学会了检验函数是否出错的方法(也就是errno变量的使用),并且更加深刻得理解了nice()函数的意义。