26

割り当てを完了するには、 fork()and関数を使用する必要があります。wait()非決定論的な動作をモデル化しており、fork()可能な遷移が複数ある場合はプログラムが必要です。

forkどのようにそしてどのように機能するかを試してみるためにwait、私は単純なプログラムを作成しました。親プロセスが単一の子プロセスの終了ステータスを使用して子プロセスが受け入れ状態に到達したかどうかを判断できるため、プログラムが1回だけ分岐した場合は、呼び出しがどのように機能するかを理解できたと思います。

ただし、次のコードからわかるように、複数の子プロセスが必要な状況を処理できるようにしたいと思います。私の問題は、_exit関数を使用してステータスを設定できるのは1回だけのように見えることです。したがって、私の例のように、親プロセスがテストする終了ステータスは、最初の子プロセスが終了ステータスとして0を発行したことを示していますが、2番目の子プロセスに関する情報はありません。

私は単に_exit()拒否を行わないようにしましたが、その子プロセスは続行され、事実上、2つの親プロセスがあるように見えます。

ワッフルについては申し訳ありませんが、親プロセスが複数の子プロセスのステータス情報を取得する方法を誰かに教えてもらえれば幸いです。または、親プロセスが子プロセスからのステータスの受け入れのみに気付くことができれば幸いです。しかし、その場合、拒否ステータスを持つ子プロセスを正常に終了する必要があります。

私のテストコードは次のとおりです。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>

int main(void)  {

    pid_t child_pid, wpid, pid;
    int status = 0;
    int i;

    int a[3] = {1, 2, 1};
    for(i = 1; i < 3; i++)  {
        printf("i = %d\n", i);
        pid = getpid();
        printf("pid after i = %d\n", pid);
        if((child_pid = fork()) == 0)  {
            printf("In child process\n");
            pid = getpid();
            printf("pid in child process is %d\n", pid);
            /* Is a child process */
            if(a[i] < 2)  {
                printf("Should be accept\n");
                _exit(1);
            } else  {
                printf("Should be reject\n");
                _exit(0);
            }
        }
    }

    if(child_pid > 0)  {
        /* Is the parent process */
        pid = getpid();
        printf("parent_pid = %d\n", pid);
        wpid = wait(&status);
        if(wpid != -1)  {
            printf("Child's exit status was %d\n", status);
            if(status > 0)  {
                printf("Accept\n");
            } else  {
                printf("Complete parent process\n");
                if(a[0] < 2)  {
                    printf("Accept\n");
                } else  {
                    printf("Reject\n");
                }
            }
        }
    }
    return 0;
}
4

3 に答える 3

37

wait()基本的な問題は、子がなくなるまで待機するループではなく、1つの呼び出しがあることであるように私には見えます。fork()また、少なくとも1つが成功した場合ではなく、最後が成功した場合にのみ待機fork()します。

_exit()を含む開いているファイルストリームをフラッシュするなど、通常のクリーンアップ操作が必要ない場合にのみ使用してくださいstdout。使用する機会があります_exit(); これはそれらの1つではありません。(この例では、もちろん、exit()直接呼び出すのではなく、単に子を返すようにすることもできます。これは、から戻ることmain()は、返されたステータスで終了することと同じであるためです。ただし、ほとんどの場合、他の関数でフォークなどを実行します。よりmain()、そしてそれからexit()しばしば適切です。)


私が望む診断を提供する、ハッキングされた単純化されたバージョンのコード。ループが配列の最初の要素をスキップしたことに注意してくださいfor(私の場合はスキップしません)。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

int main(void)
{
    pid_t child_pid, wpid;
    int status = 0;
    int i;
    int a[3] = {1, 2, 1};

    printf("parent_pid = %d\n", getpid());
    for (i = 0; i < 3; i++)
    {
        printf("i = %d\n", i);
        if ((child_pid = fork()) == 0)
        {
            printf("In child process (pid = %d)\n", getpid());
            if (a[i] < 2)
            {
                printf("Should be accept\n");
                exit(1);
            }
            else
            {
                printf("Should be reject\n");
                exit(0);
            }
            /*NOTREACHED*/
        }
    }

    while ((wpid = wait(&status)) > 0)
    {
        printf("Exit status of %d was %d (%s)\n", (int)wpid, status,
               (status > 0) ? "accept" : "reject");
    }
    return 0;
}

出力例(MacOS X 10.6.3):

parent_pid = 15820
i = 0
i = 1
In child process (pid = 15821)
Should be accept
i = 2
In child process (pid = 15822)
Should be reject
In child process (pid = 15823)
Should be accept
Exit status of 15823 was 256 (accept)
Exit status of 15822 was 0 (reject)
Exit status of 15821 was 256 (accept)
于 2010-04-25T14:20:21.513 に答える
9

wait()関数をループに入れて、すべての子プロセスを待ちます。使用可能な子プロセスがなくなると、待機関数は-1を返し、errnoはECHILDと等しくなります。

于 2010-04-25T14:19:35.823 に答える
1

素晴らしい例 Jonathan Leffler さん、コードを SLES で動作させるには、pid_t オブジェクトを許可するヘッダーを追加する必要がありました :)

#include <sys/types.h>
于 2013-02-04T14:11:56.513 に答える