本文に進む 日本−日本語
日本HPホーム 製品とサービス お客様サポート/ ダウンロード ソリューション ご購入の方法
≫ お問い合わせ
詳細検索オプション
日本HPホーム
HP-UX リファレンス: セクション 2 : システムコール > s

sigvector(2)

廃止予定
HP-UX 11i Version 2: September 2004
≫ 

テクニカル ドキュメント

PDF版
フィードバック
ここから本文が始まります

 ≫ 目次

 ≫ 索引

名称

sigvector ― ソフトウェアシグナル機構

構文

#include <signal.h> 
 
int sigvector( 
    int sig, 
    const struct sigvec *vec, 
    struct sigvec *ovec 
); 

説明

システムは、プロセスに届けることができるシグナルの集合を定義しています。 シグナルの集合は、 それぞれのシグナルの意味と副作用とともに signal(5) で定義されています。 このマニュアルエントリーでは、 sigblock(2)sigsetmask(2)sigpause(3C)、 および sigspace(2) とともに、 シグナルの到着と、シグナルを扱う手続きの整合性を保証する、 これらのシグナルを扱うひとつの機構を定義しています。 ここで述べる機構は、 signal(2) と同じプログラムの中では使わないでください。

sigvector() インタフェースでは、 シグナルの到着はハードウェア割込みの発生と似ています。 つまり、シグナルはそれ以上の条件をブロックされ、 現在のプロセスのコンテキストは保存され、新しいコンテキストが作られます。 プロセスは、シグナルが届いたときに起動されるハンドラー関数を指定するか、 シグナルがブロックされるか、無視されるかを指定することができます。 プロセスは、シグナルが発生したときに、システムがデフォルトの動作を とるかどうかを指定することもできます。 sigspace() を用いてシグナルを処理するためのスタック領域の最小量を保証することができます ( sigspace(2) を参照)。

すべてのシグナルは同じ優先順位を持っています。 起動の要因となったシグナルはブロックされ、 他のシグナルはなお発生可能な状態で、シグナルルーチンが実行されます。 大域的なシグナルマスクは、現在プロセスへの到着をブロックされている シグナルの集合を定義します。 あるプロセスのシグナルマスクは、 その上位のプロセスにより 初期化 されます (通常は 0 です)。 シグナルマスクは、 sigblock()sigsetmask()、 または sigpause() コール によって変更されるか、もしくはシグナルがプロセスに届けられたときに変更されます。

シグナルマスクは、 1 ビットがそれぞれのブロックされるシグナルを表す long として表現されます。 <signal.h> で定義されている次のマクロは、 シグナル番号 を相当するシグナルマスクのビットに変換するのに使われます。

#define sigmask(signo)
  

(1L << (signo-1))

あるプロセスにシグナルが発生すると、 そのシグナルはプロセスのペンディングしているシグナル集合に加えられます。 シグナルは、現在そのプロセスでブロックされていないならば、 プロセスに送られます。 シグナルが届くと、プロセスの現在の状態は保存され、 新しいシグナルマスクが計算され (以下で解説する)、 シグナルハンドラーが起動されます。 ハンドラーの呼出しは、 シグナルを扱うルーチンが正常に終了すれば、 プロセスが シグナルの到着の前と同じコンテキストでの実行に復帰できるようになっています。 プロセスが異なったコンテキストで復帰したければ、 自分自身で前のコンテキストを再設定するようにしなければいけません。

シグナルがプロセスへ届けられると、 プロセスの シグナルハンドラーが実行されている間 (または、 sigblock()sigsetmask() が呼び出されるまで)、 新しいシグナルマスクが設定されます。 このマスクは、現在のシグナルマスクと、 届いたシグナルに対して最も最近に呼び出された sigvector()vec.sv_mask (以下を参照) の値とのビット単位の OR を計算することにより作られます。 また、 SV_RESETHAND フラグがセットされていない場合 (以下を参照)、 到着したシグナルに応じたビットをセットすることにより作られます。 ユーザーのシグナルハンドラーが正常に終了したとき、もとのマスクが再設定されます。

sigvector() は、 sig で指定されるシグナルにハンドラーを割り当てます。 vecovec は、次の要素を含んでいる sigvec 構造体へのポインタです。

void  

(*sv_handler)();

long  

sv_mask;

long  

sv_flags;

vec が 0 でない場合、 vec は、 ハンドラールーチン sv_handler) と、指定されたシグナルを届けるのに、システムが用いる マスク sv_mask) と、 シグナルの到着を変更するフラグセット sv_flags) を指定します。 ovec が 0 でない場合、 以前のシグナルの取扱いの情報がユーザーに返されます。 vec が 0 の場合、シグナルの取扱いは変更されません。 それゆえ、 sigvector() は、与えられたシグナルの現在の取扱いを調べるのに用いることができます。 vecovec が同じ構造体を指していた場合、 vec の値は上書きされる前に読み出されます。

