o envio de comandos para uma criança de processo através de tubulação/dup2 em C

StackOverflow https://stackoverflow.com//questions/11689421

  •  12-12-2019
  •  | 
  •  

Pergunta

Eu estou tentando escrever um programa de controle remoto para omxplayer no meu rasperry Pi

Eu posso obter omxplayer para executar ok em um processo filho, mas eu não parecem ser capazes de obter os tubos funcionando corretamente, na verdade, enviar comandos para o processo filho.

int fd_pipe[2];
pipe (fd_pipe);

while(1) {  // main accept() loop

    printf("server: got connection from %s\n", s);

    /* Attempt to fork and check for errors */
    if( (pid=fork()) == -1){
        fprintf(stderr,"Fork error. Exiting.\n");  /* something went wrong */
        exit(1);
    }

    if (pid==0) 
    { // this is the child process
        dup2(0, fd_pipe[0]);
        close(fd_pipe[1]);


        if(execl("/usr/bin/top","top",NULL) == -1){
            fprintf(stderr,"execl Error!");
            exit(1);
        }

        //try and send command here
        write(fd_pipe[0], "q", 1);

        exit(0);

    } else {

        close(new_fd);  // parent doesn't need this
        dup2(1, fd_pipe[1]);

        //try and send here too
        write(fd_pipe[0], "q", 1);
    }
}

Quando eu estava testando com a parte superior e executou o programa, eu posso ver os resultados aparecem na janela de terminal e eu posso ver o q comando na janela, mas parece que vai para o processo principal, em vez de a criança.Estou fazendo algo de errado com canos ou não é possível enviar comandos para a expansão do processo filho?

Eu tentei mudar a criança dup2 instrução copiar a partir do tubo de entrada

        { // this is the child process
        dup2(fd_pipe[0], 0);

Mas, em seguida, de cima falha ao iniciar com uma falha de tty obter mensagem

Foi útil?

Solução

Para interagir com um programa que espera ser capaz de manipular um terminal, você deve usar uma pseudo-tty.Isso vai evitar a failed tty get erro.

/*...*/
#include <pty.h>

void do_child () {
    if (execlp("top", "top", (const char *)0) < 0) {
        perror("exec top");
        exit(EXIT_FAILURE);
    }
    /* NOTREACHED */
}

void do_parent (int fd, pid_t p) {
    sleep(5);
    char r;
    write(fd, "q", 1);
    while (read(fd, &r, 1) > 0) { write(1, &r, 1); }
    waitpid(p, 0, 0);
    close(fd);
}

int main () {
    int fd;
    pid_t p = forkpty(&fd, 0, 0, 0);
    switch (p) {
    case 0:  do_child();
             /* NOTREACHED */
    case -1: perror("forkpty");
             exit(EXIT_FAILURE);
    default: break;
    }
    do_parent(fd, p);
    return 0;
}

Note que forkpty não é POSIX, mas uma interface que está disponível no BSD e Linux sabores de UNIX.

Você pode executar top em um lote, mas você não pode usar um comando para sair.Você tem que matá-lo.

void do_child () {
    if (execlp("top", "top", "-b", (const char *)0) < 0) {
        perror("exec top");
        exit(EXIT_FAILURE);
    }
    /* NOT REACHED */
}

void do_parent (pid_t p) {
    sleep(5);
    if (kill(p, SIGINT) < 0) {
        perror("kill");
        exit(EXIT_FAILURE);
    }
    waitpid(p, 0, 0);
}

int main () {
    pid_t p;
    switch ((p = fork())) {
    case 0:  do_child();
    case -1: perror("fork"); exit(EXIT_FAILURE);
    default: break;
    }
    do_parent(p);
    return 0;
}

Embora a execução em modo batch permite que você abrir o processo com uma simples chamada (como popen como mux sugere), a menos que a chamada retorna o id do processo da criança, você não será capaz de matá-lo (sem executar uma pkill, ou cavar através do processo tabela para localizar a criança em processo de matar).

Eu acho que você tem alguma confusão sobre como utilizar dup2.A página de manual utiliza os termos oldfd e newfd, e isso significa que oldfd vai se tornar newfd.Para ilustrar, aqui é um programa simples que redireciona stdout e stderr para um arquivo de log, chama uma função e, em seguida, restaura o stdout e stderr depois.

void do_something () {
    fputs("Error message\n", stderr);
    puts("This is regular output.");
    fputs("Error message\n", stderr);
    puts("This is regular output.");
}

int main () {
    int fd = creat("/tmp/output.log", 0664);
    int outfd = dup(fileno(stdout));
    int errfd = dup(fileno(stderr));
    fflush(stdout);
    fflush(stderr);
    dup2(fd, fileno(stdout));
    dup2(fd, fileno(stderr));
    setlinebuf(stdout);

    do_something();

    fflush(stdout);
    fflush(stderr);
    dup2(outfd, fileno(stdout));
    dup2(errfd, fileno(stderr));
    close(outfd);
    close(errfd);

    fputs("Error to the screen\n", stderr);
    puts("Regular output to screen");
    fputs("Error to the screen\n", stderr);
    puts("Regular output to screen");

    return 0;
}

Como mux apontou, o programa está a escrever errado extremidade do tubo.O pipe o comando retorna uma unidireccional par de descritores de arquivo, onde o que já está escrito fd_pipe[1] pode ser lida a partir de fd_pipe[0].

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top