Scroll to navigation

SYSCALL(2) Linux Programmer's Manual SYSCALL(2)

名前

syscall - 間接システムコール

書式

#define _GNU_SOURCE         /* feature_test_macros(7) 参照 */
#include <unistd.h>
#include <sys/syscall.h>   /* SYS_xxx の定義用 */
int syscall(int number, ...);

説明

syscall() は、システムコールを起動する小さなライブラリ関数で、 number で指定されたアセンブリ言語インターフェースのシステムコールを、指定された引き数をつけて実行する。 syscall() が役に立つのは、例えば C ライブラリにラッパー関数が存在しないシステムコールを呼び出したい場合である。
syscall() は、システムコールを行う前に CPU レジスタを保存し、システムコールから返った際にレジスタを復元し、エラーが発生した場合はシステムコールが返したエラーコードを errno(3) に格納する。
システムコールのシンボル定数は、ヘッダファイル <sys/syscall.h> に書かれている。

返り値

返り値は呼び出されたシステムコールによって定義される。 一般に、返り値 0 は成功を表す。 -1 はエラーを表し、エラーコードは errno に入れられる。

注意

syscall() は 4BSD で最初に登場した。

アーキテクチャ固有の要件

各アーキテクチャの ABI には、 システムコールの引き数のカーネルへの渡し方に関する独自の要件がある。 (ほとんどのシステムコールのように) glibc ラッパー関数があるシステムコールでは、 glibc が詳細を処理し、アーキテクチャに応じた方法で引き数が適切なレジスタにコピーされる。 しかし、 システムコールを呼び出すのに syscall() を使う場合には、 呼び出し側でアーキテクチャ依存の詳細を処理しなければならない場合がある。 これはいくつかの 32 ビットアーキテクチャでは非常によくあることだ。
例えば、ARM アーキテクチャの Embedded ABI (EABI) では、 ( long long などの) 64 ビット値は偶数番地のレジスタのペアに境界があっていなければならない。したがって、 glibc が提供するラッパー関数ではなく syscall() を使う場合には、 readahead() システムコールは ARM アーキテクチャの EABI では以下のようにして起動されることになる。

syscall(SYS_readahead, fd, 0,
        (unsigned int) (offset >> 32),
        (unsigned int) (offset & 0xFFFFFFFF),
        count);

オフセット引き数は 64 ビットで、最初の引き数 ( fd) は r0 で渡されるので、呼び出し側では手動で 64 ビット値を分割して境界を合わせて、 64 ビット値が r2/r3 レジスタペアで渡されるようにしなければならない。このため、 r1 (2 番目の引数 0) としてダミー値を挿入している。
同様のことが、 MIPS の O32 ABI、 PowerPC の 32 ビット ABI や Xtensa でも起こりうる。
次のシステムコールに影響がある: fadvise64_64(2), ftruncate64(2), posix_fadvise(2), pread64(2), pwrite64(2), readahead(2), sync_file_range(2), truncate64(2)

アーキテクチャ毎の呼び出し規約

各アーキテクチャには、それぞれ独自のシステムコール起動方法とカーネルへの引き数の渡し方がある。 各種のアーキテクチャの詳細を以下の 2 つの表にまとめる。
最初の表は、 カーネルモードに遷移するのに使用される命令、 システムコール番号を示すのに使用されるレジスタ、 システムコールの結果を返すのに使用されるレジスタの一覧である (なお、 ここに載っているカーネルモードに遷移するのに使用される命令は、 カーネルモードに遷移する最速や最善の方法でない場合もあるので、 vdso(7) を参照する必要があるかもしれない)。
arch/ABI instruction syscall # retval Notes
arm/OABI swi NR - a1 NR はシステムコール番号
arm/EABI swi 0x0 r7 r0
blackfin excpt 0x0 P0 R0
i386 int $0x80 eax eax
ia64 break 0x100000 r15 r10/r8 真偽値のエラー/ エラー値
parisc ble 0x100(%sr2, %r0) r20 r28
s390 svc 0 r1 r2 下記参照
s390 svc 0 r1 r2 下記参照
sparc/32 t 0x10 g1 o0
sparc/64 t 0x6d g1 o0
x86_64 syscall rax rax
s390 と s390x では、 NR (システムコール番号) が 256 未満の場合 "svc NR" で NR が直接渡される場合がある。
2 つ目の表は、システムコールの引き数を渡すのに使用されるレジスタの一覧である。
arch/ABI arg1 arg2 arg3 arg4 arg5 arg6 arg7
arm/OABI a1 a2 a3 a4 v1 v2 v3
arm/EABI r0 r1 r2 r3 r4 r5 r6
blackfin R0 R1 R2 R3 R4 R5 -
i386 ebx ecx edx esi edi ebp -
ia64 out0 out1 out2 out3 out4 out5 -
parisc r26 r25 r24 r23 r22 r21 -
s390 r2 r3 r4 r5 r6 r7 -
s390x r2 r3 r4 r5 r6 r7 -
sparc/32 o0 o1 o2 o3 o4 o5 -
sparc/64 o0 o1 o2 o3 o4 o5 -
x86_64 rdi rsi rdx r10 r8 r9 -
これらの表にはすべての呼び出し規約が記載されているわけではない点に注意すること — アーキテクチャによっては、ここに記載されていない他のレジスタが見境なく上書きされる場合もある。

#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <signal.h>
int main(int argc, char *argv[]) { pid_t tid;
tid = syscall(SYS_gettid); tid = syscall(SYS_tgkill, getpid(), tid, SIGHUP); }

関連項目

_syscall(2), intro(2), syscalls(2), vdso(7)

この文書について

この man ページは Linux man-pages プロジェクトのリリース 3.65 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。
2014-04-06 Linux