我正在做一个测试,我的任务是一个孩子将输出管道化到另一个孩子的输入。我正在使用ps -ef
第一个命令(通过使用execlp())
和grep root
作为第二个命令(bu using execlp()
)。我得到了所需的输出,但我在执行 grep 的进程中被阻止。我已使用 top 命令来验证当前正在运行的进程。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<fcntl.h>
int main(){
int status,i;
int fds[2];
pid_t pid;
//pid=fork();;
if(pipe(fds)==-1){
perror("Error:");
exit(0);
}
if(fork()>0){
printf("The pid of the parent is %d\n",getpid());
if(fork()==0){
printf("The PID of the 2nd child %d\n",getpid());
//printf("Inside 2nd child\n");
close(0);
dup(fds[0]);
close(fds[1]);
//fcntl(fds[0],F_SETFD,FD_CLOEXEC);
//printf("The PID of the 2nd child %d\n",getpid());
if(execlp("grep","grep","root",NULL)==-1){
perror("ERROR FROM SECOND CHILD: ");
exit(1);
}
}
else{
printf("The parent is waiting\n");
/*for(i=0;i<2;i++){
printf("%d The PID OF THE EXIT CHILD is %d\n",i,wait(&status));
}*/
while(wait(NULL)>0)
perror("Error From Main:\n");
//wait(&status);
printf("The parent exited from the waiting stage\n");
return 0;
}
//while(1);
}
else{
close(1);
dup(fds[1]);
close(fds[0]);
//close(1);
printf("The pid of the First child is %d\n",getpid());
if(execlp("ps","ps","-ef",NULL)==-1){
perror("Error:");
exit(1);
}
}
}
请帮助我。因为我正在制作外壳。执行此任务是必要的。
答案1
grep 进程被阻止,因为它没有从管道的其他写入端获取 EOF。当关联的写入文件(fds[1])描述符将关闭时,EOF 将发送到读取器端。我的错误是我没有尽管我已经从正在写入管道的进程中关闭了它,但从父进程(main)关闭了写入描述符(fds[1])。
所以可能会出现这样的问题:即使我们不使用描述符,我们是否也需要关闭它?是的,是的!因为父进程和子进程具有相同的描述符副本,这些描述符基本上是内存引用(我不确定)。因此,即使我们从一个进程关闭,另一个副本也可能在另一个进程中打开,这可能会阻塞第三个进程可能正在从管道中读取数据。
我通过使用 cat /proc// 研究文件描述符来进行调试。