[英]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. fdopen
将const char*
作为其第二个参数。 Try尝试
FILE * sortie=fdopen(fd[1], "w");
Reference:参考:
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
:如果是这种情况,您应该使用dup
或dup2
:
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.