进程间通信
- 一.基本概念
- 二.简单的通信-管道
- 1.建立通信信道
- 2.通信接口
一.基本概念
是什么
两个或多个进程实现数据层面的交互。
因为进程独立性的存在,导致进程间的通信成本比较高。
为什么
因为我们有多进程协同的需求。
怎么办
a.进程间通信的本质:必须让不同的进程看到同一份"资源"。
b.“资源”?特定形式的内存空间。
c.这个"资源"谁提供?一般是操作系统。
d.我们进程访问这个空间,进行通信,本质就是访问操作系统!进程代表的就是用户,“资源”从创建,使用(一般),释放―–需要系统调用接口!一般操作系统会有一个独立的通信模块-隶属于文件系统-IPC通信模块。
二.简单的通信-管道
管道是Unix中最古老的进程间通信的形式。 我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”。
1.建立通信信道
管道是一个文件-内存级文件。
1.管道文件与一般文件不同,一般文件存在于磁盘里,管道文件存在于内存里。也就是说管道文件不需要将修改内容从内存刷新缓冲区到磁盘,这是它的特点。
2.一般管道文件只能具有血缘关系的进程间通信。因为只有具有血缘关系才能继承同一份files_struct。
3.一个父进程在创建管道文件时不能只是以读或者写的方式,必须两者都有。操作系统会把这个文件打开两次,分别用来读和写。但操作系统实际上只想让两个进程进行单向通信,因为如果一个进程又在读又在写,很容易会造成数据混淆,为了避免麻烦,规定只能一个进程写,另一个进程读。
这个文件不需要有名字,inode…让操作系统区分。所以这种文件也被称为匿名管道。
2.通信接口
pipe的作用就是帮助我们以读和写打开文件。它的参数是一个输出型参数,它会把分别以读和写的文件的文件描述符通过参数带出,供用户使用。pipefd[0]一般用于读,pipefd[1]一般用于写。
模拟
makefile
testPipe:TestPipe.cppg++ -o $@ $^ -std=c++11
.PHONY:clean
clean:rm -f testPipe
TestPipe.cpp(一个简单的通信,子进程向父进程里写信息)
#include<stdio.h>
#include<iostream>
#include<unistd.h>
#include<stdlib.h>
#include<string>
#include<cstdio>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>using namespace std;
#define N 2
#define NUM 1024//子进程
void Write(int wfd)
{//任意写几个数据测试string s="hello,i am a child";pid_t id=getpid();int num=0;char buffer[NUM];while(1){snprintf(buffer,sizeof(buffer),"%s-%d-%d\n",s.c_str(),id,num++);//将数据都变成字符存在buffer里//把数据写入管道write(wfd,buffer,strlen(buffer));sleep(1);}
}//父进程
void Read(int rfd)
{char buffer[NUM]={0};while(1){ssize_t n=read(rfd,buffer,sizeof(buffer));if(n>0){cout<<buffer<<endl;}else if(n==0) break;}}int main()
{int pipefd[N]={0};//创建管道int n=pipe(pipefd);//判断是否创建成功if(n<0) return 1;//创建子进程pid_t id=fork();if(id<0) return 2;if(id==0){//子进程//关闭读功能close(pipefd[0]);//IPC codeWrite(pipefd[1]);//退出close(pipefd[1]);exit(0);}//父进程//关闭写功能close(pipefd[1]);//IPC codeRead(pipefd[0]);//退出//回收子进程pid_t rid=waitpid(id,nullptr,0);if(rid<0) return 3;close(pipefd[0]);return 0;
}
管道的4中情况:
1.读写端正常,管道如果为空,读端就要阻塞 2读写端正常,管道如果被写满,写端就要阻塞 3.读端正常读,写端关闭,读端就会读到0,表明读到了文件(pipe)结尾,不会被阻塞
4,写端正常写入,读端被关闭。操作系统就要杀掉正在写入的进程。如何干掉?通过信号杀掉。
管道的特征:
1.具有血缘关系的进程进行进程间通信。
2.管道只能单向通信。
3.父子进程是会进程协同的,同步与互斥的—保护管道文件的数据安全 4.管道是面向字节流的。
5.管道是基于文件的,而文件的生命周期是随进程的!