系统调用和 traps 密不可分,系统调用需要用到 traps,所以这里将系统调用和 traps 结合到一起理解,当然重点是 traps。
系统调用相关文件
user.husys.plsyscall.hsyscall.csysproc.csysfile.c
异常和中断相关文件
trampoline.Strap.cproc.h
异常与中断
关于异常和中断的详细内容可以看看[[七、中断与异常]]。这里粗略地讲讲:

上图是异常和中断的程序流,可以看到异常和中断的处理都是暂停当前程序(这里会保存上下文),转而执行另一程序,最后再返回当前程序(恢复上下文)。这种暂停当前程序转而执行另一程序的方式也成为陷入,即 traps。
系统调用的原理也是 traps。因此,这里我们需要把两者结合起来理解。首先从系统调用开始
系统调用
我们先来看一段 lab0 中中编写的简单程序:
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int
main(int argc, char *argv[])
{
if (argc < 2) {
fprintf(2, "Usage: sleep time\n");
exit(1);
}
int time = atoi(argv[1]);
sleep(time);
exit(0);
}
在这个简单程序中,我们只是调用了 sleep 函数。sleep 函数允许一个进程暂停执行一段指定的时间,这个过程是由内核完成,因此会涉及系统调用。我们利用 IDE 的功能查看 sleep 函数定义在哪里。
可以看到 sleep 函数定义在 user.h 文件中,其中包含了很多系统调用函数,如下所示:
// user.h 节选
struct stat;
struct rtcdate;
struct sysinfo;
// system calls
int fork(void);
int exit(int) __attribute__((noreturn));
int wait(int*);
int pipe(int*);
int write(int, const void*, int);
int read(int, void*, int);
int close(int);
int kill(int);
int exec(char*, char**);
int open(const char*, int);
int mknod(const char*, short, short);
int unlink(const char*);
int fstat(int fd, struct stat*);
int link(const char*, const char*);
int mkdir(const char*);
int chdir(const char*);
int dup(int);
int getpid(void);
char* sbrk(int);
int sleep(int);
int uptime(void);
int trace(int);
int sysinfo(struct sysinfo *);
当然这些函数在 user.h 中仅仅是函数描述,而非实现,系统调用函数的实现在内核中。下面我们需要清楚调用系统调用函数时,是如何从用户空间陷入内核空间的。
经过查阅我们知道,操作系统会运行一段段 Perl 脚本 usys.pl 来生成 xv6 操作系统用户级系统调用入口。

最低0.47元/天 解锁文章
1596

被折叠的 条评论
为什么被折叠?



