spawn()、spawnp() - 新規プロセスの作成

標準

標準/拡張機能 C/C++ 依存項目

POSIX.4b
z/OS®UNIX

両方  

形式

#define _POSIX_SOURCE
#include <spawn.h>

pid_t spawn(const char *path,
            const int fd_count,
            const int fd_map[],
            const struct inheritance *inherit,
            const char *argv[],
            const char *envp[]);

pid_t spawnp(const char *file,
             const int fd_count,
             const int fd_map[],
             const struct inheritance *inherit,
             const char *argv[],
             const char *envp[]);

機能説明

spawn() および spawnp() 関数は、指定プロセス・イメージから新規プロセスを作成します。spawn() と spawnp() は、新規プロセス・イメージ・ファイル という通常の実行可能ファイルから、新規プロセス・イメージを作成します。

この呼び出しの結果として、C プログラムを実行するには、次のような関数呼び出しを入力してください。
         int main (int argc, char *argv[]);
この場合、argc は引数カウント、argv は 引数そのものを指す文字ポインターの配列です。さらに、次の変数を見てみましょう。
          extern char **environ;
上記の変数は、環境ストリングの文字ポインターの配列のポインターとして、初期設定されます。argv および environ 配列 は、それぞれ NULL ポインターによって終了されます。argv 配列を終了する NULL ポインターは、argc ではカウント されません。
サポートされるパラメーターは、以下のとおりです。
パラメーター
説明
path
実行する新規プロセス・イメージ・ファイルを識別する spawn() によって使用されるパス名。
file
新規プロセス・イメージ・ファイルを識別するパス名を構成 するために、spawnp() によって使用されます。ファイル・パラメーターにスラッシュ文字が含まれている場合は 、spawnp() は、新規プロセス・イメージ・ファイルの パス名として、ファイル・パラメーターを使用します。スラッシュ文字が含まれていない場合は、spawnp() が、環境変数 PATH として渡されたディレクトリーを検索して、このファ イルのパス接頭部を取得します。
fd_count
子プロセスが継承するファイル記述子数を指定します。0 ~ OPEN_MAX の値をとることができます。SPAWN_FDCLOSED によって指定されるファイル記述子 を除き、0 ~ fd_count-1 の範囲の、それぞれ の子のファイル記述子、x は、親プロセスから記述子 fd_map[x] を継承します。

fd_countOPEN_MAX のファイルは 、SPAWN_FDCLOSED として指定される fd_map のエレメントと同様に、子プロセスでクローズされます。

fd_map
fd_map パラメーターが NULL 以外の場合には 、fd_count および fd_map は無視されます。FD_CLOEXEC または FD_CLOFORK 属性の ファイル記述子を除くすべてのファイル記述子は、リオーダー をせずに継承されます。FD_CLOEXEC または FD_CLOFORK 属性の ファイル記述子は、簡単な継承のもとでクローズされます。

オープンのままのファイル記述子の場合には、関連した ファイル記述子オブジェクトのその他のすべての属性および オープン・ファイル記述が、この演算によって、未変更のままに なります。

呼び出しプロセスでオープンの状態のディレクトリー・ストリーム は、新規プロセス・イメージでクローズされます。

fd_map のエレメントによって、無効ファイル記述子が参照 される場合は、(EBADF) spawn() または spawnp() は、エラー状況を記入します。

FD_CLOEXEC および FD_CLOFORK ファイル記述子属性が継承されることはありません。

FD_CLOEXEC および FD_CLOFORK ファイル記述子属性は、fd_map パラメーターが NULL 以外のときには、継承に影響を与えません。

注: XTI エンドポイントの場合、fd_map は、子プロセス内で 65535 より大きい数値にマップされてはなりません。
inherit
継承構造体を含むデータ域の名前。
「struct inheritance」は、以下のように定義されます。
struct inheritance {
short flags; --Flags
pid_t pgroup; --Process group
sigset_t sigmask; --Signal mask 
sigset_t sigdefault; --Signals set to SIG_DFL 
int ctlttyfd; --Cntl tty FD for tcsetpgrp() 
}
inherit.flags は、次のように spawn() と spawnp() に影響を与えます。
SPAWN_SETGROUP
SPAWN_SETGROUP フラグが inherit.flags に設定されると、子のプロセス・グループは inherit.pgroup で指定されたようになります。

