Linux 系统调用

介绍

系统调用是程序向内核发出的服务请求,通常是只有内核才有权限执行的操作,例如进行 I/O。程序员通常不需要关心系统调用,因为 GNU C 库中有函数可以完成几乎所有系统调用的功能。这些函数通过自身调用系统调用来工作。例如,有一个系统调用可以改变文件的权限,但您不需要了解它,因为您可以直接使用 GNU C 库的 chmod 函数。

系统调用有时也被称为内核调用。

然而,有时您可能想要显式地调用一个系统调用,为此,GNU C 库提供了 syscall 函数。syscall 比像 chmod 这样的函数更难使用,也不太可移植,但比用汇编指令编写系统调用更容易,也更可移植。

syscall 最有用的时候是当您在使用一个特定于您的系统或者比您使用的 GNU C 库更新的系统调用时。syscall 是以一种完全通用的方式实现的;该函数不知道任何一个特定的系统调用做了什么,甚至不知道它是否有效。

这一节中对 syscall 的描述假设了 GNU C 库在各个平台上运行的系统调用的某种协议。这种协议没有被任何强有力的权威所定义,但我们也不会在这里描述它,因为任何编写 syscall 的人可能不会接受任何低于内核和 C 库源代码的东西作为它们之间的接口的规范。

函数定义

sycall 函数定义在 unistd.h

Function: long int syscall (long int sysno, …)

syscall 函数可以执行一个通用的系统调用。sysno 是系统调用的编号。每种系统调用都有一个对应的编号。所有可能的系统调用编号都定义在 sys/syscall.h 中。
剩余的参数是系统调用的参数,按顺序排列,它们的含义取决于系统调用的种类。每种系统调用有一个确定的参数个数,从零到五。如果您编写的参数多于系统调用需要的,那么右边多余的参数会被忽略。

返回值是系统调用的返回值,除非系统调用失败。在那种情况下,syscall 返回 -1 并设置 errno 为系统调用返回的错误码。注意,系统调用在成功时不会返回 -1。

如果您指定了一个无效的 sysno,syscall 返回 -1 并设置 errno 为 ENOSYS。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
#include <unistd.h>
#include <sys/syscall.h>
#include <errno.h>



int rc;

rc = syscall(SYS_chmod, "/etc/passwd", 0444);

if (rc == -1)
fprintf(stderr, "chmod failed, errno = %d\n", errno);

这段代码,等价于下面的代码:

1
2
3
4
5
6
7
8
9
10
11
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>



int rc;

rc = chmod("/etc/passwd", 0444);
if (rc == -1)
fprintf(stderr, "chmod failed, errno = %d\n", errno);

参考

原文:System-Calls