简体   繁体   English

C 中的 pipe、fork 和 shell 命令

[英]pipe, fork and shell commands in C

I am trying to reproduce the pipes in a shell.我正在尝试重现 shell 中的管道。 for example ls |例如 ls | sort At first I am trying the pipes but I can't get the parent to read the result of what the child has executed:排序起初我正在尝试管道,但我无法让父级读取子级执行的结果:

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

there is a problem with this line FILE * sortie=fdopen(fd[1], O_WRONLY);这行 FILE * sortie=fdopen(fd[1], O_WRONLY); 有问题

pipe1.c: In function 'main': pipe1.c:81:4: warning: passing argument 2 of 'fdopen' makes pointer from integer without a cast /usr/include/stdio.h:303:14: note: expected 'const char *' but argument is of type 'int' pipe1.c: In function 'main': pipe1.c:81:4: warning: passing argument 2 of 'fdopen' makes pointer from integer without a cast /usr/include/stdio.h:303:14: note: expected 'const char *' 但参数的类型为 'int'

but how can I make the child to output in the pipe???但是我怎样才能让孩子在 pipe 中成为 output ??? freopen doesn't work either freopen 也不起作用

the result I get: ?我得到的结果:? ls read我读

which means of course nothing is read.这当然意味着什么都没有被读取。 What can I do I am really out of ideas now???我该怎么办我现在真的没有想法??? thank you very much in advance非常感谢你

A separate problem...一个单独的问题...

If the child writes a lot of output to the pipe, it'll block until the parent reads some.如果孩子将大量 output 写入 pipe,它将阻塞,直到父母读取一些。 Pipes have limited capacity (laziness prevents me from looking up typical limit).管道的容量有限(懒惰使我无法查找典型的限制)。

Your parent code doesn't do any reading until the child exits.在孩子退出之前,您的父代码不会进行任何读取。 But if the child blocks on pipe output, it'll never exit.但是如果孩子在 pipe output 上阻塞,它永远不会退出。 Deadlock!僵局!

You are confusing the signature of fdopen with that of open .您将fdopen的签名与open的签名混淆了。 fdopen takes a const char* as its second parameter. fdopenconst char*作为其第二个参数。 Try尝试

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

Reference:参考:


EDIT : It appears that you are using fdopen for no valid reason. 编辑:您似乎没有正当理由使用fdopen Specifically, I don't see any use of sortie after it is initialized. 具体来说,初始化后我看不到任何使用sortie

I presume that you are trying to set up standard out for the exec'd program.我假设您正在尝试为 exec'd 程序设置标准。 If that is the case, you should use dup or dup2 :如果是这种情况,您应该使用dupdup2

 close(fd[0]); close(1); dup(fd[1]); close(fd[1]); //try to execute the command... as before

Reference:参考:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM