システムインタフェース

関数

表 2-1 の関数は、ユーザプロセスの制御に使用します。

表 2-1 プロセス関数

関数名 

目的 

fork(2)

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

exec(2)

execl(2)

execv(2)

execle(2)

execve(2)

execlp(2)

execvp(2)

プログラムを実行する。 

exit(2)

_exit(2)

プロセスを終了する。 

wait(2)

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

dladdr(3DL)

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

dlclose(3DL)

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

dlerror(3DL)

診断情報を取得する。 

dlopen(3DL)

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

dlsym(3DL)

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

setuid(2)

setgid(2)

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

setpgrp(2)

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

chdir(2)

fchdir(2)

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

chroot(2)

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

nice(2)

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

getcontext(2)

setcontext(2)

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

getgroups(2)

setgroups(2)

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

getpid(2)

getpgrp(2)

getppid(2)

getpgid(2)

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

getuid(2)

geteuid(2)

getgid(2)

getegid(2)

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

pause(2)

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

priocntl(2)

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

setpgid(2)

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

setsid(2)

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

waitid(2)

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

新しいプロセスの生成

fork(2)

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

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

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


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


exec(2)

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


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

exec1(2) 引数リストは、次のとおりです。

/usr/bin/prog2

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

prog2

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

progarg1

progarg2

prog2 への char (*) 型の引数

(char (*)0)

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

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

実行時リンク

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

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

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

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

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

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

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

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