0


Linux详解 --- 进程间通信1 (匿名管道与命名管道)

文章目录

在这里插入图片描述
受排版的限制,上面的思维导图显示的不是很完整。下面是思维导图源文件的获取方式:

思维导图获取

提取码: diid


问题:进程间通信是什么?
 进程间通信就是 进程和进程 之间进行通信。
问题:进程间通信的目的?(为什么要有进程间通信)
数据传输:一个进程需要将它的数据发送给另一个进程
资源共享:多个进程之间共享同样的资源
通知事件:一个进程需要向另一个或一组进程发送消息,通知它们发生了某种事件(如进程终止时会去通知父进程)
进程控制:有些进程希望完全控制另一个进程的执行,此时控制进程希望能够拦住另一个进程的所有陷入和异常,并能够及时知道它的状态改变

问题:进程间通信的分类?
 管道:匿名管道pipe、命名管道
 System V IPC:System V 消息队列、System V 共享内存、System V 信号量
 POSIX IPC:消息队列、共享内存、信号量、互斥量、条件变量、读写锁
问题:进程间通信的本质是什么?
 进程间通信的本质就是让不同的进程看到同一份资源

问题:怎么做到进程间通信?
在这里插入图片描述

ps: 由于进程运行时具有独立性,因此进程间通信时,一般要借助第三方(OS)资源 #OS要提供一段内存区域,该区域能被双方进程看到
 通信的本质就是“数据的拷贝”

匿名管道pipe

匿名管道的使用

intpipe(int fd[2]);

参数:
 fd:文件描述符数组,其中fd[0]代表read读端;fd[1]代表write写端;
返回值:
 成功返回0;失败返回错误代码

演示

