C 言語で fork 関数を使用する
この記事では、C 言語で fork
関数を使用する方法をいくつか説明します。
fork
関数を使って C 言語で新規プロセスを作成する
呼び出し元のプロセスの複製を表す新しいプロセスを作成するには、fork
関数を使用します。呼び出し元のプロセスは慣習的に親プロセスと呼ばれ、新たに作成されたプロセスは子プロセスと呼ばれることに注意してください。子プロセスは親プロセスの複製であると前述しましたが、子プロセスは独自の PID を持つなどの違いがあります(違いの詳細は fork
マニュアルページに記載されています)。
以下の例では、fork
を使って 2つのプロセスを同時に実行するという単純なシナリオを実装します。最初の if
文はエラーコードが返されたかどうかをチェックし、fork
が成功した場合のみ続行します。次の if
文は、同時実行プロセスで実行されるコードをどのように構成するかを示しています。
この fork
コールは成功すると親プロセスと子プロセスの 2 回のリターンを返し、親プロセスでは子プロセスの PID を、子プロセスでは 0
の値を返すという点で、他の関数と比較して少しユニークです。プロセスの異なるコードパスを区別するために、ループの条件を適宜指定していることに注意してください。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void) {
pid_t c_pid = fork();
if (c_pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (c_pid == 0) {
printf("printed from child process - %d\n", getpid());
exit(EXIT_SUCCESS);
} else {
printf("printed from parent process - %d\n", getpid());
wait(NULL);
}
exit(EXIT_SUCCESS);
}
出力:
printed from parent process - 8485
printed from child process - 8486
関数 exec
のいずれかを用いて C 言語の子プロセスで新しいプログラムを実行する
関数 fork
を使う一般的なケースの一つに、子プロセスで新しいプログラムを実行することがありますが、これは exec
関数の一つを追加することで実現できます。このケースでは、spawnChild
という名前の別の関数を実装し、新しいプロセスを作成してから execvp
を呼び出して与えられたプログラムを実行します。子プロセスで実行するために、広く利用可能なコマンドラインプログラム top
を選びました。親プロセスは waitpid
を用いて子プロセスの状態変化を待つことができることに注意してください。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
pid_t spawnChild(const char* program, char** arg_list) {
pid_t ch_pid = fork();
if (ch_pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (ch_pid == 0) {
execvp(program, arg_list);
perror("execve");
exit(EXIT_FAILURE);
} else {
printf("spawned child with pid - %d\n", ch_pid);
return ch_pid;
}
}
int main(void) {
int ret;
const char* args[] = {"top", NULL, NULL};
pid_t child;
int wstatus;
child = spawnChild("top", args);
if (waitpid(child, &wstatus, WUNTRACED | WCONTINUED) == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
出力:
printed from child process - 8486