execl() を使い始めた «sh» はゾンビになります

execl() を使い始めた «sh» はゾンビになります

半日を過ごしましたが、execl通話で始まったダッシュがなぜゾンビに変わったのかはまだわかりませんでした。

以下は最小限のテストケースです。私は子をフォークしてstdをコピーします。[入力、出力、エラー]記述子と開始シェン

#include <cstdio>
#include <fcntl.h>
#include <cstring>
#include <stdlib.h>
#include <cerrno>
#include <unistd.h>

int main() {
    int pipefd[2];
    enum {
        STDOUT_TERM = 0,
        STDIN_TERM  = 1
    };
    if (pipe(pipefd) == -1) { //make a pipe
        perror("pipe");
        return 0;
    }
    pid_t pid = fork();
    if (pid == 0)
    {// Child
        dup2(pipefd[STDIN_TERM], STDIN_FILENO);
        dup2(pipefd[STDOUT_TERM], STDOUT_FILENO);
        dup2(pipefd[STDOUT_TERM], STDERR_FILENO);
        execl("/bin/sh","sh", (char*)NULL);
        // Nothing below this line should be executed by child process. If so, print err
        perror("For creating a shell process");
        exit(1);
    }
    __asm("int3");
    puts("Child launched");
}

デバッガでブレークポイントがある行から始めるとき(電話異常puts()それを見てください(これPID変数を使用してpsを使用してそのプロセスを表示すると、次のような結果が毎回表示されます。

2794 pts/10   00:00:00 sh <defunct>

つまり、ゾンビ

ベストアンサー1

waitあなたは子プロセスにいないので些細なことですが、ゾンビを残しています。

無意味な方法でSTDINを設定したので、シェルはすぐに終了します。pipe一方向通信チャネルを返します。到着するwriteとからpipefd[1]戻ります。シェルがパイプ(STDIN)の書き込み側で読み取ろうとする一連の呼び出しを実行します。readpipefd[0]dup2

列挙型の数字を変更すると、シェルが永久に停止しますread。これはおそらくあなたが望むものではないかもしれませんが、パイプを通してシェルがそれ自体に接続されているときに期待できるすべてです。

親プロセスでシェルを使用したいと仮定すると、それを2回呼び出す必要がありますpipe(親プロセスの両方)。ユーザーが書き込むパイプの1つ(シェルはstdinから読み取る)と、シェルが書き込む他のパイプ(stdout / stderr)とそれを読みます。または必要に応じてsocketpair

おすすめ記事