我正在尝试创建一个shell,其中我需要实现流水线操作.. 管道工作正常,直到所有命令都正确,否则它会阻塞或进入无限循环(当最后一个cmd错误时)..这是我的管道功能.... 代码说明: - 我在命令中声明的备用管道使用两个管道。初始化管道中的pipe1(fd1),当找到第二个管道时,声明另一个管道(fd2)。当发现第三个管道时,管道1(fd1)被重新声明,当找到第四个管道时,管道(fd2)被重新声明,只要找到新管道就行了。
按功能接收的num是由管道分隔的命令数(实际为数字-1)。
在循环内部,我将命令划分为五个条件
继承我的代码:
void call_piping(int num){
int i,fd1[2],fd2[2],status;
pid_t pid;
//pipe(fd1);
//pipe(fd2);
for(i=0;i<=num;i++){
//printf("HH\n");
if(i%2==0){
if(pipe(fd1)==-1){
printf("Error creating pipe fd1\n");
return;
}
}
else{
if(pipe(fd2)==-1){
printf("Error creating pipe fd2\n");
return;
}
}
/*else{
close(fd1[1]);
}*/
if(i==0){
pid=fork();
if(pid==0){
close(fd1[0]);
close(1);
dup2(fd1[1],1);
if((execvp(argv[i][0],argv[i]))==-1){
printf("%s: Invalid command or Command not found\n",argv[i][0]);
close(fd1[1]);
return;
}
}
else{
waitpid(pid,&status,0);
close(fd1[1]);
//printf("Hello1");
}
}
else if(i%2==0 && i==num){
pid=fork();
if(pid==0){
close(0);
//close(1);
dup2(fd2[0],0);
if((execvp(argv[i][0],argv[i]))==-1){
printf("%s: Invalid command or Command not found\n",argv[i][0]);
close(fd2[0]);
return;
}
}
else{
waitpid(pid,&status,0);
//printf("Hello");
close(fd2[0]);
}
}
else if(i%2==0 && i!=num){
pid=fork();
if(pid==0){
close(0);
close(1);
dup2(fd2[0],0);
dup2(fd1[1],1);
if((execvp(argv[i][0],argv[i]))==-1){
printf("%s: Invalid command or Command not found\n",argv[i][0]);
close(fd1[1]);
//printf("Hell");
close(fd2[0]);
return;
}
}
else{
waitpid(pid,&status,0);
close(fd1[1]);
//printf("Hell");
close(fd2[0]);
}
}
else if(i%2!=0 && i==num){
pid=fork();
if(pid==0){
close(0);
dup2(fd1[0],0);
if((execvp(argv[i][0],argv[i]))==-1){
printf("%s: Invalid command or Command not found\n",argv[i][0]);
close(fd1[0]);
return;
}
}
else{
waitpid(pid,&status,0);
//printf("Hel");
close(fd1[0]);
}
}
else if(i%2!=0 && i!=num){
pid=fork();
if(pid==0){
close(0);
close(1);
dup2(fd1[0],0);
dup2(fd2[1],1);
if((execvp(argv[i][0],argv[i]))==-1){
printf("%s: Invalid command or Command not found\n",argv[i][0]);
close(fd2[1]);
close(fd1[0]);
return;
}
}
else{
waitpid(pid,&status,0);
//printf("He");
close(fd2[1]);
close(fd1[0]);
}
}
}
}
所以基本上它是错误处理我遇到问题...我认为是一个解决方案,所有后代进程创建但不知道该怎么做....
答案 0 :(得分:0)
这是if
陈述的极其复杂的老鼠窝。我当然不理解所有的代码;我甚至没有尝试过全部阅读。但是,我不认为你足够快地关闭足够的文件描述符。
例如,最后,您有:
else{
waitpid(pid,&status,0);
//printf("He");
close(fd2[1]);
close(fd1[0]);
}
诊断打印最后应该总是有换行符;否则,你不会及时看到输出。两个close()
来电应该在waitpid()
之前;在管道上等待EOF的进程如果父进程仍然打开进行写入,则不会获得EOF。
在代码的早期,你有:
if(pid==0){
close(fd1[0]);
close(1);
dup2(fd1[1],1);
if((execvp(argv[i][0],argv[i]))==-1){
printf("%s: Invalid command or Command not found\n",argv[i][0]);
close(fd1[1]);
return;
}
}
根据经验,如果使用dup2()
将管道文件描述符与标准输入或标准输出相关联,则应关闭该进程中管道文件描述符的两个 。在执行close(1)
之前,您也无需执行dup(fd[1], 1)
- dup2()
无论如何都会关闭目标文件描述符。
您应该报告标准错误的错误,而不是标准输出。这个名字应该是不言自明的。
您不需要测试execvp()
的返回值;除非失败,否则该函数不会返回,因此测试是多余的。退出失败的exec*()
呼叫而不是返回通常也是一个好主意。如果exec*()
失败并且代码返回,那么您将有两个进程竞争标准输入;这永远不会带来幸福。
第二个片段可能是这样编写的(除了其他更改之外,我还添加了一些空间以提高可读性;空间很便宜!):
if (pid == 0)
{
dup2(fd1[1], 1);
close(fd1[0]);
close(fd1[1]);
execvp(argv[i][0], argv[i]);
fprintf(stderr, "%s: Invalid command or Command not found\n", argv[i][0]);
exit(1);
}