日期:2014-05-16  浏览次数:20842 次

初学管道实现时的阻塞问题~
[code]
#include   <unistd.h>
#include   <sys/types.h>
main(){  
int   pipe_fd[2];
  pid_t   pid;  
char   r_buf[4];  
char*   w_buf;  
int   writenum;  
int   cmd;    
memset(r_buf,0,sizeof(r_buf));  
if(pipe(pipe_fd) <0)  
{        
printf( "pipe   create   error\n ");        
return   -1;  
}    
if((pid=fork())==0)  
{        
close(pipe_fd[0]);      
close(pipe_fd[1]);         //注意这两行
sleep(10);          
exit();  
}  
else   if(pid> 0)  
{  
sleep(1);      
close(pipe_fd[0]);
write   w_buf= "111 ";  
if((writenum=write(pipe_fd[1],w_buf,4))==-1)        
printf( "write   to   pipe   error\n ");  
else          
printf( "the   bytes   write   to   pipe   is   %d   \n ",   writenum);    
close(pipe_fd[1]);  
}
}

//上面将发生     Broken   Pipe

#include   <unistd.h>
#include   <sys/types.h>
main(){  
int   pipe_fd[2];
  pid_t   pid;  
char   r_buf[4];  
char*   w_buf;  
int   writenum;  
int   cmd;    
memset(r_buf,0,sizeof(r_buf));  
if(pipe(pipe_fd) <0)  
{        
printf( "pipe   create   error\n ");        
return   -1;  
}    
if((pid=fork())==0)  
{        
close(pipe_fd[1]);      
read(pipe_fd[0],r_buf,sizeof(r_buf);//加入了这行   就不会Broken   Pipe   了     小弟不解     望高手解释下这里所做的~~     为什么多了这句就能开放管道的读端了呢?
close(pipe_fd[0]);         //注意这两行
sleep(10);          
exit();  
}  
else   if(pid> 0)  
{  
sleep(1);      
close(pipe_fd[0]);
write   w_buf= "111 ";  
if((writenum=write(pipe_fd[1],w_buf,4))==-1)        
printf( "write   to   pipe   error\n ");  
else          
printf( "the   bytes   write   to   pipe   is   %d   \n ",   writenum);    
close(pipe_fd[1]);  
}
}

------解决方案--------------------
你要记得fork之后父子的pipe_fd[0]或pipe_fd[1]必须都关闭才能真正关闭0或1

原因是二种情况下,子调用read函数阻塞,因为这时没有数据可读。父进程sleep(1)后向管道中写了4字节,然后关闭管道写描述符,然后子的read返回,关闭读,再睡10秒后退出。这时没有发生:向读端已关闭的pipe写的情况。

第一种情况下,子先关闭
close(pipe_fd[0]);
close(pipe_fd[1]);
sleep(10); //关闭管道两端后,sleep(10),
在子开始sleep的时候,父的sleep(1)才完成,然后close(pipe_fd[0]);至此pipe的读端真正被关闭了,然后的write就是一个写对端关闭的错误操作。