当前位置: 首页 > article >正文

进程间通信——管道

1.进程为什么要通信

进程之间需要摸某种协同,协同的条件是通信,而通信也是有类别的,有通知就绪的,传递数据的,控制相关信息等等,

2.进程之间如何通信

事实上,进程是具有独立性的,那么进程通信的前提是让不同的进程看到操作系统中同一块资源

进程通信的常见方式 system V,是一种商业常用通信,而我们今天学习的是管道通信,

3.管道

当我们打开一个文件时,会获得这个文件的fd,当我们以不同的方式打开同一个文件,我们会获得两个fd,但是都指向同一个文件

我们可以使用pipe()系统来调用管道,一旦管道被创建,一个进程就可以在fd[1]上写数据,另一个进程在fd[0]上读数据,

#include<iostream>
#include<string>
#include<cerrno>
#include<cstring>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>

const int size=1024;

std::string GetOtherMmessage()
{
    static int cnt=0;
    std::string messageid=std::to_string(cnt);
    cnt++;
    pid_t self_id=getpid();
    std::string stringid=std::to_string(self_id);
    std::string message="messiageid:";
    message+=messageid;
    message+=" my pid is:";
    message+=stringid;
    return message;

}
//子进程进行写入
void SubProceeeWrite(int wfd)
{
    int pipesize=0;
    std::string message=" father,I am Process ! ";
    while(true)
    {
        std::string info=message+GetOtherMmessage();
        write(wfd,info.c_str(),info.size());
    }
    std::cout<<"child quit . . . "<<std::endl;


}

void FatherProcessRead(int rfd)
{
    char inbuffer[size];
    while(true)
    {
        ssize_t n=read(rfd,inbuffer,sizeof(inbuffer)-1);
        if(n>0)
        {
            inbuffer[n]=0;//在数组的最后一个元素的在一个设置为\0
            std::cout<<inbuffer<<std::endl;
        }
        else if(n==0)
        {
            //read返回的是0,表示写端直接关闭了,我们读到了文件的结尾
            std::cout<<"client quit ,father get return val :"<<n<<"father quit too !"<<std::endl;

        }
        else if(n<0)
        {
            std::cerr<<"read error"<<std::endl;
            break;
        }

    }

}

int main()
{
    //1.创建管道
    int pipefd[2];

    int n=pipe(pipefd);//输出型参数  rfd  wfd
    if(n!=0)
    {
        //创建失败
        std::cout<<"errno: "<<errno<<" "<<"errstring: "<<strerror(errno) <<std::endl;
    }
    std::cout<<"pipefd[0]: "<<pipefd[0]<<" pipefd[1]: "<<pipefd[1]<<std::endl;
    //2.创建子进程
    pid_t id=fork();
    if(id==0)
    {
        //子进程
        close(pipefd[0]);//关闭读进程
        SubProceeeWrite(pipefd[1]);
        close(pipefd[1]);
        exit(0);

    }
    close(pipefd[1]);//关闭写进程
    FatherProcessRead(pipefd[0]);
    close(pipefd[0]);


    int status=0;
    pid_t rid=waitpid(id,&status,0);
    if(rid>0)
    {
        std::cout << "wait child process done, exit sig: " << (status&0x7f) << std::endl;
        std::cout << "wait child process done, exit code(ign): " << ((status>>8)&0xFF) << std::endl;
    }


    return 0;
}

这是一个简单的子进程写数据,父进程读数据,

对于父进程,我们要关闭他的写进程,因为父进程只能读取数据,对于子进程,我们要关闭读进程,因为子进程只能写入数据

管道的四种情况

  • 如果管道内部是空的&&wfd没有关闭,读取条件不具备,读进程会被阻塞,---wait ->读取条件具备<-写入数据
  • 管道被写满&&rfd不读且没有关闭,写进程会被阻塞(管道被写满,写进程不具备)---wait ->写进程具备<-读取数据
  • 管道一直在读&&写端关闭了wfd,读端read返回值会读到0,表示读到了文件结尾
  • rfd直接关闭,写端wfd一直在写入?不合理,操作系统会直接使用13号信号关掉wfd,相当于进程出现了异常

管道的5种特征

  • 匿名管道:只用来进行具有血缘关系的进程之间进行通信吗,通常在父子进程之间
  • 管道内部:自带进程之间的同步机制,多执行流执行代码时具有顺序性
  • 管道文件的生命周期是随进程的
  • 管道文件在通信时,是面向字节流的,比如说,write和read的次数不一定是一一匹配的
  • 管道的通信模式是半双工模式,半双工模式允许数据在两个方向上传输,但是不允许同时进行双向通信,在这种模式下,一次只能向一个方向传输数据


http://www.kler.cn/news/358011.html

相关文章:

  • ts 中 type 和 interface 的区别
  • 2024CSP-J模拟赛9————S12678
  • Guava防击穿回源-异步防击穿
  • Vue快速嵌入百度地图,避坑提效指南
  • Git 可视化的实现:提升版本控制体验的利器
  • 【安装依赖】npm i
  • 【高等数学】多元微分学 (一)
  • 基于SpringBoot+Vue+uniapp的C语言在线评测系统的详细设计和实现
  • ArkTS 中时间格式化
  • QT中的D指针和Q指针
  • 驱动开发系列22 - 调试 mesa 中的 glDrawArrays 的实现
  • 芯科科技最新第三代无线开发平台全面提升人工智能和无线连接功能!
  • http大数据post与put请求
  • C++高阶:红黑树实现
  • 【Java SE 】继承 与 多态 详解
  • leetcode389:赎金信
  • 效果不错的论文介绍:Im2Flow2Act:-跨领域机器人操控技术
  • 101 - Lecture 9
  • Python 多线程学习与使用
  • 《计算机视觉》—— 基于 dlib 库的方法将两张人脸图片进行换脸