sigreturn, rt_sigreturn -
シグナルハンドラーから返り、スタックを掃除する
int sigreturn(...);
Linux
カーネルがプロセスに対してブロックされていないシグナルが処理待ちと判定した場合、
そのプロセスの次回のユーザーモードへの遷移
(すなわち、システムコールからのリターン時やそのプロセスが
CPU
に再スケジュールされる際)、カーネルはユーザー空間スタックの新しいフレームを作成し、そこにプロセスコンテキストの種々の値
(プロセッサーのステータスワード、レジスター、シグナルマスク、シグナルスタック設定)
を保存する。
また、 カーネルは、
ユーザーモードへの遷移時にシグナルハンドラーが呼び出され、
ハンドラーからのリターン時に、
制御が "signal trampoline"
と呼ばれるユーザー空間コードブロックに渡されるように、準備を行う。
signal trampoline のコードが
sigreturn()
を呼び出す。
sigreturn()
は、シグナルハンドラーを起動するために行ったことの全て
—
プロセスのシグナルマスクの変更、
シグナルスタックの切り替え
(
sigaltstack(2) 参照) —
の取り消しを行う。以前にユーザー空間スタックに保存された情報を使って、
sigreturn()
はプロセスのシグナルマスクの復元、スタックの切り替え、プロセスのコンテキスト
(プロセッサフラグ、レジスター
(スタックポインター、命令ポインターを含む))
の復元を行い、
プロセスがシグナルにより割り込まれた場所から実行を再開できるようにする。
sigreturn()
が返ることはない。
多くの UNIX
系のシステムには
sigreturn()
システムコールか似たようなシステムコールがある。
しかしながら、
このシステムコールは
POSIX
には規定されておらず、
その動作の詳細はシステムにより異なる。
sigreturn() exists only to allow the implementation of signal handlers.
It should
never be called directly. (Indeed, a simple
sigreturn() wrapper in the GNU C library simply returns -1, with
errno set to
ENOSYS.) Details of the arguments (if any) passed
to
sigreturn() vary depending on the architecture. (On some
architectures, such as x86-64,
sigreturn() takes no arguments, since
all of the information that it requires is available in the stack frame that
was previously created by the kernel on the user-space stack.)
かつて、 UNIX
システムでは signal trampoline
コードがユーザースタックに置かれていた。
今日では、
ユーザースタックのページは保護され、
コードの実行は禁止されている。
したがって、 現代の
Linux システムでは、
アーキテクチャー依存ではあるが、
signal trampoline コードは
vdso(7)
内もしくは C
ライブラリ内に置かれる。後者の場合、
C ライブラリの
sigaction(2)
のラッパー関数は、
trampoline code
の場所をそのアドレスを
sigaction(2) 構造体の
sa_restorer
フィールドに設定してカーネルに伝え、
sa_flags フィールドの
SA_RESTORER
フラグをセットする。
保存されたプロセスコンテキスト情報は
ucontext_t構造体に置かれる
(
<sys/ucontext.h> 参照)。
この構造体は、
sigaction(2)
の
SA_SIGINFO
フラグで設定されたシグナルハンドラーの第
3
引数としてシングルハンドラー内で参照できる。
他のいくつかの UNIX
システムでは、 signal trampoline
の扱いは少し異なる。
特に、
いくつかのシステムでは、
ユーザーモードに戻る際に、
カーネルは制御を
(シグナルハンドラーではなく)
trampoline に渡し、 trampoline
コードがシグナルハンドラーを呼び出す
(その後ハンドラーが返ると
sigreturn() を呼び出す)。
The original Linux system call was named
sigreturn(). However, with the
addition of real-time signals in Linux 2.2, a new system call,
rt_sigreturn() was added to support an enlarged
sigset_t type.
The GNU C library hides these details from us, transparently employing
rt_sigreturn() when the kernel provides it.
kill(2),
restart_syscall(2),
sigaltstack(2),
signal(2),
getcontext(3),
signal(7),
vdso(7)
この man ページは Linux
man-pages
プロジェクトのリリース
5.10
の一部である。プロジェクトの説明とバグ報告に関する情報は
https://www.kernel.org/doc/man-pages/
に書かれている。