C 言語で fork 関数を使用する

胡金庫 2023年10月12日
  1. fork 関数を使って C 言語で新規プロセスを作成する
  2. 関数 exec のいずれかを用いて C 言語の子プロセスで新しいプログラムを実行する
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
著者: 胡金庫
胡金庫 avatar 胡金庫 avatar

DelftStack.comの創設者です。Jinku はロボティクスと自動車産業で8年以上働いています。自動テスト、リモートサーバーからのデータ収集、耐久テストからのレポート作成が必要となったとき、彼はコーディングスキルを磨きました。彼は電気/電子工学のバックグラウンドを持っていますが、組み込みエレクトロニクス、組み込みプログラミング、フロントエンド/バックエンドプログラミングへの関心を広げています。

LinkedIn Facebook

関連記事 - C Process