窥探 kernel --- 有关系统调用的几个知识点

时间:2022-12-07 19:25:08


本系列文章由张同浩编写,转载请注明出处:http://blog.csdn.net/muge0913/article/details/7517303

邮箱:muge0913@sina.com



一般情况下,用户进程是不能访问内核空间的。它既不能访问内核中的数据,也不能访问内核中的函数。但在linux内核中设置了一组用于实现各种系统功能的函数,成为系统调用。用户可以在应用程序中调用它们。

linux系统还提供了一些c库,这些库对系统调用进行了一些包装和扩展。

系统调用,POSIX,C库,系统命令和内核函数

1、系统调用和POSIX

虽然系统调用是内核和用户空间的桥梁,但是用户的应用程序在访问内核时是通过系统提供的应用编程接口API来实现的。

操作系统的API主要作用是把操作系统的功能全展现出来,提供给应用程序。

在UNIX中最通用的操作系统API是基于POSIX(Portable Operating System ofUNIX)标准的。后来从UNIX发展来的版本各种各样,以至于给应用程序移植带来了很大的不便。为了结束这个局面IEEE制定了POSIX标准,提高UNIX环境下的用户程序移植性。POSIX标准不局限于UNIX,很多其他的操作系统也支持该标准如DEC OpenVMS和WindowNT。linux系统兼容POSIX标准,提供了根据POSIX而定义的API函数。这些函数和系统调用有着直接 的关系。一个API函数可以用一个系统调用实现,也可以多个系统调用来实现。同时不用系统调用来实现。

2、系统调用和c库

 

操作系统的API通常又有C库的方式来提供,linux也是如此。c库提供了兼容POSIX的绝大数API。内核提供的每个系统调用在c库中都有相应的函数封装。而且系统调用名和c库中封装的函数名往往相同。如read

c库中封装的函数在调用系统调用之前,一般只做一点工作。如系统调用truncate和truncate64在库中封装的truncate决定到底调用哪个系统调用。

封装的函数和系统调用不是一一对应关系。有的封装函数甚至不调用任何的系统调用如strcpy和atoi

窥探 kernel --- 有关系统调用的几个知识点

3、系统调用和系统命令

系统命令是c库的更上层。是利用c库实现的应用程序。如ls命令。

strace可以跟踪系统调用。

 

4、系统调用和内核函数

可以认为系统调用时内核函数的一部分。

 

5、系统调用表:

系统调用表sys_call_table存储了所有系统调用对应的服务例程函数的地址。

在x86中:2.6.38/arch/x86/kernel/syscall_table_32.S

在arm中2.6.38/arch/arm/kernel/calls.S

 

6、系统调用号:每个系统调用对应一个唯一的系统调用号。用户通过系统调用号,而不是名称来调用。

x86:2.6.38/arch/x86/include/asm/unistd32.h或unistd64.h

arm:2.6.38/arch/arm/include/asm/unistd.h能找到它们。

内核是通过系统调用号作为下表去sys_call_table来获取服务例程的地址的。在系统中系统调用号一旦分配就不能去除,这是为了兼容。

 

7、系统调用例程

所有的系统调用服务例程都声明在include/linux/syscalls.h中,但分散在不同的文件中。

asmlinkagelong sys_nice(int increment);

系统调用除了sys_外还有一个asmlinkage来告诉编译器从堆栈中获取参数。还必须有一个long的返回,表示执行成功还是出错。系统调用号,名称和目的都是相同的,但是在不同内核和架构中实现的方法可能不同。

 

 

8、如何使用系统调用

1、通过c库来使用系统调用

2、在2.6.18之前的内核使用_syscall宏来使用系统调用。

3、在2.6.19开始废除了_syscall,而使用syscall()通过向函数提供调用号和参数实现调用