C中的pipe,fork和shell命令

时间:2011-07-15 19:33:54

标签: c shell exec fork pipe

我正在尝试重现shell中的管道。例如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:警告:传递'fdopen'的参数2使得整数指针没有强制转换 /usr/include/stdio.h:303:14:注意:预期'const char *'但参数类型为'int'

但如何让孩子在管道中输出? freopen也不起作用

我得到的结果: ? LS 阅读

这意味着什么都没有被阅读。我能做什么我现在真的没有想法??? 非常感谢你提前

2 个答案:

答案 0 :(得分:2)

一个单独的问题......

如果孩子将大量输出写入管道,它将阻塞,直到父母读取一些。管道容量有限(懒惰使我无法查看典型限制)。

在孩子退出之前,您的父代码不会进行任何阅读。但如果孩子阻塞管道输出,它将永远不会退出。死锁!

答案 1 :(得分:1)

您将fdopen的签名与open的签名混淆。 fdopenconst char*作为其第二个参数。尝试

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

参考:

<小时/> 编辑:您似乎没有正当理由使用fdopen。具体来说,我没有看到sortie在初始化后使用。

我认为您正在尝试为exec'd程序设置标准输出。如果是这种情况,您应该使用dupdup2

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

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

参考: