进程间通信管道篇之命名管道

文章目录

  • 1.1命名管道
    • 1.2命名管道的创建
    • 1.3命名管道和匿名管道的区别
    • 代码演示(用命名管道实现进程间通信)
  • 2.1 通过进程间通信将客户端发送的字符串转化为命令让服务端执行
  • 3.1通过进程间通信传输数据设计一个计算器
  • 4.1 通过进程间通信实现进程间文件的互传
    • 总结

1.1命名管道

问题引出:为什么有了匿名管道还需要命名管道呢?

因为匿名管道是只用于具有亲缘关系的,例如父子进程间通信可以用匿名管道,但是如果要使得毫无关系的两个进程间进行通信,匿名管道就派不上用场了,就需要用命名管道来实现。命名管道是一种特殊的文件,它可以使的进程之间共享同一块资源,通过对该资源的读写来实现通信。命名管道解除了管道只能在具有亲缘关系的进程间使用的限制。

1.2命名管道的创建

  • 第一种:通过命令行方式进行创建

    mkfifo +"文件名"方式

  • 第二种:通过代码方式( 调用函数mkfifo() )创建

    定义:

    第一个参数是要创建的管道文件的路径(当前路径下的名称),第二个参数是权限的设置 一般都是0xxx的形式

​ 返回值:如果创建成功返回0 不成功返回-1 可以以此来判断是否创建成功

例:

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
int main()
{if(makfifo("myfifo",0644)<0){printf("mkfifo fail!\n");return -1;}return 0;
}

1.3命名管道和匿名管道的区别

  • 命名管道由mkfifo函数创建,打开用open
  • 匿名管道由pipe创建并打开
  • 命名管道和匿名管道之间的唯一区别在于它们创建和打开的方式不同,创建和打开之后它们具有相同的语义

​ 只读打开用open(“文件名”,O_RDONLY);

​ 只写打开用open(“文件名”,O_WRONLY);

​ 打开还有O_CREAT

​ 要实现不同的打开方式,使用 或 | 将上面的混合使用即可

代码演示(用命名管道实现进程间通信)

//两个.c 文件 client.c  serve.c  一个充当客户端 一个充当服务端 引用同一个头文件serve.h//serve.h
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<string.h>
#define File_Name "fifo"-----------------------------------
//serve.c#include"sever.h"
int main()
{if(mkfifo(File_Name,0644)<0){perror("mkfifo");return -1;}//通过mkfifo 创建了命名管道 接下来就是通过管道让服务端和客户端进行通信//接下来就是通过对管进行读写实现两个进程间的通信了int fd = open(File_Name,O_RDONLY);//打开文件 只读if(fd < 0){perror("open");return -2;}char srt[128];while(1){srt[0]=0;//清空文件int s= read(fd,srt,sizeof(srt));//open的第一个参数是文件名 而read的第一个参数是文件描述符if(s>0)//还没有读完的情况{srt[s-1]=0;//如果读了127 个字节就返回127 把改下标设为0 在打印出读到的内容 读是读s个 其中包括了\n 然后把 s-1 对应的\n 设为0 printf("client send message# %s\n",srt);}else if(s==0){printf("client quit!\n");break;}else{//说明读取错误 返回的是-1perror("read");break;}}close(fd);//打开了文件最后要将其关闭return 0;
}----------------------------------------
//client.c#include"serve.h"
int main()
{//先打开管道文件int fd=open(File_Name,O_WRONLY);if(fd<0){perror("open");return -1;}//打开了文件后就要从键盘读取数据 然后把读到的数据写到管道中去char msg[128];while(1){msg[0]=0;printf("please Enter# ");fflush(stdout);//上面的打印没有带回车 全缓冲  所以要手动刷新缓冲区int ret=read(0,msg,sizeof(msg)-1);if(ret>0){msg[ret]=0;write(fd,msg,strlen(msg));}}close(fd);return 0;
}

2.1 通过进程间通信将客户端发送的字符串转化为命令让服务端执行

代码:(改变的额只有服务端的代码,就是创建了一个子进程 然后用进程替换 把客户端发的字符当成命令来执行 只有非常小的改动)

#include"serve.h"
#include<sys/wait.h>
#include<stdlib.h>
int main()
{if(mkfifo(File_Name,0644)<0){perror("mkfifo");return -1;}//通过mkfifo 创建了命名管道 接下来就是通过管道让服务端和客户端进行通信//接下来就是通过对管进行读写实现两个进程间的通信了int fd = open(File_Name,O_RDONLY);//打开文件 只读if(fd < 0){perror("open");return -2;}char srt[128];while(1){srt[0]=0;//清空文件int s= read(fd,srt,sizeof(srt));//open的第一个参数是文件名 而read的第一个参数是文件描述符if(s>0)//还没有读完的情况{srt[s-1]=0;//如果读了127 个字节就返回127 把改下标设为0 在打印出读到的内容 读是读s个 其中包括了\n 然后把 s-1 对应的\n 设为0 // printf("client send message# %s\n",srt);printf("client send command/message# %s\n",srt);fflush(stdout);// 改变的地方  /int pid = fork();//创建子进程来完成输入的命令if(pid==0){//childexeclp(srt,srt,NULL);//进程替换exit(1);//子进程退出}waitpid(pid,NULL,0);//阻塞式等待子进程退出}else if(s==0){printf("client quit!\n");break;}else{//说明读取错误 返回的是-1perror("read");break;}}close(fd);//打开了文件最后要将其关闭return 0;
}

