操作系统接口(Linux0.11)
操作系统有四种堆栈:
系统初始化时临时使用的堆栈 ,bootsect被移动到0x9000:0处时出现
供内核程序自己使用的堆栈(内核堆栈)
任务堆栈:又分为用户态堆栈和内核态堆栈
每个任务都会有一个任务堆栈,即一个用户态堆栈和内核态堆栈。有时候多个任务可能会共用一个内核态堆栈,因为进程分为用户进程和内核进程,这部分知识涉及到的是后面的系统进程部分。
用户态堆栈和内核态堆栈的区别:
用户态堆栈空间比较大大约64MB 内核态堆栈很小,只有大约3k字节,正好是一个任务数据结构的大小,任务数据结构中包含本任务的局部描述符表指针。
那么如何将数据保存到用户态堆栈或内核态堆栈呢?
可以通过直接定义常量,因为栈的部分与硬盘不同,硬盘需要写入操作才能保存,但是栈属于缓存部分,数据处理就在这块内存空间中,所以可以直接使用常量定义,操作系统可以自动清理不用的栈空间,垃圾处理部分有兴趣的可以自己去搜集资料,了解。
任务数据结构如下图:
标黄的是个人认为比较重要的部分
任务调用系统调用程序时进入内核态,执行内核代码,使用内核态堆栈。
Linux目录结构中kernel目录下包含系统调用等程序,每个系统调用都有一个序列号,在include/Linux/unistd.h头文件中定义,常以宏的形式实现。
系统调用通常性能优于库函数,相信通过下图大家可以理解原因:
makefile文件相当于程序编译过程中的批处理文件。是工具程序make运行时的输入数据文件。
只要在含有makefile文件的目录中键入make命令,它就会根据makefile文件中的设置对源程序和目标代码文件进行编译,连接和安装等活动。
Linux中系统调用内核代码通过中断int 0x80进行。寄存器eax中存放调用号即系统调用的序列号。实现系统调用的文件有system_call.s/fork.c/signal.c/ sys.c 和exit.c文件。
对于系统调用int 0x80来说,中断处理过程如下:
- 首先检查eax中调用号是否有效
- 如果有效则保存会用到的寄存器,即参数用到的寄存器,ds,es用于内核代码段,fs用于用户代码段
- 接着通过地址跳转表sys_call_table调用相应系统调用的c函数
- c函数返回后,保存(push)了调用返回值
- 恢复保存的寄存器内容
- 退出中断处理并返回调用程序
中断过程如下图: