Linux系统调用全过程详解

  • Post author:
  • Post category:linux




系统调用(SYSTEM CALL)


OS内核中都有一组实现系统功能的过程,系统调用就是对上述过程的调用。编程人员利用系统调用,向OS提出服务请求,由OS代为完成。

一般情况下,进程是不能够存取系统内核的。它不能存取内核使用的内存段,也不能调用内核函数,CPU的硬件结构保证了这一点。只有系统调用是一个例外。

统调用是用户态进入内核态的唯一入口:一夫当关,万夫莫开。常用系统调用:

  • 控制硬件:如write/read调用。
  • 设置系统状态或读取内核数据——getpid()、getpriority()、setpriority()、sethostname()
  • 进程管理:如 fork()、clone()、execve()、exit()等

优点 编程容易,从硬件设备的低级编程中解脱出来 提高了系统的安全性,可以先检查请求的正确性



陷入指令

在 Intel CPU 中,这个指令由中断 0x80 实现。

在 ARM 中,这个指令是 SWI。



Int 0x80指令


Linux中实现系统调用利用了i386体系结构中的软件中断。即调用了int  $0x80汇编指令。

这条汇编指令将产生向量为128的编程异常,CPU便被切换到内核态执行内核函数,转到了系统调用处理程序的入口:system_call()。

int $0x80指令将用户态的执行模式转变为内核态,并将控制权交给系统调用过程的起点system_call()处理函数。

system_cal()检查系统调用号,该号码告诉内核进程请求哪种服务。

内核进程查看系统调用表(sys_call_table)找到所调用的内核函数入口地址。

接着调用相应的函数,在返回后做一些系统检查,最后返回到进程。



system_call()函数



系统调用和普通函数调用

API是用于某种特定目的的函数,供应用程序调用,而系统调用供应用程序直接进入系统内核。

Linux内核提供了一些C语言函数库,这些库对系统调用进行了一些包装和扩展,因为这些库函数与系统调用的关系非常紧密,所以习惯上把这些函数也称为系统调用。

有的API函数在用户空间就可以完成工作,如一些用于数学计算的函数,因此不需要使用系统调用。

有的API函数可能会进行多次系统调用。

不同的API 函数也可能会有相同的系统调用。比如malloc(),calloc(),free()等函数都使用相同的方法分配和释放内存。



系统命令、内核函数

系统调用与系统命令

  • 系统命令相对API来说,更高一层。每个系统命令都是一个执行程序,如ls命令等。这些命令的实现调用了系统调用。

系统调用与内核函数

  • 系统调用是用户进入内核的接口层,它本身并非内核函数,但是它由内核函数实现。
  • 进入内核后,不同的系统调用会找到各自对应的内核函数,这些内核函数被称为系统调用的“服务例程”。如系统调用getpid实际调用的服务例程为sys_getpid(),或者说系统调用getpid()是服务例程sys_getpid()的封装例程。



封装例程(wrapper routine)


<



版权声明:本文为QQ2558030393原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。