目录

管道如何通信

管道的访问控制机制:

匿名管道

匿名管道数据传输的原理

如何使用(代码案例)

用C/C++代码编译实现父子进程间通信案例 :

思路

实现

命名管道

为什么要有命名管道

回归进程间通信的本质

匿名管道的短板

命名管道的原理

如何创建命名管道

如何使用(代码案例)

用C/C++代码编译实现 client进程 和 server进程的通信案例 :

思路

实现


管道如何通信

管道,是Linux下常用的进程间通信手段,具体的通信方法是 父进程打开管道文件,被子进程继承,通过文件描述符fd,父子进程能看到相同的内存级文件,而后 一个进程往管道中写,另一个进程读,完成信息的传送。

而打开管道文件与普通文件不同的是,前者具有访问控制,即同步和互斥机制,也就是具有原子性:

管道的访问控制机制:

1.从管道中读取数据时,如果管道为空,或正在被写入,执行读取的进程会阻塞等待

2.往管道中写入数据时,如果管道满了,或正在被读取,执行写入的进程会阻塞等待

3.当写端关闭后,读端读取到EOF 

以上三点机制,使得管道能像文件一样操作的同时,避同时免了使用普通文件进程间通信的 极度的 不安全性。并且,数据在管道文件中的读写是彻底的内存级别的,即不与磁盘交互,读和写皆是在内存中,效率也有一定的保证。

注意管道文件只是单向的,也就是一个进程读,一个进程写的模式,原生规定好的,使用需要符合规范

匿名管道

匿名管道数据传输的原理

匿名管道的通信特点是,通过系统调用pipe(int fd[2]),直接在内核中创建一个内存级文件,并自动被调用它的函数分别以读和写的方式打开两次,获得两个fd。存放在输出型参数fd数组中,fd[0]代表读端fd,fd[1]代表写端fd。两个参与通信的进程能分别通过readwrite这样的系统调用接口,以文件的方式对管道进行读写操作,实现数据的传递。

pipe在内存中创建匿名管道文件

如何使用(代码案例)

用C/C++代码编译实现父子进程间通信案例 :

1.子进程 进程从标准输入按行读取信息

2.通过管道传入到父进程进程中

3.由父进程进程读取并输出到标准输出流。

思路

1.调用pipe(int*fd[2])创建匿名通信管道

2.fork()创建子进程,子进程会继承fd[2]。

子进程:

(1)关闭读端:close(fd[0])

注:管道只支持单向通信,这里要求子写父读,你也可以实现为父写子读.

(2)从标准输入(键盘)读取按行读入

(3)将从键盘读入的内容写入管道

父进程

(1)关闭写端 close(fd[1])

(2)从管道读取数据知道读到文件结尾

(3)等待子进程退出

实现

#include<string.h>
#include<stdlib.h>
#include<errno.h>
#include<assert.h>
#include<stdio.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<unistd.h>#define buffer_size (128)
int main(){int fd[2]={0,0};int pipe_ret=pipe(fd);if(pipe_ret) return errno;//调用出错返回错误码pid_t child_pid=fork();if(child_pid==-1) return errno;if(child_pid==0){//child//关闭不需要的端口close(fd[0]);char child_buffer[buffer_size];while(1){//从键盘读入数据ssize_t read_size=read(0,child_buffer,buffer_size-1);//保证安全性assert(read_size<buffer_size);  child_buffer[read_size]=0;//结束条件if(strcmp(child_buffer,"_exit\n")== 0)break;//发送给父进程write(fd[1],child_buffer,read_size+1);}close(fd[1]);exit(0);}else{//fatherclose(fd[1]);char father_buffer[buffer_size];       while(1){//从管道读取数据ssize_t read_size=read(fd[0],father_buffer,buffer_size-1);//判断是否为文件结尾(子进程关闭写端)if(read_size==0)break;//保证安全性assert(read_size<=buffer_size);//输出内容  printf("父进程收到:%s",father_buffer);}close(fd[0]);//回收子进程pid_t wait_ret=waitpid(child_pid,(int*)0,0);if(wait_ret==-1) return errno;       }return 0;
}

运行效果:

命名管道

为什么要有命名管道

