C 语言中的管道、叉子和 shell 命令

发布于 2024-11-24 09:09:47 字数 3219 浏览 2 评论 0原文

我正在尝试在外壳中重现管道。例如 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); 有问题

pipeline1.c:在函数“main”中: pipeline1.c:81:4:警告:传递“fdopen”的参数 2 使指针来自整数而不进行强制转换 /usr/include/stdio.h:303:14:注意:预期为“const char *”,但参数的类型为“int”,

但如何使子项在管道中输出??? freopen 不起作用,

我得到的结果是: ? LS read

这当然意味着什么也没读。我该怎么办我现在真的没有想法了??? 预先非常感谢

I am trying to reproduce the pipes in a shell. for example 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);

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’

but how can I make the child to output in the pipe??? freopen doesn't work either

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不必在意 2024-12-01 09:09:47

一个单独的问题...

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

在子级退出之前,您的父级代码不会执行任何读取操作。但如果子进程阻塞在管道输出上,它就永远不会退出。僵局!

A separate problem...

If the child writes a lot of output to the pipe, it'll block until the parent reads some. 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. Deadlock!

懒猫 2024-12-01 09:09:47

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

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

参考:


EDIT: It appears that you are using fdopen for no valid reason. Specifically, I don't see any use of sortie after it is initialized.

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

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

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

参考:

You are confusing the signature of fdopen with that of open.
fdopen takes a const char* as its second parameter. Try

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

Reference:


EDIT: It appears that you are using fdopen for no valid reason. Specifically, I don't see any use of sortie after it is initialized.

I presume that you are trying to set up standard out for the exec'd program. If that is the case, you should use dup or dup2:

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

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

Reference:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文