SPAWN_SETGROUP フラグが inherit.flags に、inherit.prgroupSPAWN_NEWPGROUP に設定されている場合には、子は、そのプロセス ID と等しい プロセス・グループ ID の新規プロセス・グループにあります。

SPAWN_SETGROUP フラグが inherit.flags に設定 されない場合には、新規子プロセスが親のプロセス・グループ ID を 継承します。

SPAWN_SETSIGMASK
SPAWN_SETSIGMASK フラグが inherit.flags に設定 されると、子プロセスはまず、inherit.sigmask で 指定されたシグナル・マスクをとります。
SPAWN_SETSIGDEF
SPAWN_SETSIGDEF フラグが inherit.flags に設定されると、inherit.sigdefault で指定された シグナルは、子プロセスのそのデフォルト・アクションに設定 されます。親プロセスのデフォルト・アクションに設定されたシグナルは、新規プロセスのデフォルト・アクションに設定されます。

呼び出しプロセスによってキャッチされるように設定された シグナルは、子プロセスのデフォルト・アクションに設定され ます。

別の方法で、inherit.flags に設定されて いる SPAWN_SETSIGDEF フラグ と inherit.sigdefault に示されている シグナルで指定されない限り、呼び出しプロセスで無視されるように 設定されたシグナルは、新規プロセスで無視されるように設定され ます。

SPAWN_SETTCPGRP
SPAWN_SETTCPGRP フラグが inherit.flags に設定されると、inherit.ctlttyfd で指定された ファイル記述子が使用され、子のフォアグラウンド・プロセス・グループ に制御端末ファイル記述子 (tcsetpgrp()) が設定されます。inherit.flagsSPAWN_SETGROUP フラグ が設定され、inherit.pgroup で指定した値を使用 して、子のプロセス・グループを判別するよう指示されている のでなければ、子のフォアグラウンド・プロセス・グループは、親から継承されます。
SPAWN_PROCESS_INITTAB
このフラグが設定されている場合、spawn は /etc/inittab ファイルの読み取りと、そこにあるエントリーの処理をしようとします。 この処理には、子シェル・プロセスを spawn して、ファイル内で一致する各コマンドを実行することが含まれます。 SPAWN_SETSIGMASK フラグのみが、このフラグと組み合わせて設定できます。 その他のフラグはすべて無視されます。このフラグを使用する意味は、ファイル記述子 0、1、および 2 のみが子プロセスで最初にオープンされることを示します。 ファイル記述子 0 は、最初に /dev/null としてオープンされます。一方、ファイル記述子 1 と 2 は、最初に /etc/log としてオープンされます。fd_count および fd_map パラメーターは無視されます。このフラグは、現在 /usr/sbin/init プロセスに制限されています。/etc/inittab のサポートに関する詳細は、「z/OS UNIX System Services 計画」を参照してください。
argv
argv の最初のエレメントの値で、spawn() または spawnp() 演算で開始されているプロセスと関連したファイル名を示す ことが必要です。

新規プロセスの結合引数および環境リストで使用可能なバイト数は、ARG_MAX です。

envp
envp には、指定プログラムに渡される環境変数のリストが入ります。

新規プロセス・イメージ・ファイルの set-user-ID モード・ビットが設定されると、新規プロセス・イメージの 有効ユーザー ID が、新規プロセス・イメージ・ファイルの 所有者 id に設定されます。同様に、新規プロセス・イメージ・ファイルの set-group-ID モード・ビットが設定されると、新規プロセス・イメージの 有効ユーザー ID が、新規プロセス・イメージ・ファイルの グループ id に設定されます。新規プロセス・イメージの 実ユーザー ID、実グループ ID、および補足グループ ID は、呼び出しプロセス・イメージの場合と同一のままです。新規 プロセス・イメージの有効ユーザー ID および有効グループ ID は 、setuid() 関数で使用するために (保管 set-user-ID および保管 set-group-ID として) 保管されます。

新規プロセス・イメージでは、呼び出しプロセス・イメージから、属性が継承されます。
  • プロセス・グループ ID (SPAWN_SETGROUP フラグ が inherit.flags に設定されていない場合)
  • セッション・ メンバーシップ
  • 実ユーザー ID
  • 実グループ ID
  • 補足グループ ID
  • 優先順位
  • 現行作業ディレクトリー
  • ルート・ディレクトリー
  • ファイル作成マスク
  • シグナル・マスク (SPAWN_SETSIGMASK フラグが 、inherit.flags に設定されていない場合)
  • デフォルトに指定されたシグナル・アクション (SIG_DFL)
  • 無視するように指定されたシグナル・アクション (SIG_IGN) (inherit.sigdefault および inherit.flags に設定され ている SPAWN_SETSIGDEF フラグによって変更された場合は除く)
