4

マルチプロセスの標準出力のリダイレクトに関する問題が発生しています。

プロセス A があると仮定すると、A で fork() を使用すると、プロセス A と B が取得されます。そして、B で fork() を使用すると、最終的にプロセス A、B、および C が取得されます。B と C の両方が別のプログラムを実装しています。 exec()。

ここで、A と B の stdout を 2 つのパイプを使用して C の stdin にリダイレクトしようとしています。

#include<unistd.h>
#include<stdio.h>
#include<sty/types.h>
int main()
{
    int AtoC [2];
    pipe(AtoC);

    int fd1,fd2;
    fd1=fork();
    if(fd1>0)
    {
        /***In process A, I do the following steps: ***/
        close(AtoC[0]);
        dup2(AtoC[1], STDOUT_FILENO);
        /* program running in process A */
    }
    else
    {
        int BtoC [2];
        pipe(BtoC);
        fd2=fork();
        if(fd2>0)
        {
            /***In process B, I do the following steps: ***/
            close(AtoC[1]);
            close(BtoC[0]);
            dup2(BtoC[1], STDOUT_FILENO);
            /*** execute another program in process B using execl(); ***/
        }
        else
        {
            /*** In process C, I do the following steps: ***/
            close(AtoC[1]);
            close(BtoC[1]);
            dup2(AtoC[0],STDIN_FILENO);
            dup2(BtoC[0],STDIN_FILENO);
            /*** execute another different program in process C using execl(); ***/
        }
    }
}

さて、これら2つのステートメントの後:

dup2(AtoC[0],STDIN_FILENO);
dup2(BtoC[0],STDIN_FILENO);

BtoC[0]プロセス C の stdin は、最終的にプロセス B の stdout であるにリダイレクトされます。また、プロセス A の stdout は、プロセス C の stdin に渡されません。

私の質問は、プロセス A と B の両方の stdout を同時にプロセス C の stdin にリダイレクトできる解決策があるかどうかです。

もう 1 つの質問は、プロセス A の stdout も画面に出力したい場合、どうすればよいですか? teeコマンドラインのコマンドを知っています。プロセスAで対応する関数を使用しようとしましたtee(int fd_in, int fd_out, size_t len, unsigned int flags)が、プロセスAの標準出力の出力に失敗しました。

どんな提案でも大歓迎です、ありがとう。

4

4 に答える 4

8

それが良いアイデアかどうかはわかりませんが、完全に実現可能です。重要な観察事項は、必要なパイプは1 つだけであるということです。複数のプロセス (共通の親を持つ) が 1 つのパイプに書き込むことができます。ただし、標準入力として使用できるファイル記述子は 1 つだけです。元のコードでは、パイプの 1 つだけが標準入力として C に接続されていました (他のパイプはまだ接続されていましたが、主な理由は、十分な記述子を閉じていなかったためです)。

  • 経験則: パイプの一方の端をdup2()(またはdup()) を介して標準入力または標準出力に接続する場合は、 によって返される両方のファイル記述子を閉じる必要がありますpipe()

サイズについては、このコードを試してください。ツリーの茂みを減らし、未使用の変数を削除し ( によって返されるプロセス ID を使用するものは何もありませんfork())、パイプの名前を変更し、各プロセスでパイプが適切に閉じられていることを確認し、プロセス A と B でいくつかの書き込みアクティビティといくつかの読み取りを提供しました。コマンドを実行する代わりに、プロセス C でアクティビティを実行します。usleep()(マイクロスリープ、マイクロ秒で表されるスリープ時間)が利用可能であると想定しています。そうでない場合は、 を試しnanosleep()てください。ただし、より複雑なインターフェイスがあります)。

#include <unistd.h>

int main(void)
{
    int ABtoC[2];
    pipe(ABtoC);

    if (fork() > 0)
    {
        // Process A
        close(ABtoC[0]);
        dup2(ABtoC[1], STDOUT_FILENO);
        close(ABtoC[1]);     // Close this too!
        // Process A writing to C
        for (int i = 0; i < 100; i++)
        {
            write(STDOUT_FILENO, "Hi\n", sizeof("Hi\n")-1);
            usleep(5000);
        }
    }
    else if (fork() > 0)
    {
        // Process B
        close(ABtoC[0]);
        dup2(ABtoC[1], STDOUT_FILENO);
        close(ABtoC[1]);
        // Process B writing to C
        for (int i = 0; i < 100; i++)
        {
            write(STDOUT_FILENO, "Lo\n", sizeof("Lo\n")-1);
            usleep(5000);
        }
    }
    else
    {
        char buffer[100];
        ssize_t nbytes;
        close(ABtoC[1]);
        dup2(ABtoC[0], STDIN_FILENO);
        close(ABtoC[0]);
        // Process C reading from both A and B
        while ((nbytes = read(STDIN_FILENO, buffer, sizeof(buffer))) > 0)
            write(STDOUT_FILENO, buffer, nbytes);
    }
    return(0);
}

私の Mac (Mac OS X 10.7.5、GCC 4.7.1) での実行の最後には、次のものが生成されました。

Lo
Hi
Lo
Hi
Lo
Hi
Lo
Hi
Lo
Hi
Hi
Lo
Lo
Hi
Hi
Lo
Hi
Lo
Hi
Lo
Hi
Lo
Hi
Lo
Lo
Hi
于 2012-10-24T04:29:59.313 に答える
1

パイプ共有のフォローアップとして、is-it-safe-to-pipe-the-output-of-several-parallel-processesをチェックアウトすることをお勧めします。小さな書き込みでは問題なく動作しますが、大きな書き込みではデータがインターリーブされる可能性があります =)

于 2013-01-12T13:29:52.967 に答える
-1

2 つの出力パイプの端を 1 つの入力パイプの端にリダイレクトする方法。

私もそれがどのように機能するのかわかりません.opへの他の回答を待ちます. epollただし、代わりに、のような非同期 I/O を使用できます。プロセス A は、プロセス B/C の出力をブロックする必要はありません。プロセス データが利用可能になったときに読み取られます。

プロセス A の stdout を何も出力できませんでした。

このmanページには、tee参照用に の使用方法の良い例があります。

于 2012-10-24T01:06:29.233 に答える
-1

それは不可能。パイプに関する全体的な考え方は、パイプには 2 つの端があるということです。1 つはプロセス A などに接続され、もう 1 つは別のプロセス (C など) に属しています。他のプロセスが別のパイプを作成する場合は、2 つの端も必要です2 つの端が 1 つの穴で終わることはありません。

あなたがこれをしたとき:

dup2(AtoC[0],STDIN_FILENO);
dup2(BtoC[0],STDIN_FILENO);

2行目は最初の行を効果的に上書きしました。dup2(oldfd, newfd) は、newfd を閉じて、効果的に oldfd と同じにすることになっています。つまり、最初の行はプラグを差し込んでいますが、2 行目はプラグを抜いて別のものを差し込んでいます。

于 2012-10-24T03:58:55.790 に答える