株式会社エスロジカル
株式会社エスロジカル
セキュリティ、Web開発、Unix開発、Go言語

■ UNIX の C言語:forkとexec

技術ドキュメント目次 -> UNIX の C言語 -> forkとexec

本技術ドキュメントは、ここしばらくメンテナンスをしておりません。
内容が古くなっている可能性などございますこと、ご理解を頂けますようお願いいたします。


サイフにやさしいSSL証明書
【低価格SSL証明書】弊社運営の低価格SSL証明書販売サイト、翌月末払いなど請求書払いも可能。


◆ forkとexec

fork() と exec()系関数はを理解することは重要です。
それぞれ次のような動作をします。

fork:   プロセスのコピーを作成。
exec系: プロセスを引数で指定したプロセスに置き換える


◆ たとえば、パフォーマンステストプログラムで、(少々無理矢理な例です)

例えば、負荷テスト・パフォーマンス測定などの目的で、
特定のプログラムを多重に実行させたい時に、
下記のようにコマンドを連打することがるかもしれません。

ただし、そのようにしていると、
オペレーションがすこしめんどくさいですし、
オペミスも発生する可能性が高くなってしまいます。

$ /(PATH)/somecmd arg1 arg2 arg3 &
$ /(PATH)/somecmd arg1 arg2 arg3 &
$ /(PATH)/somecmd arg1 arg2 arg3 &
$ /(PATH)/somecmd arg1 arg2 arg3 &
....


文末の fork.c のようなプログラムを作成し、
コンパイル(gcc -o fork fork.c)し、
下記のように引数を指定して実行することで、
/(PATH)/somecmd arg1 arg2 arg3 コマンドを多重度10で実行できることができます。

オペレーションが楽&正確になるので、
C言語でテストプログラムを作成したときなどに、便利かもしれません。

./fork 10 /(PATH)/somecmd arg1 arg2 arg3


◆ サンプルプログラム解説

fork() は実行中のプロセスが自分自身の分身を作成を作成します。
新たに作成されたプロセス(子)であるか、
もともと存在していたプロセス(親)であるかは、
fork の戻り値で判断することができます。

また、
exec系関数を呼び出すことで、
実行中のプロセスが、引数で指定した別のプロセスに置き換わります。
(exec系関数には複数の種類があるので、manページもよくご参照ください。)

下記のサンプルでは、
fork() して作成した子プロセスが、
exec()系関数を呼び出し、目的のプログラムを実行しています。

※RedHat Linux 7.3 と FreeBSD 5.3 でコンパイルが通ることを確認しました。

/*
 * fork.c
 *
 * Copyright (C) 2006 Slogical Corporation
 */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>

int main (int argc, char **argv) {
        int i;
        int repeat;
        DIR *dir;

        /* 引数のチェック */
        if (argc < 3 || strncmp(argv[1], "-h", 2) == 0) {
                fprintf(stderr, "1st arg is repeat count.\n");
                fprintf(stderr, "2nd arg is target command(start with '/').\n");
                fprintf(stderr, "over 3rd args are args for target command.\n");
                return 1;
        }

        repeat = atoi(argv[1]);
        if (repeat < 1) {
                fprintf(stderr, "1st arg is repeat count.\n");
                fprintf(stderr, "please input numeric(over 1) value.\n");
                return -1;
        }

        if (strncmp(argv[2], "/", 1) != 0) {
                fprintf(stderr, "2nd arg is target command(start with '/').\n");
                fprintf(stderr, "please input a value started with '/'.\n");
                return -1;
        }
        if (access(argv[2], X_OK) != 0) {
                fprintf(stderr, "can not exec %s\n", argv[2]);
                return -1;
        }
        dir = opendir(argv[2]);
        if (dir != NULL) {
                fprintf(stderr, "%s is directory can not execute.\n", argv[2]);
                closedir(dir);
                return -1;
        }

        /* 指定された回数だけ繰り返す */
        for (i=0; i<repeat; i++) {
                /* fork した子プロセスが処理を実行 */
                pid_t pid = fork();
                if (pid == 0) {
                        execvp(argv[2], &argv[2]);
                }
        }

        return 0;
}




■ UNIX の C言語 についての他のドキュメント


■ 他のグループのドキュメント

Apache  /  Linux  /  FreeBSD  /  OpenSSL  /  Perl  /  HTTPプロトコル  /  Jakarta Tomcat  /  Java  /  NetBSD  /  Oracle  /  PostgreSQL  /  UNIX の C言語  /  UNIX のコマンド  /  Windows  /  bind  /  システム運用TIPS

アンケートにご協力をお願いいたします。

1. このドキュメントへの評価をご選択ください。
         

2. ご感想をお書きください。