用户名: 密码: 忘记密码? 注册

linux进程通信之(二):管道的读与写

作者:  时间: 2010-11-03
为了更好的理解管道的读与写,请看下面的一段程序:
#include<unistd.h>
#include<sys/types.h>
#include<errno.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
 int pipe_fd[2];
 pid_t pid;
 char buf_r[100];
 char *p_wbuf;
 int r_num;
 memset(buf_r,0,sizeof(buf_r));//把一段内存清0
 if(pipe(pipe_fd)<0)//创建管道
 {
  printf("pipe create error\n"); 
  return -1;
 } 
 if((pid=fork())==0)//创建一子进程,如果子进程先运行
 {
  printf("\n");
  close(pipe_fd[1]);//关闭子进程写描述符,并通过使父进程暂停2s确保
                   //父进程已关闭相应的读描述符
  sleep(2); 
  if((r_num=read(pipe_fd[0],buf_r,100))>0)//子进程读取管道内容
  {
   printf("%d numbers read from the pipe is %s\n",r_num,buf_r);
  }
  close(pipe_fd[0]);//关闭子进程读描述符
  exit(0);
 }
 else if(pid>0)//如果父进程先运行
 {
  close(pipe_fd[0]);//关闭父进程读描述符,并分两次向管道中写入hello pipe
  if(write(pipe_fd[1],"hello",5)!=-1)
  {
   printf("parent write1 success !\n"); 
  }
  if(write(pipe_fd[1],"pipe",5)!=-1)
  {
   printf("parent write2 sucess !\n"); 
  }
  close(pipe_fd[1]);//关闭父进程写描述符
  sleep(3);
  waitpid(pid,NULL,0);//收集子进程退出信息
  exit(0);
   
 }

}
/*--------------------------------------------------------
notes:
1.用pipe函数创建的管道两端处于一个进程中,实际上,通常先是创建一个管道,再
通过fork()函数创建一子进程,该子进程会继承父进程所创建的管道。
2.实验:
[root@localhost the_eight_step]# gcc pipe_rw.c -o pipe_rw
[root@localhost the_eight_step]# ./pipe_rw
parent write1 success !
parent write2 sucess !
10 numbers read from the pipe is hellopipe
3.管道读写注意点
.只有在管道的读写端存在时向管道中写入数据才有意义。否则,向管道中写入数据的进程
将收到内核传来的SIFPIPE信号(通常Broken pipe错误)。
.向管道中写入数据时,linux将不保证写入的原子性,管道缓冲区有一空闲区域,写进程就
会试图向管道写入数据。如果读进程不读取管道缓冲区中的数据,那么写操作将会一直阻塞。
.父子进程在运行时,它们的先后次序并不能保证,因此,在这里为了保证父进程已经关闭了
读描述符,可在子进程中调用sleep函数。
4.主要顺序:
先创建管道,后创建子进程

-------------------------------------------------------------*/