linux进程通信之(二):管道的读与写
时间:2010-11-03 来源:andyluo324324
为了更好的理解管道的读与写,请看下面的一段程序:
#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.主要顺序:
先创建管道,后创建子进程
-------------------------------------------------------------*/
#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.主要顺序:
先创建管道,后创建子进程
-------------------------------------------------------------*/
相关阅读 更多 +