2013-07-13 15 views
5

Próbuję zaimplementować wiele rur dla mojej powłoki w C.Kodowanie wielu rur w C

Wszystko, co mam, to funkcja rury, która rura a | b ale nie a | b | do.

int c[2]; 
int returnv; 
pid_t id; 

pipe(c); 
pid = fork()) == 0 
if (pid) 
{ 
    dup2(c[1], 0); 
    close(p[1]); 
    close(p[1]); 
    execvp(array(0), array); 
} 

if ((pid = fork()) == 0) 
{ 
    dup2(p[0], 1); 
    close(p(0)); 
    close(p[0]); 
    returnv = execvp(array[0], array); 
} 

close(p[1]); 
wait(NULL); 
wait(NULL); 
wait(NULL); 
return returnv; 

I to jest druga wersja:

int i = 0; 

while (i < x) 

{ 
pipe(c); 
if ((pid = fork()) == 0) 
{ 
    dup2(t[i], 1); 
    if (i < 2) 
     dup2(p[0], 1); 
    close(p[1]); 
r= execvp(cmd[i][0], cmd[i]); 
} 
    wait(NULL); 
    close(p[0]); 
    i += 1; 
    t[i] = p[1]; 

Jak mogę dodać trochę coś, które uczynią ten kod zarządzać wieloma rura proszę? Bardzo dziękuję z góry!

+0

Właściwie dwa razy wywołujesz fork(), a potrzebujesz tylko raz. To dlatego, że fork() zwraca dwa razy: 0 dla procesu synowskiego i> 1 dla procesu ojca (zwykle jest to pid syna). Nie sądzę, żebyś potrzebował całego kodu do robienia tego, czego potrzebujesz. – none

+0

Spędziłem tyle czasu na tym jednym, to jest jedyna rzecz, która działa^^ Myślę, że jest tylko jedno wywołanie execvp potrzebne dla multi pipe, ale nie mogę sprawić, żeby działało. :( – user2145240

+0

Nie usuwaj kodu z postu, który unieważnia odpowiedzi – FDinoff

Odpowiedz

8

Edit: według Twojego komentarza

Aby wykonać wielokrotności rur trzeba przechowywać wszystkie swoje polecenia gdzieś. Dlatego użyłem zakładki struktury.

Sprawdź to nowa wersja może łatwiej zrozumieć

Więc najpierw trzeba kartę lub coś do przechowywania wszystkich poleceń:

int main() 
{ 
    char *ls[] = {"ls", NULL}; 
    char *grep[] = {"grep", "pipe", NULL}; 
    char *wc[] = {"wc", NULL}; 
    char **cmd[] = {ls, grep, wc, NULL}; 

    loop_pipe(cmd); 
    return (0); 
} 

to funkcja, która będzie przebiegać przez kartę i uruchomić wszystko

void loop_pipe(char ***cmd) 
{ 
    int p[2]; 
    pid_t pid; 
    int fd_in = 0; 

    while (*cmd != NULL) 
    { 
     pipe(p); 
     if ((pid = fork()) == -1) 
     { 
      exit(EXIT_FAILURE); 
     } 
     else if (pid == 0) 
     { 
      dup2(fd_in, 0); //change the input according to the old one 
      if (*(cmd + 1) != NULL) 
      dup2(p[1], 1); 
      close(p[0]); 
      execvp((*cmd)[0], *cmd); 
      exit(EXIT_FAILURE); 
     } 
     else 
     { 
      wait(NULL); 
      close(p[1]); 
      fd_in = p[0]; //save the input for the next command 
      cmd++; 
     } 
    } 
} 
+2

@ user2145240 Zmieniłem moją odpowiedź, stara była nieco niechlujna, ponieważ używałam jej do wielu innych rzeczy;) – Alexis

+1

@ user2145240 czy możesz pokazać, w jaki sposób zadzwoń, ponieważ działam ładnie na moim komputerze, a także na idee http://ideone.com/80e3nd – Alexis

+1

@ user2145240 Kilka rzeczy do sprawdzenia: printf ("9 - On rentre ici?"); proszę nie zapomnieć \ n na końcu, Dodaj perror pod exec, aby upewnić się, że czegoś nie brakuje w env – Alexis

0

Podam roboczą wersję modelu dwuprzewodowego i podpowiedź dla modelu z trzema rurami. Wypróbuj go i sprawdź, czy działa. UWAGA: Jeśli nie weźmiesz odpowiednich plików nagłówkowych, dup2() będzie koszmarem.

#include <stdio.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <sys/types.h> 
#include <sys/stat.h> 

int p[2]; 
int pid; 
int r; 

main() 
{ 
    char *ls_args[] = {"ls", NULL}; 
    char *grep_args[] = {"grep", "pipe", NULL}; 

    pipe(p); 

    pid = fork(); 
    if (pid != 0) { 
      // Parent: Output is to child via pipe[1] 

      // Change stdout to pipe[1] 
      dup2(p[1], 1); 
      close(p[0]); 

      r = execvp("ls", ls_args); 
    } else { 
      // Child: Input is from pipe[0] and output is via stdout. 
      dup2(p[0], 0); 
      close(p[1]); 

      r = execvp("grep", grep_args); 
      close(p[0]); 
    } 

    return r; 
} 

Na B | c, wskazówka jest użycie dwóch rur tzn P1 [2] P2 [2]. Wypróbuj to i daj nam znać, jak to działa.