C 语言中的管道、叉子和 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); 有问题
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
一个单独的问题...
如果子进程向管道写入大量输出,它将阻塞,直到父进程读取一些输出。管道的容量有限(懒惰使我无法查找典型的限制)。
在子级退出之前,您的父级代码不会执行任何读取操作。但如果子进程阻塞在管道输出上,它就永远不会退出。僵局!
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!
您将
fdopen
的签名与open
的签名混淆了。fdopen
采用const char*
作为其第二个参数。尝试参考:
EDIT: It appears that you are using
fdopen
for no valid reason. Specifically, I don't see any use ofsortie
after it is initialized.我认为您正在尝试为执行程序设置标准输出。如果是这种情况,您应该使用
dup
或dup2
:参考:
You are confusing the signature of
fdopen
with that ofopen
.fdopen
takes aconst char*
as its second parameter. TryReference:
EDIT: It appears that you are using
fdopen
for no valid reason. Specifically, I don't see any use ofsortie
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
ordup2
:Reference: