ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Linux进程间通信(2)---无名管道和有名管道(超简单,有示例程序)

2020-12-18 18:03:08  阅读:146  来源: 互联网

标签:pipe 示例 int 间通信 管道 fd 进程 include


管道是什么呢?

比如说有两个池塘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

标签:pipe,示例,int,间通信,管道,fd,进程,include
来源: https://blog.csdn.net/qq_42695024/article/details/111382635

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有