回归进程间通信的本质

首先明确 进程间通信的本质是 "让不同的进程,访问到同一份资源"

匿名管道的短板

匿名管道如何使不同进程访问到同一份资源?

父进程分别以读和写两次打开管道文件,而后创建子进程继承文件表述符,父子进程能够访问到同一份资源,此时能够实现一个进程写一个进程读,进而就具备了通信间通信的客观条件。

但是这样通过继承管道文件的文件描述符fd,来访问到同一份资源的方式有一个明显的缺陷,那就是匿名管道只能用于有血缘关系的进程间通信

命名管道则解决了这个问题,能让没有血缘关系的进程也能访问到同一个管道文件

命名管道的原理

在磁盘上创建一个命名管道文件,利用文件名来表示管道的唯一性,只要打开相同的文件名,就能访问到相同的管道文件。两个进程通过open分别以读和写打开文件,利用write和read就能完成进程间通信,也不需要血缘关系。

需要注意的是,文件名只是用来标识唯一性,数据的传输更匿名管道一样,完全是内存级的

如何创建命名管道

方法一:系统指令 mkfifo

方法二:系统调用 mkfifo(const char* 文件名,mode_t 文件权限)

成功返回0,失败返回-1(包括文件已经存在的情况),并设置好退出码。

如何使用(代码案例)

用C/C++代码编译实现 client进程 和 server进程的通信案例 :

1.client 进程从标准输入按行读取信息

2.通过管道传入到server进程中

3.由server进程读取并输出到标准输出流。

思路

1.创建 client.c server.c myfifo.hpp 在头文件中定义命名管道的路径

2.client 和 server 都先调用mkfifo。若返回-1根据errno判断是否存在。若errno不为-1则终止进程返回退出码

3.client 调用open 以只写的方式打开,server以只写的方式打开管道文件

4.client调用write server调用read 完成通信

实现

头文件: myfifo.hpp

#pragma once
#include<assert.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/fcntl.h>
#include<errno.h>
#include<stdio.h>
//文件路径 隐藏文件
#define fifo_path "./.myfifo"
#define fifo_mode 0666
//缓冲区大小
#define buffer_size 128

源文件:client.c server.c

client.c:

#include"myfifo.hpp"
int main(){//创建命名管道int mkfifo_ret=mkfifo(fifo_path,fifo_mode);//判断是否存在if(mkfifo_ret==-1&&errno!=EEXIST)return errno;//打开管道 只写int myfifo_fd= open(fifo_path,O_WRONLY);char client_buffer[buffer_size];while(1){//从标准输入读取数据printf("请输入:> ");fflush(stdout);ssize_t read_ret=read(0,client_buffer,buffer_size-1);//保证安全性assert(read_ret<buffer_size);client_buffer[read_ret]=0;//像管道写入write(myfifo_fd,client_buffer,read_ret+1);if(strcmp(client_buffer,"_exit\n")==0)break;}//关闭写端 server会读取到EOFclose (myfifo_fd);return 0;
}

server.c

#include"myfifo.hpp"
int main(){//创建命名管道int mkfifo_ret=mkfifo(fifo_path,fifo_mode);//判断是否存在if(mkfifo_ret==-1&&errno!=EEXIST)return errno;//打开管道 只读int myfifo_fd= open(fifo_path,O_RDONLY);char server_buffer[buffer_size];//从管道接收数据while(1){ssize_t read_ret=read(myfifo_fd,server_buffer,buffer_size-1);if(read_ret==0)break;//保证安全性assert(read_ret<=buffer_size);//输出到标准输出printf("服务器收到:> %s",server_buffer);}close(myfifo_fd);return 0;
}

运行效果