以下は、親プロセスと子プロセス間の相違点です。
  • 呼び出しプロセスによってキャッチされるように設定された シグナルは、デフォルト・アクションに設定されます (SIG_DFL)。
  • 子のプロセスおよびシステム使用効率時間は、ゼロに設定 されます。
  • 以前親によって設定されたどのファイル・ロックも、子に 継承されません。
  • 子プロセスには、アラーム・セットがありません。
  • 子プロセスには、インターバル・タイマー・セットがありません。
  • 子には、保留シグナルはありません。
  • 親によって明確化されたメモリー・マップは、子に継承されま せん。

プロセス・イメージが書き込み可能ファイル・システムから 読み取られた場合には、正常終了時に、新規プロセス・イメージ・ファイル の st_atime フィールドを更新するために、spawn() または spawnp() 関数によってマークが付けられます。

spawn() または spawnp() 関数が正常に実行されると 、open() 関数の影響にもかかわらず、新規子プロセス・イメージ・ファイルがオープンされます。

z/OSUNIX サービスの特殊な動作:
注: アプリケーションが、端末入出力を実行するシェル・コマンドまたはユーティリティーを spawn する場合、このコマンドはシェル・ファイル記述子が初期化されていないことが原因で、失敗します。 シェル・ファイル記述子が定義されている必要があります。 C アプリケーションでのそれらの定義方法の例は、以下のとおりです。
stdin = fopen("/tmp/sys.stdin","r");
stdout = fopen("/tmp/sys.stdout","w");
stderr = fopen("/tmp/sys.stderr","w");

spawn 処理は、環境変数によって制御されます。spawn 処理に影響を与えるのは、spawn syscall に渡される環境変数であり、呼び出しプロセスの環境変数ではありません。呼び出しプロセスの環境変数は、envp に渡される環境変数と同一でない限りは、spawn 処理に影響しません。

_BPXK_JOBLOG 環境変数を使用すると、WTO メッセージをオープン HFS ジョブ・ログ・ファイルに書き込むように指定できます。指定可能な値は以下のとおりです。
説明
nn
ジョブ・ログ・メッセージがオープン・ファイル記述子 nn に書き込まれます。
STDERR
ジョブ・ログ・メッセージが標準エラー・ファイル記述子 2 に書き込まれます。
なし
ジョブ・ログ・メッセージが書き込まれません。これはデフォルトです。

メッセージを取り込むために使用するファイルは、oe_env_np サービス (BPX1ENV) を呼び出して、_BPXK_JOBLOG を別のファイル記述子に指定することによって、随時変更できます。

指定されているファイル記述子に、fork または exec でクローズのマークが付けられた場合は、メッセージ取り込みがオフになります。

メッセージ取り込みは、プロセスに関連します。1 つのプロセス下では、すべてのスレッドでジョブ・ログ・ファイルを共用します。メッセージ取り込みは、そのプロセス下のどのスレッドからでも開始できます。

単一のアドレス・スペース内の複数の各プロセスで、異なるファイルを JOBLOG ファイルとしてアクティブにすることができます。一部またはすべてのプロセスで同じファイルを共用できます。また、一部のプロセスで、ほかのプロセスではアクティブにしないメッセージ取り込みをアクティブにすることができます。

ファイル記述子で表すことができるファイルだけを、ジョブ・ログ・ファイルとして使用できます。MVS™ データ・セットは使用できません。

メッセージ取り込みは、fork() または spawn() で伝搬されます。 ファイル記述子が指定された場合は、fork または作成されるプロセスでメッセージ取り込みが続行されるように、物理ファイルは同じものでなければなりません。STDERR が指定された場合は、ファイル記述子を別の物理ファイルに再マップできます。

メッセージ取り込みは、exec() または spawn() で指定変更できます。変更するには、_BPXK_JOBLOG 環境変数を exec() または spawn() のパラメーターとして指定します。