sv_flags フィールドは、 シグナルの受け取りを変更するのに用いられます。 次のフラグビットが定義されています。

SV_ONSTACK  

sigspace() が割り当てた領域を用います。

SV_BSDSIG  

バークレー方式のシグナルを用います。

SV_RESETHAND  

signal(2) の方式を用います。

SV_ONSTACK がセットされている場合、システムは、 sigspace() システムコールでのシグナル処理のための領域を用いるか、またはその利用を許可します。

SV_BSDSIG がセットされている場合、シグナルはバークレー方式で与えられます。 次のシグナルがこのフラグにより影響されます。

SIGCLD  

子プロセスが終了したときに送られるのに加えて、 このシグナルは子プロセスのステータスが実行中 から停止に変化するたびにも送られます。 ふつうこれは、 csh ( csh(1) を参照) のようなプログラムで、 バークレー方式のジョブコントロールのもとでプロセスグループを扱うときに用いられます。

SV_RESETHAND がセットされている場合、シグナルハンドラーは、 signal(2) で設定されるハンドラーと同じ方式で設定されます。 これは、シグナルハンドラーが実行されている間のシグナルマスクの設定 (上記参照) と、 シグナルを受けた後にハンドラーがリセットされるかどうか (下記参照) に影響を与えます。

SV_RESETHAND がセットされていない場合、 いったんシグナルハンドラーが設定されると、他の sigvector() コールが行われるか、 exec() システムコール ( exec(2) を参照) が実行されるまで設定されたままになります。 SV_RESETHAND がセットされていて、シグナルが signal(5) の "not reset when caught(捕獲時にリセットしない)"のうちのひとつである場合、 デフォルトのアクションは、 シグナルが捕まってシグナルを受けとる関数に入る前に、もとに戻されます。 "not reset when caught(捕獲時にリセットしない)"の違いは、 sigvector() が呼び出されて、 SV_RESETHAND がセットされていないときは無効です。

シグナルのデフォルトの動作は、 sv_handlerSIG_DFL にセットすることによりもとに戻すことができます。 通常このデフォルトは、プロセスの終了になっています。 sv_handler が、 SIG_IGN の場合、通常シグナルは後に無視され、 ペンディングしているシグナルは捨てられます。 SIG_DFLSIG_IGN のそれぞれのシグナルの正確な意味は、 signal(5) で議論されています。

ある種のシステムコールはシグナルにより割り込まれる可能性がありますが、 他のすべてのシステムコールは、シグナルが送られる前に 完了します。 signal(5) に解説されている scp ポインタは、 sigvector() がサポートされている限り、 null にはなりません。 scp は機種に依存した sigcontext 構造体を指します。 この構造体のインプリメンテーションのすべては次のフィールドを含みます。

int  

sc_syscall;

char  

sc_syscall_action;

sc_syscall フィールドに対する SYS_NOTSYSCALL という値は、 シグナルがシステムコールに割り込んでいないことを示していて、 他のすべての値はシステムコールに割り込んでいることを示します。

受け取ったシグナルが、割込み可能なシステムコールの実行中に発生した場合、 シグナルハンドラーはすぐに起動されます。 シグナルハンドラーが正常終了すると、 sc_syscall_action フィールドの値が調べられ、その値が SIG_RETURN であれば、システムコールは中止され、割り込まれたプログラムはその呼出し を通り越して実行を続けます。 割り込まれたシステムコールの戻り値は-1 で、 errno が EINTR にセットされます。 sc_syscall_action フィールドの値が SIG_RESTART であれば、その呼び出しは再起動されます。 システムコールは、 read() もしくは write() システムコール で、データがまったく転送されていない場合に再起動されます ( read(2) または write(2) を参照)。 データがいくつか転送されていた場合、 操作は半転送で完了したとみなされ、 sc_syscall の値は SYS_NOTSYSCALL になります。 他の値は、未定義で、将来の使用のためにリザーブされています。

ハンドラーが異常終了した場合 ( longjmp() を使ったような場合 ― setjmp(3C) を参照)、それ以上のコンテキストの実行はユーザーの責任にまかされたまま、 システムコールは中止されます。 scp->sc_syscall の値が SYS_NOTSYSCALL のとき、 scp->sc_syscall_action は無視されます。 scp->sc_syscall_action は、 シグナルハンドラーの起動の前に、 常に SIG_RETURN に 初期化 されます。 割り込み可能なシステムコールが、 複数のシグナルに割り込まれたとき、 あるシグナルハンドラーが、 scp->sc_syscall_actionSIG_RETURN を返した場合、 続くシグナルハンドラーのすべては、 scp->sc_syscallSYS_NOTSYSCALL を渡します。

