16

fork()子プロセスに(経由で)ターミナルへのフォアグラウンドアクセスを与えようとしています。

その後fork()、子プロセスで次のコードを実行します。

setpgid(0, 0);

と:

setpgid(child, child);

親プロセス内。

これにより、子に独自のプロセスグループが与えられます。の呼び出しはsetpgid()正しく機能します。

今、私は子供にターミナルへのアクセスを許可したいと思います。

setpgid()電話の後、子供に次のものを追加しました。

if (!tcsetpgrp(STDIN_FILENO, getpid())) {
    perror("tcsetpgrp failed");
}

その後、execv()スポーンするコマンドがあります/usr/bin/nano

ただし、nano起動する代わりに何も起こらず、端末はユーザー入力を期待しているように見えます。

さらに、tcsetpgrp()呼び出し後にコードが実行されないようです。

SIGCONT子プロセスを機能させるには、子プロセスにシグナルを送信する必要があることをどこかで読みました。プロセスが停止した場合、どうすればそれを行うことができますか?親は信号を送信する必要がありますか?

それが解決策である場合、どうすれば信号を送信SIGCONTできますか?

raise(SIGCONT);

また、これが役立つかどうかはわかりませんが、次のコマンドnanoを使用してプログラムを実行すると、コードは正常に機能し、生成されます。

exec ./program

それ以外の:

./program

何か案は?本当にありがとう!

4

3 に答える 3

10

理解した。SIGTTOUシグナルは無視する必要があります。

私は追加することによってそれをしました:

signal(SIGTTOU, SIG_IGN);

tcsetpgrp()電話の前に。

于 2011-03-17T17:03:55.177 に答える
7

男3tcsetpgrpは述べています:

tcsetpgrp()がそのセッションのバックグラウンドプロセスグループのメンバーによって呼び出され、呼び出しプロセスがSIGTTOUをブロックまたは無視していない場合、SIGTTOUシグナルがこのバックグラウンドプロセスグループのすべてのメンバーに送信されます。

子ではなく親プロセスでtcsetpgrp()を呼び出す必要があります。ただし、親プロセスが開始されてバックグラウンドに移動した場合、そのプロセスはSIGTTOUを受け取り、停止します。

于 2011-08-09T18:08:51.370 に答える
3

tcsetpgrp()を呼び出す必要があるのは、子ではなく親です。setpgid()呼び出しの後、子はバックグラウンドプロセスになります。有効なケースは、フォアグラウンドグループがその許可を放棄し、別のバックグラウンドグループをフォアグラウンドにしてそれ自体をバックグラウンドにすることです。バックグラウンドグループのプロセスは、制御端末を取得できません。サンプルコードは次のようになります。

/* perror_act.h */
#ifndef PERROR_ACT_H
#define PERROR_ACT_H

#define PERROR_ACT(rtn, act) do { \
    perror(rtn);\
    act; \
} while (0)

#define PERROR_EXIT1(rtn) PERROR_ACT(rtn, exit(1))
#define PERROR_RETN1(rtn) PERROR_ACT(rtn, return -1)

#endif

/* invnano.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include "perror_act.h"

void sig_chld(int chld)
{
    exit(0);
}

int main(void)
{
    pid_t child;
    int p2c[2];
    struct sigaction sa = {.sa_handler = sig_chld};

    if (sigaction(SIGCHLD, &sa, NULL))
        PERROR_EXIT1("sigaction");
    if (pipe(p2c))
        PERROR_EXIT1("pipe");
    if ((child = fork()) < 0)
        PERROR_EXIT1("fork");
    if (child == 0) {
        char buff;
        size_t nread;
        if (close(p2c[1])) /* We must make sure this fd is closed. The reason is explained in following comments. */
                        PERROR_EXIT1("close");
        if ((nread = read(p2c[0], &buff, 1)) < 0) /* Just to receive a message from parent indicating its work is done. Content is not important.  */
            PERROR_EXIT1("read");
        if (nread == 0) /* When all the write ends of a pipe are closed, a read() to the read end of this pipe will get a return value of 0. We've closed the child's write end so if 0 as returned, we can sure the parent have exited because of error. */
            exit(1);
        close(p2c[0]);
        execlp("nano", "nano", (char *) 0);
        PERROR_EXIT1("execlp");
    } else {
        if (close(p2c[0]))
            PERROR_EXIT1("close");
        if (setpgid(child, child))
            PERROR_EXIT1("setpgid");
        if (tcsetpgrp(STDIN_FILENO, child))
            PERROR_EXIT1("tcsetpgrp");
        if (write(p2c[1], &child, 1) != 1) /* If all the read ends of a pipe are close, a write() to the write end of this pipe will let the calling process receive a SIGPIPE whose default deposition is to terminate. */
            PERROR_EXIT1("write");
        while (1) /* If parent exit here, login shell will see the news and grab the controlling terminal */
            pause();
    }
    return 0;
}
于 2017-01-02T14:03:55.203 に答える