メッセージ取り込みは、fork された (BPXAS) アドレス・スペースでのみ行われます。
注: これは、本当のジョブ・ログのサポートではありません。通常 JESYSMSG データ・セットへ行くメッセージは取り込まれますが、JESMSGLG へ行くメッセージは取り込まれません。

環境変数の使用についての詳細は、「z/OS UNIX System Services プログラミング: アセンブラー呼び出し可能サービス 解説書) を参照してください。

_BPX_USERID 環境変数で別のものを指定しなければ、親のアドレス・スペースからのセキュリティー情報は、子のアドレス・スペース に伝搬されます。その結果、子は親と等しいセキュリティー環境 をとります。

現行タスクでアクティブな TASKLIB、STEPLIB、または JOBLIB DD データ・セット割り振りは、STEPLIB 環境変数で別のものを指定しな ければ、子のアドレス・スペースに伝搬されます。このため、子のアドレス・スペースでは、呼び出し親タスクとまったく同一 の MVS プログラム検索順序をとることになります。

親のアドレス・スペースのアカウンティング情報は、子のアドレス・スペースに伝搬されます。「z/OS UNIX System Services 計画) を参照してください。

親のジョブ名は子に伝搬され、このジョブ名が 7 文字または それより少なかった場合には、1 ~ 9 の範囲の数値が付加されます。ジョブ名が 8 文字の場合には、そのまま伝搬されます。ジョブ名 に数値が付加される場合、この数が 9 を超えると 1 に 戻ります。

呼び出し親タスクが WLM エンクレーブにある場合には、子は同じ WLM エンクレーブに結合されます。このため、WLM では親と子を、システム・アカウンティングおよび管理目的のための 1 つの「作業単位」エンティティーとして管理できます。

作成された子プロセスを、親のアドレス・スペースとは別の アドレス・スペースまたは同じアドレス・スペースのどちらで実行するか呼び出し元が制御でき るように、spawn サービスで _BPX_SHAREAS 環境変数を指定することができます。以下に、_BPX_SHAREAS 環境変数に受け入れられる値と、それぞれの 値で取られるアクションを示します。
  1. _BPX_SHAREAS=YES - 作成する子プロセスを、親プロセスと同じアドレス・スペースで実行することを指定します。以下の状況では、_BPX_SHAREAS=YES 値は受け入れられず、子プロセスは、それ自身のアドレス・スペースで作成されます。
    • 実行するプログラムが、set-user-ID プログラムまたは set-group-ID プログラムであり、そのプログラムを実行した結果、子プロセス の有効なユーザー ID またはグループ ID が、親プロセスの ユーザー ID またはグループ ID と異なる。
    • 実行するプログラムが、APF 許可 HFS プログラムまたは MVS プ ログラムであり、呼び出し元が APF 許可プログラムを実行中ではない。
    • 実行するプログラムが、無許可 HFS プログラムまたは MVS プログラムであり、呼び出し元が APF 許可プログラムを実行中である。
    • 指定ファイル名が、外部リンクまたはスティッキー・ビット・ファイルを表している。ただし、実行するプログラムがシェル・スクリプトであり、_BPX_SPAWN_SCRIPT=YES が設定されている場合、そのプロセスは同じアドレス・スペースで実行される。_BPX_SPAWN_SCRIPT は、z/OS シェル (/bin/tcsh ではなく、/bin/sh) で実行中の場合の み、効果があります。
    • 別のプロセスを作成するための十分なリソースが親のアドレス・スペースにない。

    指定の時間にサポートされるローカル作成プロセスは、1 つの TSO アドレス・スペースに対して 1 つだけです。これにより、同じアドレス・スペースで複数のシェルを実行する場合の対立を削減することができます。

  2. _BPX_SHAREAS=MUST - 作成する子プロセスを、親プロセスと同じアドレス・スペース で実行すること、それが不可能な場合は spawn 要求が失敗する ことを指定します。以下の状況では、_BPX_SHAREAS=MUST 値は受け入れられず、spawn 呼び出しは失敗します。
    • 実行するプログラムが、set-user-ID プログラムまたは set-group-ID プログラムであり、そのプログラムを実行した結果、子プロセス の有効なユーザー ID またはグループ ID が、親プロセスの ユーザー ID またはグループ ID と異なる。
    • 実行するプログラムが、APF 許可 HFS プログラムまたは MVS プ ログラムであり、呼び出し元が APF 許可プログラムを実行中ではない。
    • 実行するプログラムが、無許可 HFS プログラムまたは MVS プログラムであり、呼び出し元が APF 許可プログラムを実行中である。
    • 別のプロセスを作成するための十分なリソースが親のアドレス・スペースにない。
  3. _BPX_SHAREAS=REUSE - 作成する子プロセスを、親プロセスと同じ アドレス・スペースで実行すること、および、その子プロセスを中レベルのプロセスとして作成することを指定します。呼び出し元は、REUSE を指定することで、ローカルで作成されたプロセスに対応する既存のプロセス構造体を再利用することを指示できます。
    ローカル作成プロセスの作成に適用される仕様と同じ規則が、中レベルのローカル作成プロセスにも適用されます。 さらに、以下の状況では、_BPX_SHAREAS=REUSE 値は受け入れられず、子プロセスは中レベル以外のローカル作成プロセスとして作成されます。
    • プロセスに対して、PTRACE がアクティブの場合。
    • 実行するプログラムが、REXX exec の場合。

    パフォーマンスの理由により、アドレス・スペース用に作成される中レベルの各プロセスに対しては、同じ STEPLIB を指定してください。

  4. _BPX_SHAREAS=NO - 作成する子プロセスを、親プロセスとは別のアドレス・スペースで実行するように指定します。_BPX_SHAREAS 環境変数が指定されていない場合、もしくは _BPX_SHAREAS 環境変数にサポートされない値が入っている場合は、これが spawn サービスのデフォルトの動作になります。

