匿名管道(pipe)
管道是一种最基本的IPC机制,由pipe函数创建。
头文件:#include <unistd.h>
函数声明:int pipe( int pipefd[2] )
描述::调用 pipe() 函数时在内核中开辟一块称为管道的缓冲区用于通信。然后通过参数pipefd传出给用户程序两个描述符。pipefd[0] 指向管道的读端,pipefd[1]指向管道的写端。 管道在用户程序看来就像一个打开的文件。通过系统调用read()和write(), 在管道中传输数据。 pipe调用成功返回0,失败则返回-1.
文章的最后面有一些关于进程等待的宏描述。
示意图:
(1):父进程创建管道
(2):父进程调用fork()函数创建出子进程
(3):父进程关闭读端【close( pipefd[0])】,子进程关闭写端【close( pipefd[1])】
1.父进程调用pipe开辟管道,取得两个指向管道的文件描述符。
2.当父进程调用fork 创建子进程时,子进程会把父进程的文件描述符也一同拷贝过去。
3.父进程关闭读端,子进程关闭写端就可以实现父进程向子进程发送数据。。父进程关闭写端,子进程关闭读端。可以实现子进程向父进程写。
4.也就是说数据只能向一个方向流动。需要双向通信时,要建立起两个管道。
正常通信代码:
/*************************************************************************
# > File Name: mypipe.c
# Author: HuoZG
# Created Time: Sat 25 Feb 2017 08:10:36 PM PST
************************************************************************/
#include<stdio.h>
#include<unistd.h> // pipe() fork()
#include<string.h> // strlen()
int main()
{
int mypipe[2] = {0, 0};// [0] read [1] write
if(pipe(mypipe) < 0)
{
printf("pipe erroe!\n");
return 1;
}
pid_t id = fork();
if(id < 0)
{
printf("fork error!\n");
return 2;
}
else if (id == 0)
{ // child -> write
close(mypipe[0]); // close read
const char * msg = "Hello World!";
int count = 5;
while(count--)
{
write(mypipe[1], msg, strlen(msg) + 1);
}
close(mypipe[1]);
}
else
{ // father -> read
close(mypipe[1]); // close write
int buf[128];
int count = 5;
while(count--)
{
ssize_t _s = read(mypipe[0], buf, sizeof(buf));
if( _s > 0)
{ // read sucess
printf("%d: child -> father: %s \n", 5-count ,buf);
}
else
{
printf("pipe write is close\n");
break;
}
}
close(mypipe[0]);
}
return 0;
}
打印结果:
1、如果所有指向管道写端的文件描述符都关闭了,而仍然有进程从管道的读端读取数据,那么管道中剩余的数据都被读取后,再次read会返回零。
将代码修改为如下:子进程提前关闭写端,而父进程while(1)一直在读
#include<stdio.h>
#include<unistd.h> // pipe() fork()
#include<string.h> // strlen()
int main()
{
int mypipe[2] = {0, 0};// [0] read [1] write
if(pipe(mypipe) < 0)
{
printf("pipe erroe!\n");
return 1;
}
pid_t id = fork();
if(id < 0)
{
printf("fork error!\n");
return 2;
}
else if (id == 0)
{ // child -> wr