web-dev-qa-db-ja.com

popenで開始されたプロセスを強制終了します

popenでプロセスへのパイプを開いた後、開始されたプロセスを強制終了する方法はありますか? (pcloseを使用すると、プロセスが終了するのを待つため、私は望んでいませんが、それを強制終了する必要があります。)

23
Sophie Alpert

popen()を使用せず、必要なことを実行する独自のラッパーを作成します。

fork()に移動し、dup2()を使用してstdinstdoutを置き換え、次にexec()を呼び出すのはかなり簡単です。子。

そうすれば、親は正確な子PIDを持ち、その上でkill()を使用できます。

popen()が実行していることを実装する方法に関するサンプルコードについては、Googleで「popen2()の実装」を検索してください。たった十数行の長さです。 dzone.com から取得:次のような例を見ることができます:

#define READ 0
#define WRITE 1

pid_t
popen2(const char *command, int *infp, int *outfp)
{
    int p_stdin[2], p_stdout[2];
    pid_t pid;

    if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0)
        return -1;

    pid = fork();

    if (pid < 0)
        return pid;
    else if (pid == 0)
    {
        close(p_stdin[WRITE]);
        dup2(p_stdin[READ], READ);
        close(p_stdout[READ]);
        dup2(p_stdout[WRITE], WRITE);

        execl("/bin/sh", "sh", "-c", command, NULL);
        perror("execl");
        exit(1);
    }

    if (infp == NULL)
        close(p_stdin[WRITE]);
    else
        *infp = p_stdin[WRITE];

    if (outfp == NULL)
        close(p_stdout[READ]);
    else
        *outfp = p_stdout[READ];

    return pid;
}

注意:popen2()が必要なようですが、私のディストリビューションにはこのメソッドが付属していないようです。

27
slacy

これはpopen2の改良版です(クレジットはSergey Lによるものです)。 slacyによって投稿されたバージョンは、popen2で作成されたプロセスのPIDを返しませんが、shに割り当てられたPIDを返します。

pid_t popen2(const char **command, int *infp, int *outfp)
{
    int p_stdin[2], p_stdout[2];
    pid_t pid;

    if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0)
        return -1;

    pid = fork();

    if (pid < 0)
        return pid;
    else if (pid == 0)
    {
        close(p_stdin[WRITE]);
        dup2(p_stdin[READ], READ);
        close(p_stdout[READ]);
        dup2(p_stdout[WRITE], WRITE);

        execvp(*command, command);
        perror("execvp");
        exit(1);
    }

    if (infp == NULL)
        close(p_stdin[WRITE]);
    else
        *infp = p_stdin[WRITE];

    if (outfp == NULL)
        close(p_stdout[READ]);
    else
        *outfp = p_stdout[READ];

    return pid;
}

新しいバージョンはで呼び出されます

char *command[] = {"program", "arg1", "arg2", ..., NULL};
5
chessweb

popenは実際にはスレッドを開始しませんが、プロセスをフォークします。定義を見ると、そのプロセスのPIDを取得して強制終了する簡単な方法があるようには見えません。プロセスツリーを調べるなどの難しい方法もあるかもしれませんが、パイプ、フォーク、およびexec関数を使用してpopenの動作を模倣する方がよいと思います。次に、fork()から取得したPIDを使用して、子プロセスを強制終了できます。

4
che

実際、プロセスがI/Oを実行している場合(そうでない場合は、なぜpopen(3)の代わりにsystem?)、次にpcloseは、次に読み取りまたは書き込みを試みたときにSIGPIPEでそれを叩き、フォールオーバーする必要がありますうまく:-)

3
Norman Ramsey

関数popen2を作成する@slacyのアイデアに従いました。
しかし、子プロセスが終了すると問題が見つかりました。ファイル記述子outfpをまだ読み取っている親プロセスが関数から戻りません。

これは、親プロセスに未使用のクローズパイプを追加することで修正できます。

close(p_stdin[READ]);
close(p_stdout[WRITE]);

シェルとしてbashを使用することで、新しいプロセスの正しいpidを取得できます。

execl("/bin/bash", "bash", "-c", command, NULL);

子プロセスが死ぬと、関数の呼び出し元popen2呼び出しによって子プロセスのステータスを収集する必要がありますpclose2。そのステータスを収集しない場合、子プロセスは終了時にゾンビプロセスになる可能性があります。

これは、テストされ、期待どおりに機能する完全なコードです。

#define READ 0
#define WRITE 1

pid_t
popen2(const char *command, int *infp, int *outfp)
{
    int p_stdin[2], p_stdout[2];
    pid_t pid;

    if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0)
        return -1;

    pid = fork();

    if (pid < 0)
        return pid;
    else if (pid == 0)
    {
        dup2(p_stdin[READ], STDIN_FILENO);
        dup2(p_stdout[WRITE], STDOUT_FILENO);

     //close unuse descriptors on child process.
     close(p_stdin[READ]);
     close(p_stdin[WRITE]);
     close(p_stdout[READ]);
     close(p_stdout[WRITE]);

        //can change to any exec* function family.
        execl("/bin/bash", "bash", "-c", command, NULL);
        perror("execl");
        exit(1);
    }

    // close unused descriptors on parent process.
    close(p_stdin[READ]);
    close(p_stdout[WRITE]);

    if (infp == NULL)
        close(p_stdin[WRITE]);
    else
        *infp = p_stdin[WRITE];

    if (outfp == NULL)
        close(p_stdout[READ]);
    else
        *outfp = p_stdout[READ];

    return pid;
}

int
pclose2(pid_t pid) {
    int internal_stat;
    waitpid(pid, &internal_stat, 0);
    return WEXITSTATUS(internal_stat);
}
1
unbound

最初の行に(bash)スクリプトを入力するだけです。

echo PID $$

次に、pidを読み取り、それを使用して:kill(pid、9)を実行します。

0
user2729676

私はPythonで同様のことをしました。そこでは、サブプロセスとそのためにフォークされたサブプロセスを強制終了できます。それは実際にはslacyのソリューションに似ています。 http://www.pixelbeat.org/libs/subProcess.py

0
pixelbeat

明らかな方法はsystem( "pkill process_name");です。

プロセスの複数のインスタンスが実行されている場合、これは明らかに問題があります。

0
Andrew Grant