【Linux下】进程间通信

文章目录管道 命名管道 **管道实现进程间通信的本质**匿名管道vs命名管道V 内存空间特点即对比管道相关概念补充
进程间通信 进程间通信的目的
一个进程就是一个执行流,就像工厂的员工一样,一个人就是一个生产力,肯定是需要交互的,而进程间的交互可能就是进程通信,可能是因为数据传输需要,也可能是一个进程控制另一个进程…
主要目的有以下4种:
进程间通信的分类
管道
V IPC
POSIX IPC
进程间通信的本质
我们知道进程是具有独立性的,例如:父子进程之间共用一个全局变量,实际上进行修改时,父子进程之间会发生写时拷贝 。
而进程间如果要实现通信,就得先让不同的进程看到同一份资源,俩进程看到资源肯定不是单独一个进程所拥有的,而是被所有进程所共享的,所以这个资源一定不可能由进程自身进行提供,那应该由谁提供呢?当然是os!而且所谓的资源实际上就是一段内存
因为提供的方式不一样;就形成了不同的通信方式:文件形式(管道),链表形式(消息队列),原生内存(共享内存)
管道 初识管道
什么是管道?
例:
例如我们在命令行执行 who | wc -l 实际上就是在使用管道
匿名管道
特点:
1.单向传输的管道
2.管道是面向字节流的(调用系统接口 open read write)
3.父子进程间血缘依赖关系,即匿名管道其实是含有继承关系的进程之间通信的俩个文件,读端文件 写端文件)
4.管道的生命周期是随进程的
5.管道自带协同机制(同步和互斥),原子性写入
创建匿名管道
int pipe(int pipdfd[2])
作用:创建并打开匿名管道
参数:fd文件描述符数组 里面装到分别是父子进程读写俩端的文件
返回值:成功即返回0 失败返回-1
如图中所描述:
[0]:读端的文件的fd
[1]:写端的文件的fd
灵活记忆:0就像嘴一样,负责吃东西,所以是读取,1就像一样,用来写字,所以是写端
而实际上双端进行通信时,因为管道是面向字节流的,俩方只需要使用read write对管道进行读取即可
调用pipe的实质是,进程打开管道文件,将读写端的 file*填入进程的[]中去
例:父子通信:父进程做读端,子进程做写端
实现方法:
父进程打开匿名管道文件后,再fork子进程,而后父进程关闭写端([1]),子进程关闭读端([0])
注: 一定是在父进程打开匿名管道文件后,再fork子进程,因为需要俩个进程看到的是同一份资源,而如果我们先fork之后再创建并打开匿名管道文件,就不能保证父子进程看到的是同一份资源 。
逻辑图理解:
os视角下的匿名管道通信:
进行匿名管道操作的代码:
#include #include #include #include #include int main(){int pipe_id[2];int ret=pipe(pipe_id);//打开管道文件if(ret){perror("pipe");return 1;}//pipe_id[0]为管道读入端 pipe_id[1]为管道写入端printf("pipe_id[0]:%d pipe_id[1]:%d \n",pipe_id[0],pipe_id[1]);int id =fork();if(id<0){perror("fork");return 2;}else if(id ==0){//child 进行写操作//关闭管道读文件close(pipe_id[0]);int count=0;while(1){ //sleep(100);//当写端写得满时 读端需要等待 或者是不写char * meg="hellolsh";write(pipe_id[1],meg,strlen(meg));count++;printf("%d\n",count);break;}close(pipe_id[1]);//而当写端退出时,读端read会返回0 表示已经读到文件末尾了 即写文件已经退出了exit(0);}else{//fatherclose(pipe_id[1]);while(1){sleep(1);char buffer[1024*2+1]={0};//当写端太快时,会停下来等一下读端 。或者是读端不读时,写端也会停下来等读端ssize_t s=read(pipe_id[0],buffer,sizeof(buffer));buffer[s]=0; //将末尾设置为\0if(s==0){printf("child quit\n");break;}else if(s>0){printf("parent get child new:%s\n",buffer);}else{printf("fail \n");}}close(pipe_id[0]);int status=0;int pid=waitpid(-1,&status,0);if(pid>0){printf("exit code:%d exit sig:%d \n",(status>>8)&0xFF,status&0x7F);//但读端退出时,写端还在写入,os 会像写端发送13信号,将其停下来}}return 0;}