高速なデバイス (ディスクなど) に対する read()write()、 または ioctl() の呼出しは、割り込まれないことに注意してください。 しかし、 遅いデバイス (プリンタなど) に対する I/O 呼出しは、割り込まれることがあります。 ネットワーキングに使われるような、他のシステムコールも、 いくつかのインプリメンテーションでは、割り込まれることがあります。 このような場合は、付加的な値を scp->sc_syscall に指定できます。 scp->sc_syscall の値を見るプログラムは、 常にそれらを記号定数と比べなければいけません。 なぜなら、 これらの定数の数値表現は、インプリメンテーションにより異なるかもしれないからです。 割り込み可能な システムコールと対応する scp->sc_syscall の値を下に示します。

Callsc_syscall の値
read (遅いデバイス)SYS_READ
readv (遅いデバイス)#SYS_READV
write (遅いデバイス)SYS_WRITE
writev (遅いデバイス)SYS_WRITEV
open (遅いデバイス)#SYS_OPEN
ioctl (遅い要求)SYS_IOCTL
close (遅い要求)SYS_CLOSE
waitSYS_WAIT
selectSYS_SELECT
pauseSYS_PAUSE
sigpauseSYS_SIGPAUSE
semopSYS_SEMOP
msgsndSYS_MSGSND
msgrcvSYS_MSGRCV

<signal.h> をインクルードしたときに、 プリプロセッサマクロ _XPG2 が定義されている場合は、 これらのシステムコールは 定義されません。 これは、 『X/Open Portability Guide, Issue 2』 が SYS_OPEN ( limits(5) を参照) に対して異なった意味を割り当てているためです。

fork() または vfork() システムコールの後、 子プロセスは、 すべてのシグナル、シグナルマスク、用意されたシグナルスタック領域を引き継ぎます。

exec(2) は、 受け付けたシグナルのすべてをデフォルトのアクションに戻します。 無視されているシグナルは無視されたままで、 シグナルマスクは変更されず、 用意されたシグナルスタック領域は解放されます。

vec で指定されるマスクは、 signal(5) で定義されている、無視できないシグナルを ブロックすることはできません。 これはシステムにより暗黙のうちに強制されています。

現在終了している (ゾンビの) 子を持つプロセスが、 SIGCLD を捕まえるために sigvector() を呼び出した場合、 SIGCLD シグナルはすぐに呼出しプロセスに届けられるか、 現在 SIGCLD がブロックされているならブロックが解かれてからすぐに 届けられます。 それゆえ、 複数の子を起動していて SIGCLD を捕まえるプロセスでは、 複数のゾンビがいることを考慮して、 それぞれの起動の後で SIGCLD のハンドラーを再設定したほうがよいことがあります。 SIGCLD がハンドラーでブロックされている間に複数のプロセスが終了すると、 たった 1 つのシグナルしか到着しないので、 これは、 signal(2) のようにシステムによりリセットされないシグナルを扱う場合でも言えることです。 関数は、 wait() または wait3() を呼び出した後で、自分自身でハンドラーの再設定をしなければならないことに注意してください。 さもなければ、もとのシグナルを発生させた子プロセスが、 常にもうひとつのシグナルを送るということが起きます。

戻り値

sigvector() は正常終了した場合は 0 を返します。 異常終了した場合は-1 を返し、理由を示す値を errno にセットします。

エラー

sigvector() は次の条件のどれかを満たす場合に異常終了し、 新しいシグナルハンドラーは設定されません。

[EFAULT] 

vec または ovec がプロセスのアドレス空間の有効でない部分を指している場合。 このエラーの信頼できる検出は インプリメンテーションに依存しています。

[EINVAL] 

sig は、有効なシグナル番号でない場合

[EINVAL] 

捕まえたり、無視することができないシグナルを、 無視しようとしたり、ハンドラーを設定しようとした場合。 signal(5) を参照してください。

警告

select(2) システムコールを再起動すると、予期しない結果が起きることがあります。 select() コールにタイムアウトが指定された場合、 コールの再起動では、 タイムアウトの、シグナルによる割込みの前に経過した部分が無視されます。 通常は、これは単にタイムアウトを伸ばすだけで問題にはなりません。 しかし、ハンドラーが繰り返しシグナルを受け取り、 select() に指定したタイムアウトがそれらのシグナルの間隔より長い場合、 select() コールを再起動することは、事実上、タイムアウトを無限にすることになります。

sigvector() を、 sigset(3C) で述べた機能と組み合わせて使わないようにしてください。

廃止インタフェース

sigvector() は、将来廃止される予定です。

アプリケーション使用法

スレッドについての留意事項

sigvector() で設定されるシグナル受信時の動作 (捕捉無視デフォルト など) は、プロセス内のすべてのスレッドで共有されます。各スレッドは、ブロックされているシグナルマスクを個別に管理します。

シグナルとスレッドの詳細については、 signal(5) を参照してください。

著者

sigvector() は、HP とカリフォルニア大学バークレー校で開発されました。

参照

kill(1), kill(2), ptrace(2), sigblock(2), signal(2), sigpause(3C), sigsetmask(2), sigspace(2), setjmp(3C), signal(5), termio(7)

印刷用画面へ
プライバシー 本サイト利用時の合意事項
© 1983-2004 Hewlett-Packard Development Company, L.P.