1 系统调用
1-1 概念
用户进程在通常情况下不允许访问内核数据,也无法使用内核函数。用户只能在用户空间操作用户数据、调用用户空间函数。比如我们熟悉的“hello world”程序执行时就是标准的用户空间进程,它使用的打印函数printf就属于用户空间函数,打印的字符“hello word”字符串也属于用户空间数据。
但是很多情况下,用户进程需要获得系统服务(调用系统程序),就可以使用系统调用。比如用户想要请求系统打开文件、关闭文件或读写文件,就可以通过文件系统相关的系统调用来做到。用户想要获得系统时间或设置定时器等,就可以通过时钟相关的系统调用来做到。
系统调用是用户级程序访问内核最基本的方法。但在实际C语言开发中我们一般不直接进行系统调用,而是通过一些用户编程接口(API)来调用。
首先讲一下用户编程接口(API)。用户编程接口其实是一些函数定义,比如read()、malloc()、free()、abs()等。这些API主要是通过C库(libc)实现的。我们在调用这些函数时,函数内部实际上是进行的系统调用。比如read()函数就和read系统调用对应;再比如malloc()、free()内部利用brk系统调用来扩大或缩小进程的堆。当然也有一些函数并没有使用系统调用。比如计算整数绝对值的abs()就没有使用系统调用。
Linux有大约两百多个系统调用,可以在很多渠道查阅到它的系统调用表。网上也很容易搜到。
当然,我们除了使用C语言函数来使用系统调用之外,还可以直接使用系统调用。如果你愿意直接调用,Linux内核也提供了一个syscall()函数来实现调用
下面是一个打印进程号的C语言程序,它使用两种方法来打印。第一种是直接使用系统调用,第二种是通过C语言函数调用:
#include <syscall.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
int main(void) {
long ID1, ID2;
/* 直接系统调用*/
ID1 = syscall(SYS_getpid);
printf ("syscall(SYS_getpid)=%ld\n", ID1);
/* 使用"libc"封装的系统调用 */
ID2 = getpid();
printf ("getpid()=%ld\n", ID2);
return(