管道:当从一个进程连接数据流到另一个进程时,使用术语管道.
有名管道
无名管道(pipe)
无名管道特点:
1 只能用于具有血缘关系的进程之间
2 半双工的通信模式,具有固定的读端和写端
3 一种特殊的文件,存在于内存中,可通过read、write对其操作
通常在父进程中创建管道,在创建子进程,子进程继承了父进程打开的文件描述符,父子进程可通过管道进行通信。
创建无名管道函数原型:
#include<unistd.h>
int pipe(int fd[2]);
fd[0]读端 fd[1]写端
成功返回0,失败返回-1
应用:
1 在一个进程中使用管道:代码如下
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
void main()
{
int fd[2];
assert(pipe(fd) != -1);//创建管道
write(fd[1],"hello",5);//向管道写数据
char buff[128]={0};
read(fd[0],buff,127);//从管道读数据
printf("buff=%s\n",buff);
close(fd[0]);//关闭读端
close(fd[1]);//关闭写端
}
进程结束管道结束
2 父子进程无名管道通信
图解:
代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
void main()
{
int fd[2];
assert(pipe(fd) != -1);//创建无名管道
pid_t pid = fork();
assert(pid != -1);
if(pid == 0)
{//子进程关闭写端
close(fd[1]);
char buff[128]={0};
read(fd[0],buff,128);
printf("child read:%s\n",buff);
close(fd[0]);
}
else
{//父进程关闭读端
close(fd[0]);
char buff[128]={0};
printf("father input:\n");
fgets(buff,128,stdin);
write(fd[1],buff,strlen(buff));
close(fd[1]);
}
exit(0);
}
3 文件表
先创建管道文件fifo,有名管道写端覆盖标准输出,printf即是写进管道
函数原型:
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
写端main_pipe.c代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<fcntl.h>
void main()
{
int fdw = open("fifo",O_WRONLY);//打开管道写端
assert(fdw != -1);
dup2(fdw,1);//管道写端覆盖标准输出
//fdw标识的文件也指向保准输出
printf("hello\n");//标准输出 相当于写数据到管道 (write的功能)
fflush(stdout);//立即写入,不等缓冲区满
sleep(1);
printf("main over\n");
close(fdw);
exit(0);
}
读端test_pipe.c代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
#include<assert.h>
void main()
{
int fdr = open("fifo",O_RDONLY);
assert(fdr != -1);
char buff[128]={0};
while(read(fdr,buff,127) >0)//从管道连续读数据
{
printf("%s\n",buff);
memset(buff,0,128);//清空buff
}
close(fdr);
exit(0);
}
运行结果: