原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/
本文主要参考了实验楼中"使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用"的实验.
部分则讲解系统调用的处理过程.
文章目录
系统调用
系统调用是操作系统中耳熟能详的一个名词了, 本科上OS时的记忆已经有点模糊, 乘着这次作业刚好可以回顾一下.
了解系统调用之前, 先来看看中断.
系统中断
中断通常分为两类: 同步(synchronous)中断和异步(asynchronous)中断, 顾名思义, 前者是在一条指令中止执行后CPU才会发出的; 后者则是有其他硬件设备按照CPU时钟信号随机产生的. 我们也常常成同步中断和异步中断为异常(exception)和中断(interrupt).
Intel的文档中把中断和异常分为以下几个大类:
- 中断
- 可屏蔽(maskable)中断
- 非屏蔽中断
- 异常
- 故障(fault)
- 陷阱(trap)
- 异常终止(abort)
- 编程异常(programmed exception)
编程异常通常是由我们这些程序猿引发的, 众所周知, 在linux系统中, 凡是涉及到资源管理和设备交互这些事情, 通常是由OS管理, 当我们需要调用系统的功能时, 通常通过系统调用将这些服务交由OS来做. 系统调用就是OS为用户态进程与硬件设备进行交互提供的一组接口, 系统调用的好处多多, 不仅把用户(client, 编程用户: 程序猿)从底层的硬件编程中解放出来, 还极大地提高了系统的安全性, 使得我们开发的程序有了可移植性.
关于以上的更多详细介绍, 可以参考维基百科: 中断
系通调用的编程实现
系统调用的缘由和原理我们知道了, 但是如何实现系统调用, 才是认识过程的第二次飞跃. Linux内核的底层代码都是通过C语言实现的, 在C语言的库中, 就有一些API引用了封装例程, 封装例程的目的, 就是进行系统调用. 我们常见的printf(), chdir() 其实都属于系统调用的范畴.
系统调用在系统内部的表现
结合前面两个标题, 我们对于中断, 系统调用有了泛泛的了解, 更深入一点, 系统调用的过程中, 究竟发生了什么?
我们知道, 在进行中断的时候, 通常系统会发出中断号, 中断号的目的, 就是为了查找中断服务程序的地址, 通常中断号 ∗ * ∗ 4 即为中断向量的地址, 而中断向量通过中断描述表( I n t e r r u p t d e s c r