2

リモートマシンでシェルコマンドを実行できるようにするモジュールを含むLinux上のCでプログラムを書いています。コマンドを実際に実行する最も簡単な方法は、もちろん、system() 関数を使用するか、popen を使用して出力を取得することです。ただし、現在の問題に関連しない他の設計要件のため、より低レベルのアプローチを使用することにしました。

基本的には、パイプとフォークをセットアップしてから、execl を呼び出します。厄介な例外を除いて、これはすべて完全に機能します。実行するシェルコマンドがデーモンの場合、正しく動作しません。その場合、ハングするだけです。理由がわかりません。私の理解では、デーモンが起動すると、通常はフォークしてから親が終了します。私のアプリケーションには親へのパイプが開いているため、親が終了すると read() の呼び出しは失敗するはずです。しかし、代わりにアプリケーションがハングします。

問題を再現する必要最小限のコードを次に示します。


int main(int argc, char** argv)
{
        // Create a pipe and fork
        //
        int fd[2];
        int p = pipe(fd);
        pid_t pid = fork();

    if (pid > 0)
    {
            // Read from the pipe and output the result
            //
            close(fd[1]);
            char buf[1024] = { 0 };
            read(fd[0], buf, sizeof(buf));
            printf("%s\n", buf);

            // Wait for child to terminate
            int status;
            wait(&status);
    }
    else if (pid == 0)
    {
            // Redirect stdout and stderr to the pipe and execute the shell
            // command
            //
            dup2(fd[1], STDOUT_FILENO);
            dup2(fd[1], STDERR_FILENO);
            close(fd[0]);
            execl("/bin/sh", "sh", "-c", argv[1], 0);
    }

}

通常のシェルコマンドで使用すると、コードは正常に機能します。しかし、デーモンを実行しようとすると、本来のプロンプトに戻るのではなく、ハングするだけです。

4

4 に答える 4

0

パイプのもう一方の端が閉じられているため、読み取りが完了するのを待っているときに SIGPIPE シグナルを受信する必要があると思います。信号に異常はありませんでしたか? コードを strace コマンドで実行することをお勧めします。

于 2009-04-29T06:49:37.460 に答える
0

子プロセスはデーモンであるため、すぐに終了することはありません。

本気ですか?もちろん、デーモンがすぐには終了しないことに同意しますが、デーモンが起動するとフォークして、子が端末との関連付けを解除できるようになり、親が終了します。wait() システム コールは親デーモン プロセスで待機しているため、終了する必要があります。

それでも、wait() を呼び出さなくても同じ問題が発生します。

また、read() が EOF にならないのはなぜですか? read() は、親デーモン プロセスに接続されているオープン パイプから読み取ります。そのため、親デーモン プロセスが終了すると、read() は EOF ですぐに戻る必要があります。

于 2009-04-29T03:52:20.430 に答える