//父进程通过管道给子进程发消息#include<iostream>#include<unistd.h>#include<sys/wait.h>#include<sys/types.h>#include<cstring>usingnamespace std;intmain(){int fd[2];pipe(fd);//创建匿名管道
  pid_t id =fork();if(id ==0){//子进程close(fd[1]);//关闭写端    char buffer[128];
    ssize_t num =read(fd[0], buffer,sizeof(buffer));    
    buffer[num]='\0';//从文件中读取的字符串并不是以'\0'为结尾的
    cout << buffer;}else{//父进程    close(fd[0]);//关闭读端    constchar* buffer ="this is father porcess!\n";write(fd[1], buffer,strlen(buffer));wait(NULL);}return0;}

匿名管道的原理

在这里插入图片描述
 父进程先创建一个匿名管道,然后再创建子进程。在子进程创建的时候,子进程会拷贝父进程的task_struct和files_struct结构体,而他们的files_struct结构体中的文件描述符指向了同一个文件,这样子进程就能看到父进程所创建的匿名管道了。
Tip:
 管道虽然使用的是文件的方案,其实OS并不会把数据刷新到磁盘当中 (匿名和命名都是),因为刷新到磁盘的话,会降低效率(有IO参与,效率肯定会下降)。*//刷新到磁盘也没有意义,2个进程只是借助文件实现通信,所以并不需要刷新到磁盘当中*

父子进程通过匿名管道通信的过程

在这里插入图片描述
 首先,父进程先使用pipe函数创建一个管道,一个进程在创建管道的时候,默认是同时打开读端fd[0]和写端fd[1]的

在这里插入图片描述
 父进程调用fork函数,子进程在被创建时会拷贝父进程的task_struct和files_struct结构体,而在files_struct中有2个文件描述符已经指向了一个匿名管道,所以子进程也能看到这个管道。

在这里插入图片描述
 为了实现父子间通过管道进行通信,必须让其中1个关闭读端,另一个关闭写端。

管道的特点

  • 管道只能进行单向通信
  • 管道是半双工通信 (数据在同一时刻只能向1个方向流动,想要进行双向通信需要建立2个管道)
  • 管道的内部提供了互斥与同步的机制
  • 管道的生命周期跟随进程,一般情况下,进程退出,管道就会被释放
  • 匿名管道适合具有血缘关系的进程进行通信 (父子进程、兄弟进程)
  • 管道提供流式服务

这里大概解释一下管道特点中的个别几点:
问题:什么是半双工通信?什么是全双工通信?
 全双工:在同一时刻,发送数据 和 接收数据 能同时进行 #同一时刻能双向
 半双工:在同一时刻,只能进行发送 或 接收      #同一时刻只能单向

问题:什么是同步与互斥机制?
 这个概念我将会放在多线程博客当中去讲解,这里就大概的介绍一下。互斥就是同一时刻只能有一个进程/线程正在使用临界资源,同步就是在确保了临界资源安全的前提下,以特定的顺序让进程/线程去访问临界资源。

管道的读写规则

  1. 正常进行写和读时,当write写完,关闭该进程的写端fd[1]。此时,读端read函数的返回值为0
  2. 写端还没写完,读端就关闭了,此时写端进程会被OS杀掉 (收到SIGPIPE信号)
  3. 不write,一直read,由于写端接收不到数据,就会出于阻塞状态
  4. 不read,一直write,当管道满了之后,写端就会进入阻塞状态

总结:
读管道:
 1. 管道中有数据,read返回实际读到的字节数
 2. 管道中无数据:
  (1) 管道写端全部被关闭,read返回0
  (2) 写端没有全部被关闭,在read处阻塞等待
写管道:
 1. 管道读端全部被关闭,进程异常终止 (OS发送SIGPIPE信号给写端)
 2. 读端没有全部被关闭:
  (1) 管道未满时,write继续写入数据
  (2) 管道写满了,write阻塞

管道的大小

在这里插入图片描述

命名管道

 由于匿名管道只能作用于具有共同祖先的进程间通信,然而大部分的进程实际上都是不相关的,所以我们引入了命名管道,命名管道可以让完全不相干的2个进程进行通信。命名管道虽然是打开一个目录下的文件,但是实际上也是在内存当中进行操作,并不会刷新到磁盘当中。

命名管道的使用

命令行中创建:

mkfifo filename

程序中创建:

intmkfifo(constchar* filename,mode_t mode);//包含于<sys/types.h>  <sys/stat.h>

参数:
 filename:创建出来的命名管道的名称
 mode:命名管道权限的设置

演示

//实现client端给server端发消息//server.cpp#include<iostream>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>#include<string.h>usingnamespace std;#defineFILE_NAME"myfifo"intmain(){mkfifo(FILE_NAME,0666);//mkfifo的第一参数是文件名,它会给你创建个以这个为名字的命名管道    int fd =open(FILE_NAME, O_RDONLY);char buffer[128];while(1){
    ssize_t num =read(fd, buffer,sizeof(buffer));
    buffer[s]=0;//下面的代码是server端接收client端的字符串的消息if(num <0){
       cout <<"read error!"<< endl;break;}elseif(num ==0){         
       cout <<"End of File!"<< endl;break;}else{    
       cout << buffer << endl;}}return0;}//client.cpp#include<iostream>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>#include<string.h>usingnamespace std;#defineFILE_NAME"myfifo"intmain(){int fd =open(FILE_NAME, O_WRONLY);constchar* msg ="hello server, this is client";int cnt =5;while(cnt--){write(fd, msg,strlen(msg));sleep(1);}sleep(100);return0;}

匿名管道 VS 命名管道

匿名管道与命名管道的唯一区别就在于 ----- 管道的打开方式不同
 匿名管道由pipe函数创建,并在创建时打开
 命名管道由mkfifo函数创建,打开需要使用open

管道的应用

  1. 可以实现进程之间互相传递消息(字符串)
  2. 可以让一个进程帮助另一个进程执行指令 (另一个进程接收消息后,使用execl函数执行指令)
  3. 可以让另一个进程帮助进行计算
  4. 可以实现“文件的拷贝”   //文件的上传、下载,实际上都是文件的拷贝
标签: linux 运维 服务器

本文转载自: https://blog.csdn.net/weixin_51696091/article/details/121944259
版权归原作者 wuqiongjin 所有, 如有侵权,请联系我们删除。

“Linux详解 --- 进程间通信1 (匿名管道与命名管道)”的评论:

还没有评论