C++によるプロセス制御

1.fork関数によるマルチプロセス

fork関数を呼び出すと現在のプロセス(親プロセス)が複製され、子プロセスが生成されます。
親プロセスは pid > 0、子プロセスは pid = 0 です。getpid() は自プロセスのプロセスIDを表します。

fork1.cpp (Cygwin)

#include <iostream>
#include <sys/wait.h>
#include <unistd.h>

auto main() -> int {
  std::cout << "Hello!" << std::endl;
  pid_t pid = fork();
/*
  int status;
  wait(&status);
*/
  for (int i = 0; i < 10; i++) {
    std::cout << pid << ":" << getpid() << ":" << "Multi-Process!" << std::endl;
  }
}

上記のプログラムを実行するとfork関数以降が親プロセスと子プロセスのマルチプロセスで実行されます。尚、wait関数を使うと親プロセスは子プロセスが終了するまで待機します。

〈実行結果〉

$ ./exec
Hello!
2735:1557:Multi-Process!
2735:1557:Multi-Process!
0:2735:Multi-Process!
0:2735:Multi-Process!
2735:1557:Multi-Process!
2735:1557:Multi-Process!
2735:1557:Multi-Process!
2735:1557:Multi-Process!
2735:1557:Multi-Process!
0:2735:Multi-Process!
0:2735:Multi-Process!
0:2735:Multi-Process!
2735:1557:Multi-Process!
2735:1557:Multi-Process!
2735:1557:Multi-Process!
0:2735:Multi-Process!
0:2735:Multi-Process!
0:2735:Multi-Process!
0:2735:Multi-Process!
0:2735:Multi-Process!


親プロセスと子プロセスで異なる処理をさせる場合は以下のようにします。

fork2.cpp (Cygwin)

#include <iostream>
#include <unistd.h>

auto main() -> int {
  pid_t pid = fork();
  if (pid > 0) {
    std::cout << "Parent Process!" << std::endl;
    return 0;
  }
  if (pid == 0) {
    std::cout << "Child Process!" << std::endl;
    return 0;
  }
  if (pid < 0) {
    std::cerr << "Error!" << std::endl;
    return -1;
  }
}


2.pipe関数によるプロセス間通信(interprocess communication)

pipe関数を使えば親プロセスと子プロセスの間で通信を行えます。下記のプログラムは子プロセスから親プロセスにデータを送信するプログラムです。

pipe.cpp (Cygwin)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <unistd.h>

auto main() -> int {
  char buffer[1024];
  int pipefd[2];
  pipe(pipefd);
  pid_t pid = fork();
  if (pid > 0) {
    close(pipefd[1]);
    read(pipefd[0], buffer, sizeof(buffer));
    std::cout << buffer;
    close(pipefd[0]);
    return 0;
  }
  if (pid == 0) {
    close(pipefd[0]);
    fgets(buffer, sizeof(buffer), stdin);
    write(pipefd[1], buffer, strlen(buffer) + 1);
    close(pipefd[1]);
    return 0;
  }
  if (pid < 0) {
    std::cerr << "Error!" << std::endl;
    return -1;
  }
}


3.exec関数によるプロセスの置き換え(replacement of current process)

exec関数で別プロセスを起動すると、自プロセスが別プロセスに置き換えられます。以下の例では、Hello!は標準出力されません。

exec.cpp

#include <iostream>
#include <unistd.h>

auto main() -> int {
  execl("main.exe", "a0", "a1", "a2", NULL);
  std::cout << "Hello!" << std::endl;
}

main.cpp

#include <iostream>

auto main(int argc, char* argv[]) -> int {
  std::cout << argc << std::endl;
  for (int i = 0; i < argc; i++) {
    std::cout << i << ":" << argv[i] << std::endl;
  }
}


4.popen関数による外部プロセスの標準出力取得

popen関数を使うと外部プロセスの標準出力を取得することができます。

popen.cpp

#include <cstdio>
#include <cstdlib>
#include <iostream>

int main() {
  const char* command = "main.exe a0 a1 a2";
  FILE* fp = popen(command, "r");
  if (fp == NULL) return -1;
  char buffer[1024];
  while (fgets(buffer, sizeof(buffer), fp) != NULL) {
    std::cout << buffer;
  }
  pclose(fp);
  return 0;
}

main.cpp

#include <iostream>

auto main(int argc, char* argv[]) -> int {
  std::cout << argc << std::endl;
  for (int i = 0; i < argc; i++) {
    std::cout << i << ":" << argv[i] << std::endl;
  }
}

popen.bat

set PATH=D:\sdk\MinGW\bin
g++ popen.cpp -o popen.exe
g++ main.cpp -o main.exe
popen.exe


参考サイト

1.fork関数
2.プロセスの作成 fork
3.マルチプロセス
4.メモリとプロセスとスレッド編
5.C言語 popen()でコマンドを実行して出力を読み込む
6.system関数とpopen関数を適当に選んではいけない
7.外部プログラムの戻り値を取得するには?
8.Google:C言語 pipe関数
9.クライアント・サーバーとは?(パイプによるプロセス間通信)
10.Man page of PIPE
11.pipe関数

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中