_BPX_USERID 環境変数を指定すると、 spawn() は、指定されたユーザー ID の識別で新しいアドレス・スペースとイメージを 作成します。spawn() の起動側は、MVS 識別を変更する権限を 持っている必要があります。結果として、プログラムが fork()、 setgid()、initgroups()、setuid()、および exec を実行したときのように、spawn() イメージが生成されます。

_BPX_USERID の値は、1 ~ 8 文字の XPG4 準拠のユーザー名にすることができます。_BPX_USERID と _BPX_SHAREAS の両方を指定する と、spawn() は _BPX_SHAREAS を無視して、新規の識別で新しいアドレス・スペース を作成します。

spawn() 関数の呼び出し元が z/OSUNIX シェル・スクリプト (つまり、/bin/sh) の場合には、_BPX_SPAWN_SCRIPT = 環境変数の設定を YES にすることをお勧めします。この変数を YES に設定することで、z/OSUNIX シェル・スクリプトを起動するさらに効率的なメカニズムが提供されます。

STEPLIB 環境の新規プロセス・イメージへの生成および伝搬をサポートするために、spawn() および spawnp() は、STEPLIB 環境変数を指定できます。以下は、STEPLIB 環境変数の受け入れ値および それぞれで行われるアクションです。
  • STEPLIB=NONE。新規プロセス・イメージの Steplib DD が作成されません。
  • STEPLIB=CURRENT。spawn() および spawnp() への呼び出しの際に、呼び出しタスクでアクティブになっている TASKLIB、STEPLIB、または JOBLIB DD データ・セット割り振りは、カタログされていることが確認された場合は、新規プロセス・イメージに伝搬されます。カタログされていないデータ・セットは、新規プロセス・イメージに伝搬されません。
  • STEPLIB=Dsn1:Dsn2:,...DsnN。指定したデータ・セットの Dsn1:Dsn2:...DsnN は、新規プロセス・イメージの STEPLIB DD に組み込まれます。
    注: DD の実際の名前は STEPLIB ではありません が、STEPLIB DD と同じ効果を持つシステム生成名です。
データ・セットは指定した順に連結されます。 指定するデータ・セットは、標準 MVS データ・セット命名規則に従わなければなりません。 この標準に違反しているデータ・セットは無視されます。データ・セットが標準に従っていても、以下の条件が該当する 場合、データ・セットは無視されます。
  • 呼び出し元に、データ・セットへの適切なセキュリティー・アクセス がない。
  • データ・セットがカタログされていない、または ロード・ライブラリー形式ではない。
エラー状態のデータ・セットは無視されるため、実行可能ファイル は、適切な STEPLIB 環境を使用しないで実行されることがあります。不適切なセキュリティー・アクセスのためにデータ・セットが エラー状態の場合、X'913' 異常終了が生成されます。この異常終了のダンプは、ユーザーのインストールによって 抑制することができます。

