Xv6异常处理(三):系统调用

阅读材料

  • Xv6代码:usys.pl、syscall.h、syscall.c
  • 教材4.3节

系统调用流程

用户程序调用系统调用--->usys.S中对应的汇编函数--->uservec汇编函数--->usertrap()函数--->syscall()函数--->usertrapret()函数--->userret汇编函数--->usys.S中对应的汇编函数--->继续执行用户程序

系统调用接口:usys.S

usys.S本身不存在,通过执行make qemu命令,usys.pl脚本会自动生成usys.S文件。内容如下:

  1. 声明一个全局符号
  2. 将对应的系统调用号保存在a7寄存器中
  3. 执行ecall指令
  4. 执行ret伪指令返回用户进程
.global fork
fork:
    li a7, SYS_fork
    ecall
    ret

系统调用表

系统调用表中将系统调用号作为索引,元素则是指向相应系统调用的函数指针

static uint64 (*syscalls[])(void) =
{
	[SYS_fork] sys_fork,
	[SYS_exit] sys_exit,
	[SYS_wait] sys_wait,
	[SYS_pipe] sys_pipe,
	[SYS_read] sys_read,
	[SYS_kill] sys_kill,
	[SYS_exec] sys_exec,
	[SYS_fstat] sys_fstat,
	[SYS_chdir] sys_chdir,
	[SYS_dup] sys_dup,
	[SYS_getpid] sys_getpid,
	[SYS_sbrk] sys_sbrk,
	[SYS_sleep] sys_sleep,
	[SYS_uptime] sys_uptime,
	[SYS_open] sys_open,
	[SYS_write] sys_write,
	[SYS_mknod] sys_mknod,
	[SYS_unlink] sys_unlink,
	[SYS_link] sys_link,
	[SYS_mkdir] sys_mkdir,
	[SYS_close] sys_close,
};

syscall函数 

该函数根据a7寄存器中的系统调用号,调用对应的系统调用,并将返回值保存在a0寄存器当中

void syscall(void)
{
	int num;
	struct proc *p = myproc();

	num = p->trapframe->a7;
	if (num > 0 && num < NELEM(syscalls) && syscalls[num])
	{
		// Use num to lookup the system call function for num, call it,
		// and store its return value in p->trapframe->a0
		p->trapframe->a0 = syscalls[num]();
	}
	else
	{
		printf("%d %s: unknown sys call %d\n",
			   p->pid, p->name, num);
		p->trapframe->a0 = -1;
	}
}

参考资料

The xv6 Kernel-22 Anatomy of a System Call_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值