系统调用
从上文简介得知,操作系统是计算机硬件和软件之间的桥梁,通过管理计算机软件和硬件资源,最终为我们用户提供服务。就如同一个管家帮助我们对CPU(进程)的管理、内存的管理、设备的管理、文件的管理。而我们如何实现操作系统这个管家帮助我们的管理就需要用到系统调用了。
系统调用 是用户程序与操作系统内核之间的接口,用于在用户空间和内核空间之间进行交互。系统调用允许用户程序请求操作系统提供的服务,如文件操作、进程管理、内存分配等。简单来说,系统调用就相当于操作系统这个管家底下的下人,去完成管家所要求的具体事项。是应用程序请求操作系统执行特权操作的一个机制。
操作系统的接口类型
(1)图形接口:主要是通过图标、文字、窗口等形式形成一个便于操作的使用环境,令任何人都可以使用计算机。例如Windows系统
(2)命令级接口:是提供给系统管理员或者程序员的接口,他们可以通过命令级接口向计算机发号施令,而每条命令又有很多选项,这是图形接口无法给予的功能。 例如Linux系统
(3)程序接口:是面向程序开发者的接口,他们可以通过程序接口获取更多系统资源和服务,并且程序接口也是程序取得操作系统服务的唯一途径,OS的程序接口又是由各种类型系统调用组成。
操作系统的接口标准
POSIX标准,由IEEE(Institute of Electrical and Electronics Engineers)制定的标准,旨在确保不同操作系统之间的兼容性和可移植性。
基本概念
在了解具体的系统调用之前我们需要先需要知道以下几个概念:
系统调用与API(应用程序接口)
联系与区别:
1、API是对系统调用的抽象与封装,通常由操作系统或第三方库提供。通过API,开发者能够方便地访问底层系统调用,而无需直接与内核交互。 2、系统调用是API的实现,通常位于操作系统内核层。当开发者调用API时,API会调用相应的系统调用来完成底层的任务。
以下是C语言中API函数printf()调用系统调用write()的过程
系统态与用户态
系统态:指操作系统内核正在占用CPU运行时的工作状态,有较高的特权级别,又称为内核态、管态。 用户态:用户程序运行时的状态,较低的特权级别,又称为普通态(普态)、目态。
系统调用号
是操作系统用来标识不同系统调用的唯一标识符。每个系统调用在操作系统内核中都有一个与之关联的编号。
系统调用表(sys_call_table)
是操作系统内核中的一个数据结构,它将系统调用号与实际的系统调用处理函数(内核函数)相对应。每个系统调用号都会在系统调用表中有一个对应的条目,系统调用表在系统启动时被初始化并存储在内存中。操作系统通过查找这个表来决定在用户程序发起某个系统调用时,应该调用哪个内核函数来处理该请求。
系统调用过程
当用户态的进程调用一个系统调用时,首先调用引bc库中的函数,这个函数必定有一条从用户态转入到内核态的陷入指令(如int0x80),这时便进入了内核态,在内核中找到系统调用表的入口地址sys_call_table,然后根据系统调用号在表中查到对应的系统调用入口地址,并执行相应的系统调用服务例程,执行完成后通过返回指令iet从内核态返回到用户态。
以fork()函数为例
如图
(1)从用户程序中调用fork();
(2)在Iibc库中把fork()对应的系统调用号“2”放入寄存器eax;
(3)通过“int 0x80"陷入内核;
(4)在中断描述表IDT中查到系统调用的入口“0x80";
(5)进入Linux内核的entry_.32(64).S文件,从系统调用表sys_call_table中找到sys_fork的入口地址;
(6)将控制权转交给系统调用,执行fork.c中的do_fork代码;
(7)执行结束后通过iret或者sysireti返回;
(8)最后检查切换回用户空间之前需要完成的任务,如果没有则恢复用户进程的状态,并将控制权交还给用户程序。