补充:

这里的进程间通信通过管道实现 其中的数据是不涉及磁盘的 也就是说数据没有被刷新到磁盘里,而是在内存中!!!!

3.1通过进程间通信传输数据设计一个计算器

代码:(改动的也只有服务端)

#include"serve.h"
#include<sys/wait.h>
#include<stdlib.h>
int main()
{if(mkfifo(File_Name,0644)<0){perror("mkfifo");return -1;}//通过mkfifo 创建了命名管道 接下来就是通过管道让服务端和客户端进行通信//接下来就是通过对管进行读写实现两个进程间的通信了int fd = open(File_Name,O_RDONLY);//打开文件 只读if(fd < 0){perror("open");return -2;}char srt[128];while(1){srt[0]=0;//清空文件int s= read(fd,srt,sizeof(srt));//open的第一个参数是文件名 而read的第一个参数是文件描述符if(s>0)//还没有读完的情况{srt[s-1]=0;//如果读了127 个字节就返回127 把改下标设为0 在打印出读到的内容 读是读s个 其中包括了\n 然后把 s-1 对应的\n 设为0 printf("client send message# %s\n",srt);char* st=srt;int flag=0;while(*st)//找运算符号{switch(*st){case'+':flag=1;break;case'-':flag=2;break;case'*':flag=3;break;case'/':flag=4;break;case'%':flag=5;break;}st++;}int a,b,c;const char* str=" +-*/%";if(flag)//如果找到了运算符号就进行拆分子串{char* s1=strtok(srt,str);char* s2=strtok(NULL,str);a=atoi(s1);//字符转数字b=atoi(s2);switch(flag)//计算{case 1:c=a+b;break;case 2:c=a-b;break;case 3:c=a*b;break;case 4:c=a/b;break;case 5:c=a%b;break;}printf("%d %c %d = %d\n",a,str[flag],b,c);//打印}}else if(s==0){printf("client quit!\n");break;}else{//说明读取错误 返回的是-1perror("read");break;}}close(fd);//打开了文件最后要将其关闭return 0;
}

4.1 通过进程间通信实现进程间文件的互传

代码:

//客户端
#include"serve.h"
int main()
{//先打开管道文件int fd=open(File_Name,O_WRONLY);if(fd<0){perror("open");return -1;}int fd1=open("file.txt",O_RDONLY);//打开文件 从管道中读取file.txt的数据 再往file-bk.txt里面写就可以实现文件的拷贝了if(fd1<0){perror("open file.txt");return -2;}//打开了文件后就要从键盘读取数据 然后把读到的数据写到管道中去char msg[128];while(1){msg[0]=0;dup2(fd1,0);//重定向fd为0 也就是相当于把stdin关了 再创建file-bk 实现了从标准输入中读入数据就是从file-bk中读入数据ssize_t ret=read(0,msg,sizeof(msg));if(ret==sizeof(msg)){// msg[ret-1]=0;//设置\0使得文件可以在输出的时候可以结束write(fd,msg,ret);//把数据写到新打开的文件中去}else if(ret<sizeof(msg)){write(fd,msg,ret);//把不足期望的大小的数据写到文件中printf("read end of file!\n");break;}else{printf("read error!\n");break;}}close(fd);close(fd1);return 0;
}
//服务端
#include"serve.h"
#include<sys/wait.h>
#include<stdlib.h>
int main()
{if(mkfifo(File_Name,0644)<0){perror("mkfifo");return -1;}//通过mkfifo 创建了命名管道 接下来就是通过管道让服务端和客户端进行通信//接下来就是通过对管进行读写实现两个进程间的通信了int fd = open(File_Name,O_RDONLY);//打开文件 只读if(fd < 0){perror("open");return -2;}int fd1=open("file-bk.txt",O_CREAT|O_WRONLY,0644);//以只读的方式打开已经存在的file.txt文件 一定是可以打开的 不用判断char srt[128];while(1){srt[0]=0;int s= read(fd,srt,sizeof(srt));//open的第一个参数是文件名 而read的第一个参数是文件描述符if(s>0)//还没有读完的情况{//  write(fd1,srt,sizeof(srt));write(fd1,srt,s);//不是sizeof(srt)}else if(s==0){printf("client quit!\n");break;}else{//说明读取错误 返回的是-1perror("read");break;}}close(fd);//打开了文件最后要将其关闭close(fd1);return 0;
}

总结

总结:命名管道其实就是一个文件,只不过是操作系统对其进行了加工处理,使其具有特定的功能,这个管道文件就是在毫无关系的进程间共享的,使得毫无关系的进程能看到同一份资源,进程对该资源进行文件读写,实现信息的交互,达到通信的效果!!!(只要创建出了命名管道,接下来的操作就是对文件的读写处理了)

