进程间通信

前言

进程具有独立性,进程想要通信其实是有难度的,与独立性相违背。进程通信的本质是让不同的进程看到同一份资源。

为什么要进程之间互相通信:数据交互,控制,通知等目标。

进程通信标准

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张图片

理解管道:总结管道的特点。

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["<

 

你可能感兴趣的:(Linux,linux)