日本-日本語 |
|
|
|
OpenVMS マニュアル |
|
HP OpenVMS
|
目次 | 索引 |
HP C Run-Time Library (RTL) では, HP C プログラムからサブプロセスを生成するための関数が提供されます。サブプロセスを生成するプロセスを親と呼び,生成されるサブプロセスを子と呼びます。
親プロセスの内部で子プロセスを生成するには, exec関数 ( execl, execle, execv, execve, execlp, execvp) および vfork関数を使用します。その他にも,親プロセスと子プロセスがプロセス間でデータの読み書きを実行するための関数 ( pipe) や 2 つのプロセスの同期をとるための関数 ( wait) などもあります。この章では,これらの関数の実装の方法と使用方法について説明します。
親プロセスは子プロセスの内部で,同期的または非同期的に HP C プログラムを実行できます。同時に実行できる子プロセスの数は,システムの各ユーザに対して設定されている /PRCLM ユーザ登録クォータによって決定されます。サブプロセスの使用に影響を与える可能性のあるその他のクォータとしては, /ENQLM (キュー・エントリ・リミット),/ASTLM (AST 待ちリミット), /FILLM (オープン・ファイル・リミット) があります。
この章では,サブプロセス関数について説明します。 表 5-1 は, HP C RTL で提供されるすべてのサブプロセス関数を示しています。各関数の詳細については,『HP C ランタイム・ライブラリ・リファレンス・マニュアル (下巻)』「リファレンス・セクション」を参照してください。
関数 | 説明 |
---|---|
子プロセスの生成 | |
system | コマンド・プロセッサによって実行される文字列をホスト環境に渡す。 |
vfork | 独立した子プロセスを生成する。 |
exec 関数 | |
execl,execle,execlp
execv,execve,execvp |
子プロセスの内部で起動されるイメージの名前を渡す。 |
プロセスの同期化 | |
wait , wait3 , wait4 , waitpid | 値が子から返されるまで,親プロセスを一時停止する。 |
プロセス間通信 | |
pipe | 親プロセスと子プロセスの間の通信を可能にする。 |
子プロセスは,OpenVMS LIB$SPAWN RTL ルーチンと HP C 関数によって生成されます (LIB$SPAWN の詳細については,『VMS Run-Time Library Routines Volume』を参照してください)。 LIB$SPAWN を使用すると,複数レベルの子プロセスを生成できます。親から生成された子がさらに子を生成することができます。生成できるレベルは,この章の冒頭で説明したユーザ登録クォータで認められている上限値までです。
子プロセスは他の HP C プログラムだけを実行できます。他のネイティブ・モードの OpenVMS 言語は,プロセス間で通信するために HP C の機能を共用しません。プロセス間で通信する場合,他の言語は同じ機能を使用しません。親プロセスは,DCL など,弊社がサポートするコマンド言語インタプリタ (CLI) のもとで実行しなければなりません。親を独立プロセスとして実行したり,ユーザ指定 CLI の制御のもとで実行することはできません。
DECC$DETACHED_CHILD_PROCESS 機能論理名を有効にすると,子プロセスが,サブプロセスではなく,デタッチされたプロセスとして生成されます。この機能のサポートには,制限があります。場合によっては,コンソールが親プロセスと,デタッチされたプロセスで共用できず, execが失敗することがあります。
親プロセスと子プロセスは, 図 5-1 に示すようにメールボックスを通じて通信します。このメールボックスは,子が実行されるコンテキストを転送します。このコンテキスト・メールボックスは,親がオープンしたすべてのファイルの名前やファイル記述子,それらのファイル内での現在の位置など,親から継承する情報を子に渡します。子イメージが終了すると,メールボックスは親によって削除されます。
図 5-1 親プロセスと子プロセスの間の通信リンク
注意 vfork関数と exec関数によって作成されるメールボックスは一時的なものです。このメールボックスの論理名は VAXC$EXECMBX であり, HP C RTL で使用するために予約されています。 |
メールボックスは 512 バイトの最大メッセージ・サイズおよび 512 バイトのバッファ・クォータで作成されます。これらの RTL 関数を使用してメールボックスを作成するには,TMPMBX 特権が必要です。 TMPMBX は DCL コマンド PRINT および SUBMIT で必要とされる特権であるため,システムの大部分のユーザはこの特権を保有しています。保有しているシステム特権を確認するには, SHOW PROCESS/PRIVILEGES コマンドを入力します。
これらのメールボックスの属性を変更することはできません。メールボックスの詳細については,『VMS I/O User's Reference Volume』を参照してください。
5.2 exec 関数
子プロセスで HP C イメージを実行するために呼び出すことのできる exec関数は 6 つあります。これらの関数では,戻りアドレスを設定するために vforkがあらかじめ呼び出されていることが必要です。 exec関数は,親プロセスで vforkが呼び出されていない場合,その関数を呼び出します。
vforkが親で呼び出されると, exec関数は親プロセスに戻ります。 vforkが exec関数によって呼び出されると, exec関数はその関数自体に戻り,子プロセスが終了するのを待ち,その後で親プロセスを終了します。 exec関数は,親が vforkを呼び出して戻りアドレスを保存しない限り,親プロセスに戻りません。
OpenVMS Version 7.2 で, exec関数は実行可能イメージまたは DCL コマンド・プロシージャを起動するように拡張されました。ファイル拡張が file_name 引数に指定されていない場合は,この関数はまずファイル拡張が .EXE であるファイルを検索し,次にファイル拡張が .COM であるファイルを検索します。同じ名前の実行可能イメージとコマンド・プロシージャの両方が存在する場合は,コマンド・プロシージャを強制的に起動するために, .COM ファイル拡張を指定する必要があります。
DCL コマンド・プロシージャの場合は, exec関数は, P1,P2,...パラメータなど, exec呼び出しに指定した最初の 8 つの arg0, arg1,... 引数をコマンド・プロシージャに渡します。その場合,大文字と小文字の区別は保持されます。
UNIX ベースのシステムと異なり, HP C RTL の exec関数は,指定された実行可能イメージまたはコマンド・プロシージャが存在するかどうか,またこれらを起動および実行できるがどうかを常に判断できるわけではありません。したがって, exec関数は,子プロセスが指定されたファイルを実行できない場合でも,正常終了したように見えることがあります。
親プロセスへ返される子プロセスの状態は,エラーが発生したことを示します。このエラー・コードは, wait関数ファミリのいずれかの関数を使用することにより検索できます。
注意 OpenVMS システムの HP C RTL の vfork関数と exec関数は, UNIX システムの場合と異なる方法で動作します。
プログラマの場合,次の重要な相違点に注意してください。
|
5.2.1 exec の処理 |
exec関数では, LIB$SPAWN ルーチンを使用してサブプロセスを生成し,サブプロセス内で子イメージを起動します。この子プロセスは,定義されているすべての論理名やコマンド・ライン・インタプリタ・シンボルなど,親の環境を継承します。
デフォルトでは,子プロセスは親プロセスのデフォルト (作業) ディレクトリも継承します。ただし, decc$set_child_default_dir関数を使用して,子プロセスの実行開始時のデフォルト・ディレクトリを設定できます。 decc$set_child_default_dir関数の詳細については,『HP C ランタイム・ライブラリ・リファレンス・マニュアル (下巻)』の「リファレンス・セクション」を参照してください。
exec関数は論理名 VAXC$EXECMBX を使用して,親と子の間の通信を行います。この論理名は親イメージのコンテキストの内部に存在しなければなりません。
すべての情報が子に転送されると, execの処理は終了します。親プロセス内の制御は, vforkによって保存されたアドレスに返され,子のプロセス ID は親に返されます。
シグナル動作および SIGCHLD シグナルの詳細については, 第 4.2.4 項 を参照してください。
5.2.2 exec のエラー条件
LIB$SPAWN がサブプロセスを生成できない場合は, exec関数は異常終了します。エラーの原因となる可能性のある条件としては,サブプロセス・クォータの超過や,親と子の間でコンテキスト・メールボックスによる通信が不能であることの検出などがあります。一部のクォータは,超過しても LIB$SPAWN がエラーになることはありませんが, LIB$SPAWN が待ち状態になり,その結果,親プロセスがハングする可能性があります。このようなクォータの例としては,オープン・ファイル・リミット・クォータがあります。
オープン・ファイル・リミット・クォータは少なくとも 20 ファイルに設定する必要があり,平均値はプログラムで同時に実行するプロセスの数の 3 倍です。一度に複数のオープン・パイプを使用する場合や,一度に複数のファイルに対して I/O を実行する場合は,このクォータをさらに大きくする必要があります。このクォータを増大する必要があるかどうかについては,システム管理者にお問い合わせください。
exec関数が異常終了した場合, - 1 という値が返されます。このような障害が発生した後,親は
exit関数または
_exit関数を呼び出すことが期待されます。どちらの関数も親の
vfork呼び出しに戻り,この関数呼び出しは子のプロセス ID を返します。この場合,
exec関数から返される子プロセス ID は 0 より小さくなります。
exit関数の詳細については,『HP C ランタイム・ライブラリ・リファレンス・マニュアル (下巻)』「リファレンス・セクション」を参照してください。
5.3 プロセスの同期化
親プロセスが終了すると,子プロセスも終了します。したがって,親プロセスは終了する前に,子プロセスの状態を確認する必要があります。この処理は, HP C RTL 関数
waitを使用して行います。
5.4 プロセス間通信
親プロセスと子プロセスが通信するチャネルはパイプと呼ばれます。パイプを作成するには,
pipe関数を使用します。
5.5 プログラムの例
例 5-1 は,子プロセスでイメージを実行するための基本手順を示しています。 例 5-1 の子プロセスはメッセージを 10 回プリントします。
例 5-1 子プロセスの生成 |
---|
/* chap_5_exec_image.c */ /* This example creates the child process. The only */ /* functionality given to the child is the ability to */ /* print a message 10 times. */ #include <climsgdef.h> /* CLI status values */ #include <stdio.h> #include <perror.h> #include <processes.h> #include <stdlib.h> static const char *child_name = "chap_5_exec_image_child.exe" ; main() { int status, cstatus; /* NOTE: */ /* Any local automatic variables, even those */ /* having the volatile attribute, may have */ /* indeterminant values if they are modified */ /* between the vfork() call and the matching */ /* exec() call. */ (1) if ((status = vfork()) != 0) { /* This is either an error or */ /* the "second" vfork return, taking us "back" */ /* to parent mode. */ (3) if (status < 0) printf("Parent - Child process failed\n"); else { printf("Parent - Waiting for Child\n"); (4) if ((status = wait(&cstatus)) == -1) perror("Parent - Wait failed"); (5) else if (cstatus == CLI$_IMAGEFNF) printf("Parent - Child does not exist\n"); else printf("Parent - Child final status: %d\n", cstatus); } } (2) else { /* The FIRST Vfork return is zero, do the exec */ printf("Parent - Starting Child\n"); if ((status = execl(child_name, 0)) == -1) { perror("Parent - Execl failed"); exit(EXIT_FAILURE); } } } ---------------------------------------------------------- |
/* CHAP_5_EXEC_IMAGE_CHILD.C */ /* This is the child program that writes a message */ /* through the parent to "stdout" */ #include <stdio.h> main() { int i; for (i = 0; i < 10; i++) printf("Child - executing\n"); return (255) ; /* Set an unusual success stat */ } |
例 5-1 の補足説明:
目次 | 索引 |
|