管道实现进程间通信之命名管道相关推荐

  1. pythonwindows管道_Python进程间通信之命名管道(Windows)

    前面文章说了一下 Linux 命名管道的实现,今天看看 Windows 上我们怎么实现. 在 Windows 上的命名管道主要是通过调用 win32 api 的以下方法来实现的:win32pipe.C ...

  2. 【Linux系统编程】进程间通信之命名管道

    00. 目录 文章目录 00. 目录 01. 命名管道概述 02. 命名管道创建 03. 命名管道特性 04. 命名管道非阻塞 05. 附录 01. 命名管道概述 无名管道,由于没有名字,只能用于亲缘 ...

  3. Linux进程间通信——使用命名管道

    在前一篇文章-- Linux进程间通信--使用匿名管道中,我们看到了如何使用匿名管道来在进程之间传递数据,同时也看到了这个方式的一个缺陷,就是这些进程都由一个共同的祖先进程启动,这给我们在不相关的的进 ...

  4. 【Linux】进程间通信 - 匿名/命名管道与System V共享内存

    目录 前言 一.管道 0.什么是管道 1).管道的概念 2).管道的本质 3).管道指令: "|" 1.匿名管道 1).如何创建匿名管道 2).如何使用匿名管道进行通信 3).匿名 ...

  5. Linux系统编程——进程间通信:命名管道(FIFO)

    命名管道的概述 无名管道,由于没有名字,只能用于亲缘关系的进程间通信(更多详情,请看<无名管道>).为了克服这个缺点,提出了命名管道(FIFO),也叫有名管道.FIFO 文件. 命名管道( ...

  6. python命名管道通讯_Python进程间通信的命名管道详解(Windows)

    本文和大家分享的主要是windows系统下,python进程间通信的命名管道相关内容 ,一起来看看吧,希望对大家学习python有所帮助. 在 Windows 上的命名管道主要是通过调用win32 a ...

  7. 进程间通信:命名管道FIFO(2)

    一.命名管道 如果我们想在不相关的进程之间交换数据,可以用FIFO文件来完成这项工作,它通常也被称为命名管道.命名管道是一种特殊类型的文件,它在文件系统中以文件名的形式存在,但是它的行为却和我们已经见 ...

  8. 进程间通信之命名管道

    命名管道(FIFO)是进程间通信的一种方式. API: int mkfifo(const char *pathname, mode_t mode); DEMO: // 写进程 int main(int ...

  9. python 命名管道_详解Python进程间通信之命名管道

    管道是一种简单的FIFO通信信道,它是单向通信的. 通常启动进程创建一个管道,然后这个进程创建一个或者多个进程子进程接受管道信息,由于管道是单向通信,所以经常需要创建两个管道来实现双向通信. 命名管道 ...

最新文章

  1. 工业相机帧率与曝光时间的关系
  2. JavaScript实现z-algorithm算法(附完整源码)
  3. 01.WPF中制作无边框窗体
  4. 求逆矩阵计算器_991CN的矩阵运算
  5. 百变方块java代码_多牛百变方块
  6. php转化为2位小数的数字,学习猿地-php 转化为两位小数的方法
  7. 如何使用PowerShell创建简单SQL Server数据库登录对话框
  8. 记一次在Tomcat部署项目后无法启动该项目的例子
  9. python——迭代器itertools.cycle
  10. 2021进销存管理软件最具影响力榜单排名
  11. SpringBoot整合调用微信模板方法实现微信公众号消息通知推送,Java实现微信公众号给关注用户推送自定义消息通知(手把手从0到1)
  12. matlab中变量类型
  13. win10系统无工具一键升级与重装
  14. 为什么手机上传图片这么慢 前端_为什么手机上传速度那么慢?
  15. linux对IO口控制remap,ioremap/remap_page_range [经典]Linux内核中ioremap映射的透彻理解...
  16. 夜神模拟器没有开发者选项怎么办?
  17. Lenovo笔记本各类型触控板,触摸部分只能移动无法点击的问题汇总
  18. CTFHub-web前置技能-请求方式、302跳转、cookie、基础认证、响应包源代码
  19. 设计模式----观察者模式
  20. 玩转树莓派 一、为你的树莓派烧录系统镜像

热门文章

  1. 中职计算机网络课后题,中职计算机网络技术试题.doc
  2. 普中单片机怎么接霍尔传感器_基于51单片机的数字测速系统的设计方案
  3. 传奇脚本显示服务器开区时间代码,开区服务端常用命令列表脚本
  4. 微软开始为公开推出准备 Windows 10 22H2 功能更新
  5. sentos7下yum安装mariadb
  6. 粗暴解决node-gyp的configure error问题
  7. USB转串口那些事儿—电源与防倒灌设计
  8. 万达商管再冲刺上市:承诺三年要赚220亿元,王健林夫妇提前套现
  9. bootloader调试
  10. Redis性能调优之Pipeline(管道)