Linux进程间通信之有名无名管道

Linux进程间通信之有名无名管道

一:无名管道
通信原理:
在这里插入图片描述
管道文件是一个特殊的文件,是由队列来实现的。
在文件IO中创建一个文件或打开一个文件是由open函数来实现的,它不能创建管道文件。只能用pipe函数来创建管道。(open函数只能创建普通文件)
函数形式:int pipe(int fd[2])
功能:创建管道,为系统调用:unistd.h
参数:就是得到的文件描述符。可见有两个文件描述符:fd[0]和fd[1],管道有一个读端fd[0]用来读和一个写端fd[1]用来写,这个规定不能变。(有了文件描述符后就可以对文件进行write read)
返回值:成功是0,出错是-1;

例1:pipe函数使用。

#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main()
{
  int fd[2];
  int ret;
  char writebuf[]="hello linux";
  char readbuf[128]={0};
  ret=pipe(fd);
  if(ret <0)
  {
	printf("creat pipe failure\n");
	return -1;
  }
  printf("creat pipe sucess fd[0]=%d,fd[1]=%d\n",fd[0],fd[1]);

  write(fd[1],writebuf,sizeof(writebuf));
  //start read from pipe
  
  read(fd[0],readbuf,128);
  printf("readbuf=%s\n",readbuf);

  //second read from pipe
  
  memset(readbuf,0,128);
  //会阻塞在这里
  read(fd[0],readbuf,128);
  printf("second read after\n");

  close(fd[0]);
  close(fd[1]);
  return 0;
}

注意:
管道中的东西,读完了就删除了;队列
如果管道中没有东西可读,则会读阻塞。

例2:验证读阻塞。例3:验证写阻塞:可以计算出内核开辟的管道有多大。
5456个writebuf时不写阻塞 5457个writebuf 时会阻塞

#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main()
{
  int fd[2];
  int ret;
  int i=0;
  char writebuf[]="hello linux";
  char readbuf[128]={0};
  ret=pipe(fd);
  if(ret <0)
  {
	printf("creat pipe failure\n");
	return -1;
  }
  printf("creat pipe sucess fd[0]=%d,fd[1]=%d\n",fd[0],fd[1]);
  while( i < 5457)
  {
   write(fd[1],writebuf,sizeof(writebuf));
   i++;
  }
  
  printf("write pipe end\n");

  close(fd[0]);
  close(fd[1]);
  return 0;
}

在这里插入图片描述

例4:实现进程通信。

#include "unistd.h"
#include "stdio.h"
#include "sys/types.h"
#include "stdlib.h"
int main()
{
  pid_t pid;
  int fd[2];
  int ret;
  char process_inter=0;
  //应该在fork函数之前就创建管道,这样父子进程才用的是同一管道
  ret=pipe(fd);
  if(ret < 0)
  {
	printf("creat pipe failure\n");
	return -1;
  }
  printf("creat pipe sucess\n");
  pid = fork();
  if(pid ==0)//child process code   second
  {
    int i=0;
	read(fd[0],&process_inter,1);//if pipe empty   sleep
    while(process_inter ==0);
	 for(i=0;i<5;i++)
	 {
      printf("this is child process i=%d\n",i);
	  usleep(100);
	 }
  }
  if(pid >0)//parent process code   first
  {
	int i=0;
	for(i=0;i<5;i++)
	{
	  printf("this is parent process i=%d\n",i);
	  usleep(100);
	}
	process_inter=1;
	sleep(5);
	write(fd[1],&process_inter,1);
  }
  while(1);
  return 0;   
}

在这里插入图片描述
无名管道的缺点:只能实现父子进程(有亲缘关系进程)之间的通信。

无名管道:文件系统中无文件名
有名管道:文件系统中有文件名

二.有名管道

正由于这无名管道的缺点,对无名管道进行改进:有名管道。
所谓的有名,即文件系统中存在这个一样文件节点,每一个文件节点都有一个inode号
而且这是一个特殊的文件类型:p管道类型。
1.创建这个文件节点,不可以通过open 函数,open 函数只能创建普通文件,不能创建特殊文件(管道-mkdifo,套接字-socket,字符设备文件-mknod,块设备文件-mknod,符号链接文件-ln –s,目录文件mkdir)
2.管道文件只有inode号,不占磁盘块空间,和套接字、字符设备文件、块设备文件一样。普通文件和符号链接文件及目录文件,不仅有inode号,还占磁盘块空间。
3. mkfifo 用来创建管道文件的节点,没有在内核中创建管道。
只有通过open 函数打开这个文件时才会在内核空间创建管道。
4.mkfifo
函数形式:int mkfifo(const char *filename,mode_t mode);
功能:创建管道文件
参数:管道文件文件名,权限,创建的文件权限仍然和umask有关系。
返回值:创建成功返回0,创建失败返回-1。
例1:mkfifo的用法。
例子:通过管道实现无亲缘关系进程间通信。
mkfifo.c

#include "stdio.h"
#include "unistd.h"
#include "stdlib.h"
#include <sys/stat.h>
#include <sys/types.h>
int main()
{
  int ret;
  ret=mkfifo("./myfifo",0777);
  if(ret <0)
  { 
	printf("creat myfifo failure\n");
	return -1;
  }
  printf("creat myfifo sucess\n");

  return 0;
}

注:ubuntu下的共享文件夹下是无法创建有名管道的。
在这里插入图片描述
注:管道文件只有inode号,不占磁盘块空间,和套接字、字符设备文件、块设备文件一样。普通文件和符号链接文件及目录文件,不仅有inode号,还占磁盘块空间。

进程A写有名管道

#include "unistd.h"
#include "stdio.h"
#include "sys/types.h"
#include "stdlib.h"
#include "fcntl.h"
int main()
{
 int fd;
 int i;
 char process_inter=0;
 fd=open("./myfifo",O_WRONLY);
 if(fd <0)
 {
   printf("open myfifo failure\n");
   return -1;
 }
 printf("open myfifo sucess\n");

 for(i=0;i<5;i++)
 {
   printf("this is first process i=%d\n",i);
   usleep(100);
 }
 process_inter=1;
 sleep(5);
 write(fd,&process_inter,1);
 while(1);
 return 0;  
}

进程B读管道

#include "unistd.h"
#include "stdio.h"
#include "sys/types.h"
#include "stdlib.h"
#include "fcntl.h"
int main()
{
 int fd;
 int i;
 int process_inter=0;
 fd=open("./myfifo",O_RDONLY);
 if(fd <0)
 {
   printf("open myfifo failure\n");
   return -1;
 }
 printf("open myfifo sucess\n");

 read(fd,&process_inter,1);
 while(process_inter == 0);

 for(i=0;i<5;i++)
 {
   printf("this is second process i=%d\n",i);
   usleep(100);
 }
 while(1);
 return 0;  
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值