前言
进程具有独立性,进程想要通信其实是有难度的,与独立性相违背。进程通信的本质是让不同的进程看到同一份资源。
为什么要进程之间互相通信:数据交互,控制,通知等目标。
linux文件系统原生的:管道 匿名管道
systeam V :多进程——单机通信
--共享内存
--消息队列(不常用)
--信号量(基本没用)
posix:多线程——网络通信
一个进程创建子进程,他的struct file问价描述符表要不要拷贝给子进程?必须要拷贝,不然子进程看不到文件。进程指向的一堆文件需要给子进程拷贝吗?不要。这时候新打开的文件,通过文件描述符表就看到了同一份文件。这个文件就叫管道。单向通信
单进程无法使用并发能力,更加无法实现多进程协同。传输数据,同步执行,消息通知。而进程间通信不是目的而是手段。
进程间通信背景理解。
1.进程是具有独立性的,虚拟地址空间+页表保证进程的独立性
2.进行通信的成本很好!!!因为天然的进程具有独立性。
进程间通信的前提:首先需要看到同一块特定的“内存”组织结构。
所谓的进程看到同一个“内存”,属于哪一个进程呢?不能属于任何一个进程,更应该强调共享
当父子进程都看到同一份资源的时候,就形成了管道,管道是需要规定方向。父进程写入就不能读取。子进程读取就不能写入。通过这样子的形式就形成了管道。这其中是不需要和磁盘打交道,是纯内存中完成的,不会设计磁盘。这样子效率是最高的。
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
//1.创建管道
//include
// 功能:创建一无名管道
// 原型
// int pipe(int fd[2]);
// 参数
// fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端 输出型参数
// 返回值:成功返回0,失败返回错误代码
int pipefd[2]={0};
int n= pipe(pipefd);//完成了管道的创建
assert(n!=-1);//debug模式下assert是无效的,会报错定义但是没有被使用。
(void)n;
#ifdef DEUBG
cout<<"pipe[0]:"<0)
{
buffer[s]=0;
cout<<"child get 1 message ["<
一个简单的demo程序实现父进程发消息,子进程读取。
运行结果如下
理解管道:总结管道的特点。
1.管道是用来具有血缘关系的进程之间通信的。——常用于父子通信
2.管道是一个文件,显示器也是一个文件,父子同时往显示器打印的时候,会发生互相等待吗?缺乏访问控制。但是管道提供了访问控制。
3.管道提供的是面向字节流式的通信服务
4.管道是基于文件的,文件的生命周期是随进程的,管道的生命周期是随进程的。
5.管道是是单向通信的,是基于半双工的一种特殊情况。
源文件
#include
#include
#include
#include
#include
#include
#include
#include"Task.hpp"
#define PROCESS_NUM 5
using namespace std;
int waitcomend(int waitfd,bool &quit)
{
uint32_t commend =0;//4个字节
ssize_t s =read(waitfd,&commend,sizeof(commend));
if(s==0)
{
quit=true;
return -1;
}
//必须读4字节,不是则对方发错了
assert(s==sizeof(uint32_t));
return commend;
}
void sendAndWakeup(pid_t who,int fd,uint32_t command)
{
write(fd,&command,sizeof command);
cout<<"callbacks process"<> slots;
for(int i=0;i=0&&commend(id,pipfp[1]));
}
//走完循环之后,此刻父进程有一批进程
//开始任务,父进程派发
srand((unsigned long)time(nullptr)^getpid()^223333333);
while(true)
{
int select;
int command=rand()%Handlesize();
cout<<"####################################"<>select;
sleep(1);
if(select==1)
{
showHandl();
}
else if(select==2)
{
cout<<"enter your commment";
cin>> command;
//选择进程
int procId = rand()%slots.size();
sendAndWakeup(slots[procId].first,slots[procId].second,command);//唤醒子进程干活
}
else
{
cout<<"输入错误请重试"<>select;
}
//结束之后需要清空字符缓冲区,不然会陷入无限循环之中。
char buff[1024];
cin.clear();
cin.ignore();
}
//关闭fd,结束所有进程
//所有子进程会退出
for(const auto&slot:slots)
{
close(slot.second);
}
for(const auto&slot:slots)
{
waitpid(slot.first,nullptr,0);
}
return 0;
}
头文件
#pragma once
#include
#include
#include
#include
#include
using func = std::function;
std::vector callbacks;
std::unordered_map desc;
void readMYsql()
{
std::cout<<"progress["<