系统调用:原理及实现
1. 什么是系统调用
在计算机中,系统调用(英语:system call),又称为系统呼叫,指运行在使用者空间的程序向操作系统内核请求需要更高权限运行的服务。系统调用提供了用户程序与操作系统之间的接口(即系统调用是用户程序和内核交互的接口)。
操作系统中的状态分为管态(核心态)和目态(用户态)。大多数系统交互式操作需求在内核态执行。如设备IO操作或者进程间通信。特权指令:一类只能在核心态下运行而不能在用户态下运行的特殊指令。不同的操作系统特权指令会有所差异,但是一般来说主要是和硬件相关的一些指令。用户程序只在用户态下运行,有时需要访问系统核心功能,这时通过系统调用接口使用系统调用。
翻来覆去也就是这几句话:
应用程序有时会需要一些危险的、权限很高的指令,如果把这些权限放心地交给用户程序是很危险的(比如一个进程可能修改另一个进程的内存区,导致其不能运行),但是又不能完全不给这些权限。于是有了系统调用,危险的指令被包装成系统调用,用户程序只能调用而无权自己运行那些危险的指令。另外,计算机硬件的资源是有限的,为了更好的管理这些资源,所有的资源都由操作系统控制,进程只能向操作系统请求这些资源。操作系统是这些资源的唯一入口,这个入口就是系统调用。
2. 系统调用实现方法概述
在Xv6中增加系统调用的方法为:
1) 在 sysproc.c 文件中,添加要增加的系统调用的实现函数;
2) 在 syscall.h 文件中,定义指向实现函数的系统调用向量(system call vector)的位置;
3) 在 user.h 文件中,定义可以在 shell 中调用的函数;
4) 在 syscall.c 文件中,外部定义(external define)一个链接内核和 shell 的函数,使用“步骤2)”中的位置将此函数添加到系统调用向量;
5) 在 usys.S 文件中,使用 macro 连接 用户的调用请求 和 实现函数;
6) 在 defs.h 文件中,为自己添加的系统调用增加一个前台声明。
3. 实际操作
为Xv6增加系统调用“halt”,以完成关机功能。
a. 在 sysproc.c 文件中,添加要增加的系统调用的实现函数,添加代码如下:
int sys_halt(void) { char *p = "Shutdown"; for( ; *p; p++) outb(0x8900, *p); return 0; }
b. 在 syscall.h 文件中,定义指向实现函数的系统调用向量(system call vector)的位置,添加代码如下:
#define SYS_halt 22
c. 在 user.h 文件中,定义可以在 shell 中调用的函数;
int halt(void);
d. 在 syscall.c 文件中,添加如下代码:
extern int sys_halt(void);
并在static int (*syscalls [])(void)中,添加如下内容:
[SYS_halt] sys_halt,
e. 在usys.S中添加:
SYSCALL(halt)
完成。
注:
本文参考了以下地址,如有兴趣可访问原地址。
参考博客:http://yalongyang.com/2012/10/xv6-add-system-call/
参考博客:http://www.ithao123.cn/content-6299692.html
参考回答:http://stackoverflow.com/questions/8021774/how-do-i-add-a-system-call-utility-in-xv6