STEPLIB 環境変数が指定されていない場合、spawn() および spawnp() のデフォルトの動作は、STEPLIB=CURRENT が指定されている場合と同じになります。

起動するプログラムが set-user-ID ファイルまたは set-group-ID ファイルで、ファイルのユーザー ID または グループ ID が現行プロセス・イメージのそれと異なる場合には、新規プロセス・イメージの STEPLIB 環境に組み立てられるデータ・セット は、set-user-id および set-group-id プログラム のシステム許可にあることが必要です。許可リストにあるデータ・セットのみが、新規プロセス・イメージの STEPLIB 環境に作成されます。 認可リスト、および STEPLIB のパフォーマンス考慮事項に関する詳細は、「z/OS UNIX System Services 計画) を参照してください。

注 :
  1. 無許可ライブラリーから MVS XCTL サービスによる、以前ロードされた MVS 無許可プログラムの再利用へ適用する同じ状況下で、同一アドレス・スペースで以前にロードされた HFS プログラムのコピーは 再利用されます。ただし、以下のような例外があります。
    • 呼び出しプロセスが Ptrace デバッグ・モードの場合、以前にロードされたコピーは再使用されません。
    • 呼び出しプロセスが Ptrace デバッグ・モードではない が、HFS プログラムの中で以前にロードした唯一の 使用可能コピーが呼び出し元で変更可能なストレージにある場合、以前のコピーは再利用されません。
  2. 指定のファイル名が外部リンクまたは スティッキー・ビット・ファイルを表す場合、プログラムは 呼び出し元の MVS ロード・ライブラリーの検索順序で ロードされます。外部リンクの場合、外部名は、名前が 8 文字以下の場合にのみ使用されます。その他の場合は、呼び出し元は loadhfs サービスからエラーを受け取ります。スティッキー・ビット・プログラムの場合は、ファイル名は 8 文字以下の場合にのみ使用されます。ファイル名が 8 文字より多い場合、プログラムは HFS からロードされ、set-user-ID 属性または set-group-ID 属性を持つスティッキー・ビット・プログラムに対して次の制限があります。

    プログラムが MVS プログラム検索順序で見つかる場合、MVS プログラム名は RACF® FACILITY クラスで定義された BPX.STICKYSUG.program_name リソース・プロファイルである必要があります。リソース・プロファイルの定義について詳しくは、 z/OS UNIX System Services 計画ブックを参照してください。この制限に従わない場合、コード xxxxE055 での異常終了 EC6 の原因となります。

  3. 呼び出しタスクが WLM エンクレーブにある場合、新規プロセス・イメージ内の結果のタスクは、同一 WLM エンクレーブへ結合されます。このため、WLM では新旧プロセス・イメージを、システム・アカウンティングおよび管理目的のための 1 つの「作業単位」エンティティーとして管理できます。
注: この関数で z/OS UNIX マジック番号サポートを利用するには、プロセス初期化時に、POSIX(ON) の Language Environment® ランタイム・オプションを設定しておく必要 があります。POSIX(OFF) を指定して開始したプロセスでマジック番号サポートを利用しようとすると、何らかの障害が起きることがあります。z/OS UNIX マジック番号の詳細と使用法については、「z/OS UNIX System Services 計画) および「z/OS UNIX System Services ユーザーズ・ガイド) を参照してください。

戻り値

正常に実行された場合には、spawn() と spawnp() は、子プロセスのプロセス ID の値を親プロセスに戻します。

