YouTubeでは、すべてのレジスタに対してシステムコールがあるビデオを見ました。もしそうなら、これはシステムコールがレジスタに格納されるという意味ですか?では、これはどのように可能ですか?オペレーティングシステムを制御するカーネルによってアクセスされることを意味します。もしそうなら、カーネルアクセスレジスタはどのように行われますか?
ベストアンサー1
「レジスタごとのシステムコール...」はありません。
システムコールインターフェイスはハードウェアアーキテクチャによって異なります。通常、(ほぼ常に?)プロセスは、目的のシステムコールに対応する整数を所定のレジスタに格納し、CPUが実行をカーネルのシステムコール処理コードに転送するようにトリガするコマンドを実行します。カーネルは、所定のレジスタを参照してプロセスが要求するシステムコールを識別し、適切なシステムコールハンドラを実行する。
たとえば、Linux x86_64アセンブリの「hello world」プログラムを考えてみましょう。
$ cat hello.s
.text
.global
main:
movq $1, %rax # write() system call number
movq $1, %rdi # first parameter -- standard output file descriptor
movq $msg, %rsi # second parameter -- buffer
movq $14, %rdx # third parameter -- buffer length
syscall # invoke system call
movq $60, %rax # exit() system call number
movq $0, %rdi # first parameter -- exit status
syscall # invoke system call; this will never return
.section .rodata
msg:
.ascii "Hello, world!\n"
$ gcc hello.s
$ ./a.out
Hello, world!
$
x86_64の場合、システムコール番号はレジスタに保存され、rax
システムコールの最初のパラメータはに保存され、システムコールrdi
の2番目のパラメータはに保存されrsi
、3番目のパラメータはに保存されますrdx
。
この例では、まず値を1
レジスタに入れますrax
。 1
システムコールのシステムコール番号write()
。次に、標準出力のファイル記述子であり、最初の引数のレジスタであるレジスタを挿入1
します。次に、2番目のパラメータのアドレスをレジスタに保存します。次に。 14に格納するのは、3番目の引数のレジスタである文字列の長さです。その後、この命令はCPUが制御をカーネルコードに転送するようにトリガします。カーネルはをチェックし、このレジスタ(1)の値を使用して実行(書き込み)するシステムコールを決定し、適切なハンドラを呼び出します。rdi
1
rdi
msg
rsi
rsi
14
rdx
rdx
syscall
rax
カーネルがシステムコールを完了すると、コントロールはユーザー空間プロセスに返されます。これは60
レジスタに書き込みますrax
。つまり、rax
これはシステムコール番号のレジスタです。ここでは60
システムコール番号ですexit()
。シャットダウンシステムコールの最初の(唯一の)パラメータである0
レジスタに書き込みます。rdi
この命令は、再びsyscall
CPUが制御権をカーネルコードに転送するようにトリガする。カーネルはをチェックし、rax
このレジスタ(60)の値を使用して実行するシステムコール(終了)を決定し、適切なハンドラを呼び出します。ハンドラはexit()
プロセスを破壊するため、コマンドは返されません。
同じことを行う例は、32ビットIntelの場合でもハードウェアアーキテクチャによって異なります。