システムインタフェース

関数

表 3-1 にリストされる関数は、ユーザプロセスの制御に使用します。

表 3-1 プロセス関数

関数名 

目的 

fork

新しいプロセスを生成する。 

exec

execl

execv

execle

execve

execlp

execvp

プログラムを実行する。 

 

 

 

 

exit

_exit

プロセスを終了する。 

wait

子プロセスが停止または終了するのを待つ。 

dladdr

アドレスをシンボルの情報に変換する。 

dlclose

共用オブジェクトを閉じる。 

dlerror

診断情報を取得する。 

dlopen

共用オブジェクトを開く。 

dlsym

共用オブジェクト内のシンボルのアドレスを取得する。 

setuid

setgid

ユーザ ID とグループ ID を設定する。 

setpgrp

プロセスグループ ID を設定する。 

chdir

fchdir

作業用ディレクトリを変更する。 

chroot

ルートディレクトリを変更する。 

nice

プロセスの優先順位を変更する。 

getcontext

setcontext

現在のユーザコンテキストを取得または設定する。 

getgroups

setgroups

補助グループ ID のリストを取得または設定する。 

getpid

getpgrp

getppid

getpgid

プロセス ID、プロセスグループ ID、および親プロセス ID を取得する。 

 

 

getuid

geteuid

getgid

getegid

実ユーザ ID、実効ユーザ ID、実グループ ID、および実効グループ ID を取得する。 

 

 

pause

シグナルを受信するまでプロセスを一時停止する。 

priocntl

プロセススケジューラを制御する。 

setpgid

プロセスグループ ID を設定する。 

setsid

セッション ID を設定する。 

waitid

子プロセスの状態が変化するまで待つ。 

新しいプロセスの生成

fork(2)

fork を呼び出すと、呼び出しプロセスを正確にコピーして新しいプロセスを生成します。この新しいプロセスを子プロセスといい、呼び出し側を親プロセスといいます。子プロセスは、新しい固有のプロセス ID を取得します。fork 関数は、正常終了すると子プロセスに 0 を戻し、親プロセスに子のプロセス ID を戻します。戻り値によって、それが親プロセスか子プロセスかがわかります。

fork 関数または exec 関数によって生成される新しいプロセスは、3 つの標準ファイル stdinstdoutstderr を含めた開いているすべてのファイル記述子を親から継承します。親プロセスが、子プロセスの出力よりも先に表示しなければならない出力をバッファリングしている場合、fork の前にバッファをフラッシュしなければなりません。

次のコード例は、fork および後続のアクションを呼び出します。

pid_t		pid;

 	pid = fork;
 	switch (pid) {
 		case -1:			/* fork が失敗した */
 			perror ("fork");
 			exit (1);
 		case 0:			/* 新しい子プロセスで */
 			printf ("In child, my pid is: %d¥n", getpid(); );
 			do_child_stuff();
 			exit (0);
 		default:			/* 親では、pid は子の PID を持つ */
 			printf ("In parent, my pid is %d, my child is %d¥n", getpid(), pid);
 			break;
 	}

 	/* 親プロセスコード */
 	...

また、親プロセスと子プロセスの両方がストリームから入力を読み込む場合、一方のプロセスが読み込んだ情報を、もう一方のプロセスは読み込むことができません。これは、入力バッファからあるプロセスに情報が送られると、読み込みポインタが移動してしまうからです。


注 -

従来は、fork()exec() を使用して別の実行プロセスを起動し、新しいプロセスが終了するまで待つという方法が使われていました。実際には、第 2 のプロセスはサブルーチンを呼び出すために作成されます。サブルーチンを一時的にメモリに常駐させるには、「実行時リンク」で説明するように、dlopen()dlsym()dlclose() を使用する方が効率的です。


exec(2)

exec は、execlexecvexecleexecveexeclpexecvp を含む関数ファミリ名です。これらの関数はいずれも、呼び出しプロセスを新しいプロセスで置き換えますが、引数のまとめ方と表し方が異なります。たとえば、execl は次のように使用できます。

execl("/usr/bin/prog2", "prog2", progarg1, progarg2, (char (*)0));

execl 引数リストは、次のとおりです。

/usr/bin/prog2

新しいプロセスファイルのパス名 

prog2

新しいプロセスが argv[0]に取り込む名前

progarg1

progarg2

prog2 への char (*) 型の引数

(char (*)0)

引数の終わりを示す NULL の char ポインタ 

詳細は、execl(2) のマニュアルページを参照してください。

exec() が正常に実行されるといかなる時でも、復帰はありません。新しいプロセスが exec を呼び出したプロセスを上書きしてしまうためです。新しいプロセスは、古いプロセスのプロセス ID やその他の属性を引き継ぎます。exec の呼び出しが失敗すると、制御は呼び出しプログラムに戻され、戻り値 -1 が返されます。errno をチェックすれば、失敗した理由がわかります。

実行時リンク

アプリケーションは、実行中に他の共用オブジェクトにバインドして、アドレス空間を拡張できます。このような共用オブジェクトの遅延バインディングには、次のような長所があります。

プロセスのスケジューリング

UNIX システムのスケジューラは、プロセスをいつ実行するかを決定します。このスケジューラは、構成パラメタ、プロセスの動作、およびユーザの要求に基づいてプロセスの優先順位を管理し、これらの優先順位を使用して CPU にプロセスが割り当てられます。

スケジューラ関数を使用すると、特定のプロセスの実行順序と、各プロセスが他のプロセスに CPU を明け渡すまでに CPU を使用できる時間をすべてユーザが制御できます。

デフォルトでは、スケジューラはタイムシェアリング方式を使用します。タイムシェアリング方式では、プロセスの優先順位を動的に調整して、対話型プロセスには適切な応答性能、CPU を多く使用するプロセスには良いスループットを提供します。

スケジューラは、実時間スケジューリング方式も提供します。実時間スケジューリングにより、ユーザはプロセスごとに優先順位を固定できます。固定優先順位とは、システムによって変更されない優先順位のことです。最も優先順位の高い実時間ユーザプロセスは、他のシステムプロセスが実行可能な状態になっても、実行可能になりしだい常に CPU を使用できます。したがって、プログラムでプロセスの正確な実行順序を指定できます。また、実時間プロセスの応答時間がシステムによって保証されるようなプログラムも作成できます。

ほとんどの Solaris 2.x システム環境では、デフォルトのスケジューラの構成で十分に機能するため、実時間プロセスは必要ありません。管理者が構成パラメタを変更したり、ユーザが各自のプロセスの優先順位を変更したりする必要はありません。ただし、タイミングの制約が厳しいプログラムでは、実時間プロセスでなければ制約を満たせないことがあります。

詳細は、priocntl(1)priocntl(2)dispadmin(1M) の各マニュアルページを参照してください。このテーマの詳細な説明は、第 4 章「プロセススケジューラ」を参照してください。