正常に実行されなかった場合には、spawn() と spawnp() は、-1 を戻し、子プロセスは作成されず、errno を次のいずれかの値に設定します。
エラー・コード
説明
E2BIG
引数および新規プロセス・イメージの環境リストで使用される バイト数が、ARG_MAX バイトの システムが課す制限より大きくなっています。
EACCES
新規プロセス・イメージ・ファイルのパスのディレクトリーで、検索許可が拒否されるか、または新規プロセス・イメージ・ファイル で許可の実行が拒否されます。あるいは 新規プロセス・イメージ・ファイルが通常のファイルではなく、インプリメンテーションでこのタイプのファイルの実行が サポートされません。
EAGAIN
システムに別のプロセスを作成するのに必要なリソースがないか、あるいは一人のユーザーによる実行のもとで、プロセスまたは UID の 合計数のシステムが課す制限を超えている場合があります。
EBADF
fd_map 配列のエントリーは、無効ファイル記述子 を指しているか、あるいは inherit.ctlttyfd で指定された 制御端末ファイル記述子が無効です。
EFAULT
呼び出しのパラメーターを使用しようとしていて、システムで 無効アドレスが検出されました。
EINVAL
以下の条件 (1 つ以上) が検出されました。
  • _BPX_USERID 環境変数に指定したユーザー名の長さが正し くない。
  • 継承構造体 (BPXYINHE) 内に指定された属性が無効である、また はサポートされない値が入っている。
  • 継承構造体 (BPXYINHE) に対して指定したバージョン番号が無効である。
  • Inherit_area_len パラメーターで指定されている継承構造体の長さ、ま たは継承構造体内に指定されている長さが、BPXYINHE バージョン用の適切な長さではない。
  • 継承構造体で指定されているプロセス・グループ ID が、ゼロより小さ いか、あるいはサポートされない値である。

次の理由コード JROK、JRUserNameLenError、JRJsRacXtr、 JRInheUserid、JRInheRegion、JRInheCPUTime、JRInheDynamber、 JRInheAccountData、JRInheCWD、JRInheSetPgrp、 JRInheVersion、および JRInheLength が、戻りコードに添付される場合があります。

ELOOP
file 引数の解決時に現れたシンボリック・リンクに、ループが存在しています。8 より多いシンボリック・リンクが、ファイル名の解決で検出される場合に、このエラーが発行されます。
EMVSERR
MVS 内部エラーが発生しました。これは、spawn() または spawnp() のユーザー呼び出しにおけるセキュリティー権限に問題があることを示しています。
EMVSSAF2ERR
実行可能ファイルが set-user-ID または set-group-ID ファイルであり、ファイル所有者の UID または GID がセキュリティー許可機能 (SAF) に対して定義されていないか、 _BPX_USERID が指定され、指定ユーザー名が z/OSUNIX セグメントで SAF に対して定義されませんでした。
ENAMETOOLONG
path または file 引数の長さ、あるいは file の接 頭部である環境変数 PATH のエレメントが PATH_MAX を超えているか、またはパス名のコンポーネントが NAME_MAX より長く、{_POSIX_NO_TRUNC} がそのファイルに対して有効です。
ENOENT
新規プロセス・イメージ・ファイルのパス名の 1 つ以上のコンポーネントが存在していないか、あるいは path または file 引数が空です。
ENOEXEC
新規プロセス・イメージ・ファイルに適切なアクセス許可は ありますが、形式が適切ではありません。
注: さらに、理由コードが errno に加わります。 理由コードについては、「z/OS UNIX System Services メッセージおよびコード」を参照してください。
ENOEXEC の場合、該当する理由コードは以下のとおりです。
理由コード 説明
X'xxxx0C27' ターゲットの HFS ファイルのフォーマット設定が正しく ないため、実行可能ファイルになりません。
X'xxxx0C31' ターゲットの HFS ファイルは、実行システム でサポートされているレベルより高いレベルで作成されています。
ENOMEM
新規プロセスには、ハードウェアまたは オペレーティング・システムで許可されている容量以上のメモリーが 必要です。
ENOTDIR
新規プロセス・イメージ・ファイルのパス接頭部のコンポーネント が、ディレクトリーではありません。
ENOTTY
inherit.ctlttyfd の指定制御端末ファイル記述子 のために、tcsetpgrp() は失敗しました。呼び出しプロセスに 制御端末がないか、または指定ファイル記述子が制御端末と関連 していないか、あるいは制御端末が既に呼び出しプロセスの セッションと関連していないことが原因で、障害が発生しました。
EPERM
spawn は、次のいずれかの理由で失敗しました。
  • 生成されたプロセスが、プロセス・グループ・リーダーではない。
  • _BPX_USERID 環境変数が指定されていても、MVS 識別を変更するための適切な特権が呼び出し元にない。
  • 継承構造体 (BPXYINHE) 内に指定されている属性 (1 つ以上) を変更するための特権が呼び出し元にない。

次の理由コード JROK、JRNoChangeIdentity、JRInheUserid、 JRInheRegion、JRInheCPUTime、JRInheUmask、および JRInheCWD が、戻りコードに添付される場合があります。

ESRCH
inherit.pgroup で指定されたプロセス・グループ ID は、呼び出しプロセスのセッションのプロセス・グループのものではありません。

