Linux进程间通信(2)---无名管道和有名管道(超简单,有示例程序)教程
管道是什么呢?
比如说有两个池塘A和B如果我先要A和B中的水可以相互流动,那么我们只需要在两个池塘间安放一条水管就可以了嘛!如果将A、B换成我们程序中的进程,那么使这两个进程通信的那根管子就叫管道。
- -
管道可以分为两种:
无名管道
:用于父子进程间的通信。
有名管道
:用于任意两进程间的通信。
首先我们来看一下无名管道
管道不是有两端嘛,每一端都可以流入水和流出水,但是流入和流出是不是只能有一种情况呢。所以在无名管道中也一样,无名管道的两端,每一端都可以读和写。
若一端为读就要关闭他的写功能,另一端就只能为写关闭读功能
下面我们先看一下一个函数
#include <unistd.h>
int pipe(int pipefd[2])
作用:创建一个无名管道
参数:pipefd[2]为你自己定义的一个数组
返回值:成功 0,失败 -1;
pipefd[0]存储管道的读描述符
pipefd[1]存储管道的写描述符
好了接下来无名写一个小程序:
/*
创建一个管道,子进程读取管道内容,父进程写入管道内容
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define N 1024
/*
1、子进程读 父进程写
2、先写才能读,所以保证父进程先完成写操作
*/
int main(void)
{
pid_t pid;
int pipe_fd[2];
int fd;
char date[]="wlecome the rose flower shop";
char buf[N];
if(pipe(pipe_fd)<0)
{
printf("pipe error\n");
}
pid=fork();
if(pid==0)//子进程
{
close(pipe_fd[1]);//子进程用于读,所以关闭写功能
sleep(3);//保证父进程运行完成,子进程只执行到关闭写功能
fd= read(pipe_fd[0],buf,sizeof(date));
if(fd>0)
{
printf("child progress read: %s\n", buf);
}
close(pipe_fd[0]);
exit(0);
}
if(pid>0)
{
close(pipe_fd[0]);//父进程写入,所以关闭读功能
sleep(1);//等待子进程关闭写功能
fd=write(pipe_fd[1],date,sizeof(date));
if(fd>0)
{
printf("father progress write: %s\n", date);
}
close(pipe_fd[1]);
sleep(2);
}
return 0;
}
/*
子进程:
close(pipe_fd[1]);
sleep(3);
父进程:
close(pipe_fd[0]);
sleep(1);
原因:假如子进程先运行(fork创建的进程父、子进程无法判断谁先运
行)子进程是读所以关闭写,sleep(3)让父进程运行,此时父进程运行,
先关闭读功能,还要保证写功能没有被子进程占用,这里子进程先运行上
来就关闭子进程的写功能了。假如父进程先运行,父进程先关闭读功能,
但是子进程没有关闭写功能,所以父进程sleep(1)延时1S.让子进程执行
完第一条程序。sleep(1)<sleep(3)
*/
看一下运行结果:
2s后
有名管道
有名管道你就可以理解为,有一个文件,A、B进程都可以访问,A可以向里面写数据,也可以读数据,B亦然。
话不多说,我们先来看一个函数
#include<sys/types.h>
#include<sys/stat.h>
int mkfifo(const char * pathname,mode_t mode);
参数:pathname: 文件名
mode:这个要深入研究的话比较复杂,我网上查了也很多
https://blog.csdn.net/superywf/article/details/73438465
这个博客里面是这样说的:
mkfifo()会依参数pathname建立特殊的FIFO文件,该文件必须不存在,而
参数mode为该文件的权限
有名管道读端:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#define MYFIFO "/zxp_linux/myfifo"
int main(void)
{
int fd;
char buff[4096];
if(access(MYFIFO,F_OK)==-1)//检测文件是否存在,函数详解可以csdn一搜就有
{
if(mkfifo(MYFIFO,0666)<0)//创建有名管道
{
printf("error mkfifo\n");
exit(1);
}
}
fd=open(MYFIFO,O_RDONLY);//打开有名管道(文件)
if(fd<0)
{
printf("error open\n");
exit(1);
}
while(1)
{
memset(buff,0,sizeof(buff));
if(read(fd,buff,sizeof(buff)))
{
printf("read named_pipe %s\n", buff);
}
}
close(fd);
return 0;
}
写端口:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#define MYFIFO "/zxp_linux/myfifo"
int main(int argc,char *argv[])
{
int fd;
char buff[4096]={0};
if(argc<=1)
{
printf("error scanf\n");
printf("./write string\n");
}
sscanf(argv[1],"%s",buff);
fd=open(MYFIFO,O_WRONLY);
if(fd<0)
{
printf("error open\n");
exit(1);
}
if(write(fd,buff,sizeof(buff)));
{
printf("pipe write %s\n", buff);
}
close(fd);
return 0;
}
运行结果:
本文代码参考博客:
http://blog.csdn.net/mybelief321/article/details/9073895
https://blog.csdn.net/mybelief321/article/details/9075229