Frage

Ich versuche, ein Fernsteuerungsprogramm für den Omxplayer auf meinem Raspberry Pi zu schreiben

Ich kann omxplayer dazu bringen, in einem untergeordneten Prozess einwandfrei zu laufen, aber es scheint mir nicht möglich zu sein, die Pipes richtig zum Laufen zu bringen, um tatsächlich Befehle an den untergeordneten Prozess zu senden.

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);
    }
}

Als ich mit top getestet und das Programm ausgeführt habe, kann ich die Top-Ausgabe im Terminalfenster sehen und den Befehl q im Fenster sehen, aber es sieht so aus, als ob er an den übergeordneten Prozess und nicht an den untergeordneten Prozess geht.Mache ich mit den Pipes etwas falsch oder ist es nicht möglich, Befehle an den erzeugten untergeordneten Prozess zu senden?

Ich habe versucht, die untergeordnete dup2-Anweisung so zu ändern, dass sie von der Pipe nach stdin kopiert wird

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

Aber dann startet top nicht mit einer fehlgeschlagenen TTY-Get-Nachricht

War es hilfreich?

Lösung

Um mit einem Programm zu interagieren, das erwartet, ein Terminal manipulieren zu können, sollten Sie ein Pseudo-TTY verwenden.Dadurch wird das vermieden failed tty get Fehler.

/*...*/
#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;
}

Beachten Sie, dass forkpty ist kein POSIX, sondern eine Schnittstelle, die auf BSD- und Linux-Varianten von UNIX verfügbar ist.

Sie können ausführen top im Batch-Modus, aber Sie können keinen Befehl zum Beenden verwenden.Du musst es töten.

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;
}

Obwohl die Ausführung im Batch-Modus es Ihnen ermöglichen würde, den Prozess mit einem einfacheren Aufruf zu öffnen (z. B popen wie mux vorschlägt), können Sie es nicht beenden, es sei denn, dieser Aufruf gibt die Prozess-ID des untergeordneten Elements zurück (ohne auszuführen). pkill, oder durchsuchen Sie die Prozesstabelle, um den richtigen untergeordneten Prozess zum Beenden zu finden).

Ich glaube, Sie sind etwas verwirrt über die Verwendung dup2.Die Handbuchseite verwendet die Begriffe oldfd Und newfd, und das bedeutet es oldfd wird werden newfd.Zur Veranschaulichung sehen Sie hier ein einfaches Programm, das stdout und stderr in eine Protokolldatei umleitet, eine Funktion aufruft und anschließend stdout und stderr wiederherstellt.

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;
}

Wie mux betonte, schreibt Ihr Programm an das falsche Ende der Pipe.Der pipe Der Befehl gibt ein unidirektionales Paar von Dateideskriptoren zurück, wohin auch immer geschrieben wird fd_pipe[1] kann daraus nachgelesen werden fd_pipe[0].

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top