spawn を使って子プロセスを作成する親プロセスの例を以下に示します。
#define _XOPEN_SOURCE_EXTENDED 1
#include <unistd.h>
#include <spawn.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>

/* This program uses spawn instead of fork/exec to create a child
 * process and uses unnamed pipes to allow the parent and child to
 * exchange communication.
 */


void main(int argc, char *argv[])  {
	pid_t child;
	int fd_count, fd_map[10];
	struct inheritance inherit;
	const char *c_argv[10], *c_envp[10];
	char buf[256];
	int nbytes;

	int c_stdin[2], c_stdout[2], c_stderr[2];  /* Pipes for child
        * communication */

	/* Create pipes to communicate with child via stdin/stdout/stderr */
	if(pipe(c_stdin)  ||
	   pipe(c_stdout) ||
	   pipe(c_stderr) ) {
		perror("Bad pipe");
                exit(-1);
                }

	/* Set up file descriptor map for child process */
	fd_map[0]=dup(c_stdin[0]);  /* child stdin is read end of pipe */
	fd_map[1]=dup(c_stdout[1]); /* child stdout is write end of pipe */
	fd_map[2]=dup(c_stderr[1]); /* child stderr is write end of pipe */
	fd_count=3;

	/* Close unused end of pipes for the parent */
        close(c_stdin[0]); close(c_stdout[1]); close(c_stderr[1]);

	/* Build the argument structure for child arguments.
        *  [0] is the program name */
	c_argv[0]="spawnc";
	c_argv[1]="arg1"; c_argv[2]="arg2"; c_argv[3]=NULL;

	/* Build the environment structure which defines the child's
        * environment variables */
	c_envp[0]="TEST_ENV=YES"; c_envp[1]="BPX_SHAREAS=NO"; c_envp[2]=NULL;
	
	/* Spawn the child process */
	child=spawnp("spawnc", fd_count, fd_map, &inherit, c_argv, c_envp);
	if(child==-1) {
		perror("Error on spawn");
		exit(-1);
		}
	else printf("Spawned %i¥n", child);

	/* Test interaction with the child process */
	printf("parent: Asking child, ¥"what are you doing?¥¥n¥"¥n");
	strcpy(buf, "child from parent: what are you doing?¥n");
	if(write(c_stdin[1], buf, sizeof(buf))==-1)  {
		perror("write stdout");
		exit(-1);
		}

	memset(buf, 0, 255);  /* Just zeroing out the buffer */
	printf("parent: reading from child now¥n");
	if((nbytes=read(c_stdout[0], buf, 255))==-1) {
		perror("read error:");
		exit(-1);
		}
	printf("parent: child says, ¥"%s¥"¥n", buf);
	
	/* Cleanup pipes before exiting */
	close(c_stdin[1]); close(c_stdout[0]); close(c_stderr[0]);

 	exit(0);
}

spawn が使用する子プログラムの例を以下に示します。
#include <stdlib.h>
#include <stdio.h>

/* This is a sample child program used by spawn.  This program will
 * work stand-alone as well as from spawn or fork/exec. */

extern char ** environ; /* External used to access the environment
			   directly instead of using getenv */

void main(int argc, char *argv[]) {

	char *e, **env=environ;  /* Used to step through the environment
				  * to write out to file. */
	char buf[256]={0};
	FILE *fp=fopen("spawntest.out","w");
 	int i;

	/* Print out the environment variables */
	i=0;
	fprintf(fp, "Environment:¥n");
	while(e=env[i++])  fprintf(fp, "%s¥n", e);
	fprintf(fp, "¥n¥n");

	/* Just to prove getenv works */
	fprintf(fp, "TEST_ENV envvar = %s", getenv("TEST_ENV"));

	/* Print out the command line arguments */
	i=0;
	fprintf(fp,"Args:¥n");
	while(e=argv[i++]) fprintf(fp,"%s¥n", e);
	fprintf(fp, "¥n¥n");
	
	/* Print out what was sent on stdin */
	fprintf(fp, "Child/parent¥n");
	if(!gets(buf)) {
		ferror(stdin);
		exit(-1);
		}
	fprintf(fp, "child from parent: %i bytes,[%s]¥n", strlen(buf), buf);

	/* Send something to stdout */	
	printf("nothing");

	fclose(fp);
	exit(0);
}