команды pipe, fork и shell в C - PullRequest
1 голос
/ 15 июля 2011

Я пытаюсь воспроизвести трубы в оболочке. например, ls | Сортировать Сначала я пробую каналы, но не могу заставить родителя прочитать результат того, что выполнил ребенок:

//pipes essai
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/wait.h>
# include <assert.h>
# include <string.h>
# include <sys/stat.h>
# include <fcntl.h>

enum {
MaxLigne = 1024, // longueur max d'une ligne de commandes
MaxMot = MaxLigne / 2, // nbre max de mot dans la ligne
MaxDirs = 100, // nbre max de repertoire dans PATH
MaxPathLength = 512,
 // longueur max d'un nom de fichier
 };

void decouper(char *, char *, char **, int);
int spawn(char * pathname, char * mot[]);

# define PROMPT "? "

int main(int argc, char * argv[]) {
char ligne[MaxLigne];
char pathname[MaxPathLength];
char * mot[MaxMot];
char * dirs[MaxDirs];
int i, tmp, x;
int fd[2];
int t, res = 0;
char buf[1024];
char * mot2[10];

/* Decouper PATH en repertoires */
decouper(getenv("PATH"), ":", dirs, MaxDirs);

/* read the command lines and try to execute them */
for (printf(PROMPT); fgets(ligne, sizeof ligne, stdin) != 0; printf(PROMPT)) {
    decouper(ligne, " \t\n", mot, MaxMot);
    if (mot[0] == 0) // empty line
        continue;

        //launch the pipe
        int p=pipe(fd);
        assert(p>=0);


        tmp = fork(); // launch the pipe process
        if (tmp < 0) {
            perror("fork");
            continue;
        }

        if (tmp != 0) { // parent wait for end of child

            //close this side of the pipe
            close(fd[1]);
            //waiting
            while (wait(0) != tmp)
                ;
            //when finish waiting read what the child has written in the pipe
            read(fd[0], buf, sizeof(buf));
            //print the result
            printf("read %s\n", buf);
            //get back the hand to the user
            continue;

        }else if (tmp==0){

        // child

        //close this side of the pipe
        close(fd[0]);
        //close stdout
        t=close(1);
        //make sur stdout is closed
        assert(t>=0);
        //open the pipe for writing in it instead of in the stdout
        FILE * sortie=fdopen(fd[1], O_WRONLY);
        //make sure it is ok
        assert(sortie!=NULL);

        //try to execute the command
        for (i = 0; dirs[i] != 0; i++) {
            snprintf(pathname, sizeof pathname, "%s/%s", dirs[i], mot[0]);
            execv(pathname, mot);

        }
        }

        // if exec was unsuccessful
        fprintf(stderr, "%s: not found\n", mot[0]);
        exit(1);

}

    printf("Bye\n");
    return 0;

}

void decouper(char * ligne, char * separ, char * mot[], int maxmot){
int i;

mot[0] = strtok(ligne, separ);
for(i = 1; mot[i - 1] != 0; i++){
if (i == maxmot){
  fprintf(stderr, "Erreur dans la fonction decouper: trop de mots\n");
  mot[i - 1] = 0;
 }
 mot[i] = strtok(NULL, separ);
}
}

есть проблема с этой строкой FILE * sortie = fdopen (fd [1], O_WRONLY);

pipe1.c: в функции «main»: pipe1.c: 81: 4: предупреждение: передача аргумента 2 из «fdopen» делает указатель из целого числа без приведения /usr/include/stdio.h:303:14: примечание: ожидается "const char *", но аргумент имеет тип "int"

а как заставить ребенка выводить в трубу ??? freopen тоже не работает

результат, который я получаю: ? Ls читать

что означает, конечно, что ничего не читается. Что я могу сделать, я действительно вне идей сейчас ??? заранее большое спасибо

Ответы [ 2 ]

2 голосов
/ 15 июля 2011

Отдельная проблема ...

Если дочерний элемент записывает много данных в канал, он блокируется, пока родительский элемент не прочитает некоторые из них. Трубы имеют ограниченную пропускную способность (лень мешает мне найти типичный предел).

Ваш родительский код не читает, пока ребенок не выйдет. Но если дочерний элемент блокирует вывод канала, он никогда не завершится. Тупик!

1 голос
/ 15 июля 2011

Вы путаете подпись fdopen с подписью open.fdopen принимает const char* в качестве второго параметра.Попробуйте

FILE * sortie=fdopen(fd[1], "w");

Ссылка:

РЕДАКТИРОВАТЬ : Похоже, что вы используете fdopen без уважительной причины.В частности, я не вижу никакого использования sortie после его инициализации.

Я предполагаю, что вы пытаетесь установить стандарт для программы exec'd.В этом случае вы должны использовать dup или dup2:

close(fd[0]);
close(1);
dup(fd[1]);
close(fd[1]);

//try to execute the command
... as before

Ссылка:

...