Linux系统中的管道通信相关推荐

  1. linux管道命令详解,Linux系统中的管道命令的用法详解

    Linux系统中管道命令是linux系统的一个强大之处.下面由学习啦小编为大家整理了Linux系统中的管道命令的用法详解的相关知识,希望对大家有帮助! Linux系统中的管道命令的用法详解 管道命令操 ...

  2. 在Linux系统中管道线竖杠‘|’

    在Linux系统中管道线是由竖杠(|)隔开的若干个命令组成的序列,在管道线中,每个命令运行时都有一个独立的进程.前一个命令的输出正是下一个命令的输入.而管道线中有一类命令也称作"过滤器&qu ...

  3. Linux系统中的函数

    Linux系统中的函数: 一.进程控制 fork 创建一个新进程 clone 按指定条件创建子进程 execve 运行可执行文件 exit 中止进程 _exit 立即中止当前进程 getdtables ...

  4. Linux内核中无名管道pipe和有名管道fifo的分析

    1.管道(pipe) 管道是进程间通信的主要手段之一.一个管道实际上就是个只存在于内存中的文件,对这个文件的操作要通过两个已经打开文件进行,它们分别代表管道的两端.管道是一种特殊的文件,它不属于某一种 ...

  5. linux系统中文件的几种类型

    Linux系统是以文件的形式来进行管理的.Linux文件类型常见的有:普通文件.目录.字符设备文件.块设备文件.符号链接文件等,如果想了解这方面知识的弟兄,就进来了解了解. Linux系统不同于win ...

  6. Linux系统中消息队列,共享内存、信号和线程的基本操作使用方法

    Linux系统中消息队列,共享内存.信号和线程高级操作 第十一章 消息队列 10.1消息队列定义 10.2 消息队列特点 10.3 key值 10.4 创建消息队列 10.4.1 发送消息 10.4. ...

  7. linux有名管道数据异常,Linux系统编程—有名管道

    ▋****1. 管道的概念 管道,又名「无名管理」,或「匿名管道」,管道是一种非常基本,也是使用非常频繁的IPC方式. 1.1 管道本质 管道的本质也是一种文件,不过是伪文件,实际上是一块内核缓冲区, ...

  8. linux系统中的日志管理

    Linux系统中的日志管理 1 实验环境 2 journald日志服务 2.1 journalctl命令的用法 2.2 用journald服务永久存放日志 3 rsyslog日志服务 3.1 自定义日 ...

  9. linux系统中的文件传输

    Linux系统中的文件传输 1 实验环境 2 scp命令 3 rsync命令 3.1 rsync和scp命令对比 3.2 rsync命令用法 4 文件的归档压缩 4.1 文件归档 4.2 文件压缩 4 ...

最新文章

  1. ffmpeg rtmp 不清晰_知识储备:理解RTMP、HttpFlv和HLS的正确姿势
  2. 用户姓名保护python_Python操作LDAP,对用户进行认证(验证用户名以及密码)
  3. 简单实用的铁道部12306.cn网站自动化登录
  4. dot-files/directories 点开头的文件或文件夹(windows/linux)
  5. Error:Could not find common.jar (android.arch.core:common:1.0.0)
  6. Springboot未登录请求拦截器实现
  7. 今天第一次来这里开博,大家多多指教
  8. PDM系统与PLM系统
  9. 精通 CSS+DIV 网页样式与布局 158
  10. 第一次滑雪小记——杭州临安大明山滑雪场
  11. 锐捷交换机密码恢复操作
  12. 基于BoF算法的图像分类
  13. 浅谈大型互联网的企业入/侵及防护策略
  14. 小弟为共享软件作者制作的管理软件注册的动态链接库 (转)
  15. 为什么很多人不喜欢做程序员?甚至讨厌程序员?
  16. 具体分析contrex-A9的汇编代码__switch_to(进程切换)
  17. 【安卓】——Autofill Framework(自动填写)用法详解
  18. spoolsv出错,无法使用打印服务的解决办法
  19. 仓库管理(库存系统模块)
  20. Android辅助功能(Accessibility)简介

热门文章

  1. 使用PowerDesigner逆向工程生成pdm文件(超全)
  2. 数学故事在小学数学课堂教学中的应用研究
  3. pytorch安装教程 GPU版本
  4. DouPHP模块化企业网站管理系统源码 v1.6
  5. Top 10 顶级项目管理工具
  6. 结合脚本跳过网盘限速,带宽拉满
  7. 商城后台管理系统学习日志-02
  8. hadoop slaves
  9. execjs安装及相关问题解决
  10. linux修改时间写入cmos,解析Linux操作系统修改时间