- 系统调用是内核提供的用户进程与内核进行交互的一组接口(是应用程序受限地访问接口、提供了创建新进程并与已有进程进行通信的机制、提供了申请操作系统其它资源的能力),是用户访问内核的唯一手段。主要是为了保证系统稳定可靠,避免应用程序肆意妄为。
- 系统调用作为用户空间进程和硬件设备之间的中间层,主要作用有以下三个方面:
(1)为用户空间提供了一种硬件的抽象接口,无需了解底层。
(2)保证了系统的稳定和安全。
(3)考虑到每个进程都运行在虚拟系统中。 - 一个应用编程接口(API)可能包含零个或者多个系统调用。程序员主要是跟API打交道。类似的还有POSIX、SUSv3等。
- 编译指令asmlinkage通知编译器仅从栈中提取该函数的参数,系统调用号独一无二地关联系统调用。若系统调用被删除,那么用sys_ni_syscall()函数来填充系统调用号。系统调用号与系统调用的对应关系存储在sys_call_table表中。
- 内核驻留在受保护的地址空间上,不能直接被用户空间的程序执行。用户程序需要告诉内核自己需要执行一个系统调用,希望系统切换到内核态,这样内核代表应用程序在内核空间中执行系统调用。通过引发一个异常(软中断128号:通过init$0x80触发或者sysenter)是系统切换到内核态去执行异常处理程序(系统调用处理程序,名称为system_call())。
- 陷入内核(引发异常)同时需要通过eax寄存器将系统调用号传递给内核。在陷入内核前就需要将系统调用号放入eax寄存器中。系统调用处理程序一旦运行,就可以从eax中得到数据。
- 需要传递的参数少于等于5个时,可以通过寄存器传递,如果多余5个,则需要一个单独的寄存器来存放指向所有这些参数的指针。
- 设计一个系统调用时,要注意可移植性和健壮性,不但要考虑当前还要为未来做打算。
- 内核在接受用户空间的指针时:指针指向的内存区域属于用户空间、指针指向的内存区域在进程的地址空间内、进程绝不能绕过内存访问限制。
- 当系统调用返回时,控制权仍在system_call()中,他最终会负责切换到用户空间中。并继续执行下去。