系统调用的前因后果
系统调用就是系统提供给你的一些函数你可以直接使用的最基础的函数 比如open fock read等
那么系统调用是什么我们要和电脑打交道当然你想要打开一个文件 在vs上打开文件都是通过fopen当然也可以直接调用系统调用如果没有系统调用open 那么就打不开文件
学过c++和c语言的就应该知道printf 这个函数 这个是库里面的函数 vs上不开源但是本质上来说也就是一个系统调用 或者是几个系统调用组合起来
由于window底下不开源 那么我们研究一下linux底下的系统调用
首先得知道我们运行一个程序需要将代码加载到物理内存上(一般来说这个物理内存是4G) 但是实际上我们每一个进程都有4G大小的虚拟内存
其实也就是这样
既然已经知道虚拟地址空间是个怎么样的了那么就来说一下一个系统调用是如何执行的
在linux下比如我们执行fork函数 那么首先我们得包含头文件unistd.h
我们研究的是linux 2.6 版本的 (为什么要说版本应为可能在不同版本下可能会有一些差距但是思想是不变的)
另外可能会有人看到这个头文件了之后直接来找sys_fork 但是实际上系统不是这样做的 而是通过一个宏
再这样把宏给放进去
如果看不懂可以这样理解name就是——NR_fork type就是定义的2
int 0x80 这个代表的一种中断 是指切换到内核的中断 可以脑补一下刚刚画的图也就是内核空间和用户空间的图
这个意思简单来说就是产生了一个中断 至于这个中断是干什么的就需要查找中断向量表
这个时候我们才进入内核 当然在进入内核之前我们还得进行堆栈的切换 刚刚脑补的画面应该还在吧
对就是切换堆栈将之前用户空间的栈的信息保存起来 至于如何保存起来就是通过寄存器呗 比如ss esp 等等把这些值先压入内核栈上这些寄存器保存的比如 用户空间的栈的栈地址栈低 栈大小等等
中断向量表在
trap.s这个文件里
这个文件下有兴趣的可以看看
这样就找到了system_call的地址了
这个简单的看看压入eax寄存器也就是2然后再就是就是压入save_all(save_all也是一些寄存器这些寄存器放到是系统调用的参数) save_all里面是就是参数比如不一定是fork系统调用如果是open系统调用的话就需要打开什么文件等等参数(由于是寄存器是有限的所以这个save-all 就只有6个 也就是说参数最多6个)
save-all里面放的就是不同的参数
这个意思就是讲通过eax寄存器真正的找到fork函数 然后有个call 就是进入sys_call_table (系统调用表)然后通过寄存器中所存的值选择一个函数 这个就是真正的入口函数
第二个sys-fork函数也就执行到了真正的系统调用sys-fork
然后执行完成系统的函数后出栈返回用户空间 这样就执行完了真正的系统调用