扒开系统调用的三层皮
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了扒开系统调用的三层皮相关的知识,希望对你有一定的参考价值。
张潇月《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
通过库函数与系统调用沟通。
用户态和内核态:高的执行级别下,代码可以执行特权指令,访问任意物理地址,这就是内核态。低级别的就是用户态。
为什么要有权限分级?让操作系统更加稳定,防止程序员的用户态代码使系统崩溃。
intel x86 CPU上有四种执行指令的级别0-3,Linux只使用两种,0是内核态,3是用户态。
如何区分用户态和内核态?在内核态时我们可以访问cs eip是任意的地址,然而用户态只能访问0x0000000-0xbfffffff的地址空间(地址空间是逻辑地址不是物理地址)
中断处理是从用户态进入内核态的主要方式!系统调用只是一种特殊的中断。
寄存器上下文切换:用户态切换到内核态时,必须要要把用户态的寄存器上下文保存起来,同时要把内核态寄存器上下文的值保存在对应地方。如:用户态栈顶地址、当时的状态字、当时的cs:eip的值以及内核态的栈顶地址、当时的状态字等。
中断发生后第一件事就是保存现场 save_all,中断结束前的最后一件事就是恢复现场 restore_all,最后iret指令与中断信号发生时的CPU的做的动作只好相反。
中断处理过程:
interrupt (ex:int 0x80)-save cs:eip/ss:eip/eflages(current)to kernel stack,then load cs:eip(entry of a specific ISR)and ss:esp(point to kernel stack) int 0x80表示系统调用 保存了当前的堆栈,栈顶,标志寄存器保存到内核堆栈 同时加载了当前的系统调用相关联的中断服务历程的入口 同时把当前的堆栈段和esp也加载到CPU里
save_all
-…//内核代码,完成中断服务,发生进程调度
restore_all
iret-pop cs:eip/ss:esp/eflags from kernel stack
系统调用的意义:操作系统为用户态进程与硬件设备进行交互提供了一组接口——系统调用
把用户从底层的硬件编程中解放出来
极大地提高了系统的安全性
使用户程序具有可移植性
API和系统调用(应用程序编程接口):API知识一个函数定义,系统调用通过软中断向内核发出一个明确的请求。
一般每个系统调用对应一个封装例程;不是每一个系统调用对应一个API,大部分封装都返回一个整数。
系统调用的三层皮:API、对应的中断向量、服务程序
内核实现了很多不同的系统调用,进程必须指明要哪一种系统调用,因此有了系统调用号这个参数。用eax寄存器传递参数。
寄存器传递参数具有如下限制:每个参数的长度不能超过寄存器的长度,即32位;在系统调用号之外,参数的个数不能超过六个。
实验:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用。
以上是关于扒开系统调用的三层皮的主要内容,如果未能解决你的问题,请参考以下文章