无名管道与有名管道

一、无名管道

1.无名管道函数图
在这里插入图片描述
2. 管道文件是一个特殊文件,它由队列实现的。
在文件IO中,创建、打开一个文件是由open函数实现,但是无名管道不能用open创建,对应的函数是pipe。
创建:pipe(fd) //fd[0]是读端口,fd[1]是写端口
读:read(f[0], readbuf, 128 ) //在管道读取128byte到readbuf内存中,实际读取字节数<=128字节
写:write(f[0], writebuf, sizeof(writebuf) ) //将writebuf内存中的数据写入到管道中,大小为sizeof(writebuf)个字节
关闭:
close(fd[0]) //close read
close(fd[1]) //close write
无名管道的无名是指在它在文件系统中无文件名。

3.无名管道的特性
3.1 没有名字,因此不能使用open函数,只能在进程中创建,然后通过继承方式将无名管道文件描述符传递给子进程
3.2 只能用于亲缘进程间(父子、兄弟、祖孙进程)通讯
3.3 半双工,读写分开
3.4 写入不具备原子性,因此只能一对一的简单通讯
3.5 跟FIFO和socket一样,不能使用lseek()来定位,他们不像普通文件一样存放在磁盘、flash等设备上。
3.6 具有读写堵塞性,当管道写满或者管道无数据的时候去读取管道,将会堵塞

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;
  ret=pipe(fd);	//必须先创建管道,然后再创建子进程。如此才能继承父进程的PIPE文件描述符
  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);//如果管道没有数据则堵塞
    while(process_inter ==0);
	 for(i=0;i<2;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<2;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;
}

效果如下:

c@c:$ ./a.out
creat pipe sucess
this is parent process i=0
this is parent process i=1
this is parent process i=2
this is child process i=0
this is child process i=1
this is child process i=2

二、有名管道

1.有名管道函数图
在这里插入图片描述
2. mkfifo使用方法与open类似,有名管道创建完后,在指定目录中生成文件。
mkfifo调用内核,内核在文件系统中生成文件名,并没有在内核中生成管道。只有在调用open代开有名管道时,才会在内核中创建管道。这个文件不占用磁盘空间,只有innode号,和套接字、字符设备文件、块设备文件一样。普通文件,符号链接文件及目录文件不仅有inode号,还占用磁盘空间。
创建有名管道mkfifo。跟普通文件一样使用,打开open,读read,写write,关闭close。

3.有名管道的特性

3.1 两个进程操作有名管道时,一个读,一个写。当读端RD,写端WR都打开时,程序才会运行,不然会阻塞。(就是管道读写都开打时,open函数才能打开管道)
3.2 有名字,存储于普通文件系统之中
3.3 任何具有相应权限的进程都可以使用open()来获取FIFO的文件描述符
3.4 跟普通文件一样:使用统一的read、write来读写
3.5 具有原子性,支持多写者同时进行写操作而数据不会相互践踏
3.6 First In First Out, 最先被写入FIFO的数据。最先被读写出来
3.7 跟普通文件不同,不能使用lseek()来定位

在这里插入图片描述
写者:持有文件可写权限的描述符的进程
读者:持有文件可读权限的描述符的进程

4.例子
第一个进程:

#include "unistd.h"
#include "stdio.h"
#include "sys/types.h"
#include "stdlib.h"
#include "fcntl.h"

#define MYFIFO "/home/c/process/myfifo"

int main()
{
 int fd;
 int i;
 char process_inter=0;

 if(access(MYFIFO, F_OK))	//只判断是否存在,不存在返回非0
 {
	 mkfifo(MYFIFO, 0644);
 }

 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;  
}

第二个进程:

#include "unistd.h"
#include "stdio.h"
#include "sys/types.h"
#include "stdlib.h"
#include "fcntl.h"

#define MYFIFO "/home/c/process/myfifo"

int main()
{
 int fd;
 int i;
 int process_inter=0;

 if(access(MYFIFO, F_OK))	//只判断是否存在,不存在返回非0
 {
	 mkfifo(MYFIFO, 0644);
 }

 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;  
}

参考:https://blog.csdn.net/wenwen111111/article/details/54645682

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值