哈工大李治军操作系统--操作系统基础(系统调用)

系统调用就是上层应用调用操作系统提供的接口(一些函数)。POSIX就是一种接口标准。中断(系统调用使用int 0x80)是硬件提供的用户态进入内核态的唯一方式。
在这里插入图片描述

系统调用详细过程

在这里插入图片描述

参看上图系统调用过程,要从库函数write说起,write库函数其实就是调用了linux/include/unistd.h中的_syscall3宏。
在这里插入图片描述
linux/include/unistd.h中的_syscall3如下。
在这里插入图片描述

经write库函数来到_syscall3宏,"_syscall3"中的3代表3个参数,
type=int, name=write, atype=int, btype=const char *,
b=buf, ctype=off_t, c=count

int write(int fd, const char * buf, off_t count){
	long __res;
	// 内嵌汇编翻译,int 0x80中断,返回结果放在eax,最终给__res(mov %eax,__res)
	mov __NR_write,%eax
	mov fd,%ebx
	mov buf,%ecx
	mov count,%edx
	...
}

注意上述代码是把系统调用号__NR_write写入eax寄存器,并在ebx,
ecx,edx寄存器中传入参数,调用0x80号中断进入内核完成系统调用。

__NR_write也是在linux/include/unistd.h中定义的,如下图。

在这里插入图片描述
int 0x80需要查询中断表IDT,找到对应的中断门。而内核初始化的时候,恰好设置了0x80号中断对应的中断门。在文件linux/init/main.c中132行调用了sched_init()函数,而sched_init()函数在linux/kernel/sched.c中,sched_init()函数最后一行代码就是设置0x80号对应的中断门描述符,如下图。
在这里插入图片描述
set_system_gate在linux/include/asm/system.h中,如下,就是设置中断门描述符的,段选择子设为0x8,段内偏移设置为&system_call(中断处理函数地址),DPL设为了3。而用户态CPL=3,正好可使用该中断门,而该中断门里面的段选择子是0x8,0x8对应的二进制是b0000_0000_0000_1_0_00,对应的CPL=0,于是乎进入内核态。在中断程序执行完之后,CPL会设置为3,回到用户态。
在这里插入图片描述
在这里插入图片描述
中断处理程序就是linux/kernel/system_call.s,如下。
在这里插入图片描述
在linux/include/linux/sys.h中,对应了系统调用的所有函数列表,如下。
在这里插入图片描述
到此,就要开始真正去调用sys_write了,而sys_write内部是怎么样的呢?后面课程会讲。

系统调用大致过程

在这里插入图片描述

参考资料

[1] 中国大学MOOC《操作系统》李治军 哈尔滨工业大学
[2] 《Linux内核完全注释》赵炯
[3] BIOS中断大全
[4] 汇编语言最全指令表
[5] 《x86汇编语言:从实模式到保护模式》李忠 著
[6] https://blog.csdn.net/ccnuacmhdu/article/details/104946213

发布了323 篇原创文章 · 获赞 193 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/ccnuacmhdu/article/details/105328271