システムコール:ユーザープロセスはどのようにカーネルとデータをやり取りしますか?

システムコール:ユーザープロセスはどのようにカーネルとデータをやり取りしますか?

ユーザーとカーネル仮想アドレスの関係は、以前のいくつかの質問(下のリンク)で説明されていますが、私が理解している限り、ユーザープロセスはできないカーネルアドレスを読み書きします。

だから、どのようにユーザープロセスはカーネルでデータを共有して受信しますか?

記憶を通してであるか。それでは、メモリレイアウトはどこにありますか?たぶんCPUレジスタですか?

関連質問:

メモリレイアウト

答え1

たとえば、見てみましょう。シンプルx86こんにちは世界メッセージを印刷しstdoutて終了するLinuxプログラム。複数のデータ項目をカーネルに渡す必要があります。

  • 出力するテキスト文字列、
  • 終了コード。

FASMでコンパイルされたアセンブリコードは次のとおりです。

format ELF executable
segment readable executable

; system call numbers
SYS_EXIT=1
SYS_WRITE=4
; file descriptors
STDOUT=1

entry $
start:
    mov eax, SYS_WRITE
    mov ebx, STDOUT
    mov ecx, message
    mov edx, messageLength
    int 0x80

    mov eax, SYS_EXIT
    xor ebx, ebx ; exit code 0
    int 0x80

message:
    db "Hello, world!",0xa
messageLength=$-message

このプログラムが主な目標(メッセージ出力)を達成するために実行するすべてのタスクは次のとおりです。

  • sys_writestdoutシステムコール番号(syscall用)、ファイル記述子()、メッセージアドレス、およびメッセージ長を示す値で適切なCPUレジスタを設定します。
  • この場合、ソフトウェア割り込み0x80を介してシステムコールを実行します。

シャットダウンにも同様の順序があります。レジスタをシステムコール番号と終了コードに設定し、システムコールを実行します。

どのレジスタがどの値に設定されるかは、システムコールによって定義されます。呼び出しルール

カーネルがシステムコールハンドラの実行を開始した後、ハンドラはアプリケーションのコンテキストからレジスタ値を読み込み、コールルールに従って解釈します。特に、システムコールを見ると、sys_writeメッセージの長さとアドレスを取得し、それを使用してユーザー空間メモリから読み込みます。その後、このデータ(ファイル記述子とともに)が実際の操作を実行するドライバに渡されます。

答え2

ユーザープロセスがカーネルアドレスを読み書きできません。

いいえ。ただし、カーネルは必要に応じてユーザーアドレスを読み書きできます。 Linuxシステムコールは、CPUレジスタのシステムコール番号とパラメータを渡します。 (「Linuxシステムコールの呼び出し規則」のようなものを探してください。)

これらの引数の一部はポインタである可能性があります。この場合、カーネルはユーザーアドレス空間の指定された場所でデータを見つける方法を知っています。私が理解したところ、カーネルはデータを使用する前に実際にデータをカーネル空間にコピーします。 (そうでなければ、他のユーザースペーススレッドはシステムコール中にデータを変更できます。)ただし、データの場所はプログラムの要件に応じてユーザーのアドレススペースの任意の場所に存在する可能性があります。

関連情報