高编:进程间通信 IPC interprocess communicate

news2024/10/6 2:23:31

一、进程间三大类通信

1、古老的通信方式

        无名管道  有名管道  信号

2、IPC对象通信 system v(5)    BSD     suse fedora   kernel.org

        消息队列(用的相对少,这里不讨论)
        共享内存
        信号量集(进程间做互斥与同步semaphore)

3、socket通信

        网络通信

二、管道

无名管道 ===》pipe ==》只能给有亲缘关系进程通信
有名管道 ===》fifo ==》可以给任意单机进程通信

1.管道的特性

1)管道是 半双工的工作模式
2)所有的管道都是特殊的文件不支持定位操作。lseek->> fd  fseek ->>FILE* 
3)管道是特殊文件,读写使用文件IOfgets,fread,fgetc(标准IO,文本文件常用)
    open,read,write,close;(文件IO,一般用这个,二进制文件常用)
  

 2.无名管道使用注意事项 

1)读端存在,一直向管道中去写(写得太快),超过64k,会阻塞

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
    int pipefd[2]={0};
    int ret = pipe(pipefd);
    if(-1 == ret)
    {
        perror("pipe");
        exit(1);
    }

    pid_t pid = fork();
    if(pid>0)
    {
        char buf[1024]={0};
        close(pipefd[0]);
        memset(buf,'a',1024);
        int i = 0 ;
        for(i=0;i<65;i++)
        {
            write(pipefd[1],buf,sizeof(buf));
            printf("i is %d\n",i);
        }
    }
    else if(0 == pid)
    {
        close(pipefd[1]);
        char buf[100]={0};
        while(1)sleep(1);
    }
    else 
    {
        perror("fork");
        exit(1);
    }
    return 0;
}


2)写端存在,读管道,(写得慢,读得快)如果管道为空的话,会阻塞

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{  
    int pipefd[2]={0};
    int ret = pipe(pipefd);
    if(-1 == ret)
    {
        perror("pipe");
        exit(1);
    }

    pid_t pid = fork();
    if(pid>0)
    {
        char buf[]="capper";
        close(pipefd[0]);
        sleep(3);
        write(pipefd[1],buf,strlen(buf));
    }
    else if(0 == pid)
    {
        close(pipefd[1]);
        char buf[100]={0};
        read(pipefd[0],buf,sizeof(buf));
        printf("pipe %s\n",buf);
    }
    else 
    {
        perror("fork");
        exit(1);
    }
    return 0;
}

阻塞3s后,才打印出结果


3)管道破裂读端关闭写管道出错,程序结束。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
    int pipefd[2]={0};
    int ret = pipe(pipefd);
    if(-1 == ret)
    {
        perror("pipe");
        exit(1);
    }

    pid_t pid = fork();
    if(pid>0)
    {
        char buf[]="hello,world";
        close(pipefd[0]);
        sleep(3);
        // 管道破裂 gdb  跟踪
        write(pipefd[1],buf,strlen(buf));
        printf("aaaa\n");
    }
    else if(0 == pid)
    {
        close(pipefd[1]);
        close(pipefd[0]);
    }
    else 
    {
        perror("fork");
        exit(1);
    }
    return 0;
}

管道破裂,程序退出 


4)写端关闭,如果管道没有内容,读端返回0,read 0 ;

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
    int pipefd[2]={0};
    int ret = pipe(pipefd);
    if(-1 == ret)
    {
        perror("pipe");
        exit(1);
    }

    pid_t pid = fork();
    if(pid>0)
    {
        char buf[]="hello,world";
        close(pipefd[0]);
        write(pipefd[1],buf,strlen(buf));
        write(pipefd[1],buf,strlen(buf));
        close(pipefd[1]);
    }
    else if(0 == pid)
    {
        close(pipefd[1]);
            char buf[5]={0};
        while(1)
        {
            //memset(buf,0,5);
            bzero(buf,sizeof(buf));
            int rd_ret = read(pipefd[0],buf,sizeof(buf)-1);
            if(rd_ret<=0)
            {
                break;
            }
            printf("pipe %s\n",buf);
        }
    }
    else 
    {
        perror("fork");
        exit(1);
    }
    return 0;
}

3.无名管道使用框架

创建管道 ==》读写管道 ==》关闭管道

1.无名管道 ===》管道的特例 ===>pipe函数
特性:
1.1  亲缘关系进程使用
1.2  有固定的读写端


2.3.1创建并打开管道

pipe函数
#include <unistd.h>
int pipe(int pipefd[2]);
功能:创建并打开一个无名管道
参数:pipefd[0] ==>无名管道的固定
           pipefd[1] ==>无名管道的固定
返回值:成功  0
              失败 -1;

注意事项:
无名管道的架设应该在fork之前进行。
    
无名管道的读写:===》文件IO的读写方式。
  读: read() 
  写: write() 

关闭管道: close();


练习:相当于cp的功能
    设计一个多进程程序,用无名管道完成父子进程间的任意信息:传送,包括数字、字符串等。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
    int pipefd[2]={0};
    int ret = pipe(pipefd);
    if(-1 == ret)
    {
        perror("pipe");
        exit(1);
    }

    pid_t pid = fork();
    if(pid>0)
    {
        close(pipefd[0]);
       int fd =  open("/home/linux/1.png",O_RDONLY);
       if(-1 == fd)
       {
            perror("open");
            exit(1);
       }
       while(1)
       {
            char buf[4096]={0};
            int rd_ret = read(fd,buf,sizeof(buf));
            if(rd_ret<=0)
            {
                break;
            }
            write(pipefd[1],buf,rd_ret);
       }
       close(fd);
       close(pipefd[1]);
    }
    else if(0 == pid)
    {
        close(pipefd[1]);
        int fd = open("2.png",O_WRONLY|O_CREAT|O_TRUNC,0666);
        if(-1==fd)
        {
            perror("open");
            exit(1);
        }
        while(1)
        {
            char buf[1024]={0};
            int rd_ret = read(pipefd[0],buf,sizeof(buf));
            if(rd_ret<=0)
            {
                break;
            }
            write(fd,buf,rd_ret);
        }
        close(fd);
        close(pipefd[0]);
    }
    else 
    {
        perror("fork");
        exit(1);
    }
    return 0;
}

运行结果:将1.png复制为2.png


验证如下问题:
1、父子进程是否都有fd[0] fd[1],如果在单一进程中写fd[1]能否直接从fd[0]中读到。

        可以,写fd[1]可以从fd[0]读

2、管道的数据存储方式是什么样的数据是否一直保留?
        栈, 先进后出
        队列形式存储 读数据 会剪切取走数据 不会保留    <先进先出>

3、管道的数据容量是多少,有没有上限值。
        操作系统的建议值: 512* 8 = 4k
         man 7 pipe
        代码测试实际值:   65536byte= 64k

4、管道的同步效果如何验证?读写同步验证。
     读端关闭能不能写? 不可以 ===>SIGPIPE 异常终止 
     写端关闭能不能读? 可以,取决于pipe有没有内容,===>read返回值为0 不阻塞

        结论:读写端必须同时存在,才能进行管道的读写。

5、固定的读写端是否就不能互换?
     能否写fd[0] 能否读fd[1]?   不可以,是固定读写端。


4.有名管道

有名管道===》fifo ==》有文件名称的管道。文件系统中可见

框架:
    创建有名管道 ==》打开有名管道 ==》读写管道==》关闭管道  ==》卸载有名管道

2.4.1 创建:mkfifo

#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);
功能:在指定的pathname路径+名称下创建一个权限为mode的有名管道文件。
参数:pathname要创建的有名管道路径+名称
          mode  8进制文件权限//0666/0777
返回值:成功 0
              失败  -1;

2.4.2 打开有名管道 open

    注意:该函数使用的时候要注意打开方式,因为管道是半双工模式,所有打开方式直接决定当前进程的读写方式。
    一般只有如下方式:
    int fd-read = open("./fifo",O_RDONLY); ==>fd 是固定读端
    int fd-write = open("./fifo",O_WRONLY); ==>fd 是固定写端
    不能是 O_RDWR 方式打开文件
    不能有 O_CREAT 选项,因为创建管道有指定的mkfifo函数

2.4.3 有名管道的读写: 文件IO

    读: read(fd-read,buff,sizeof(buff));
    写: write(fd-write,buff,sizeof(buff));

2.4.4 关闭管道

close(fd);

2.4.5 卸载有名管道

remove();
int unlink(const char *pathname);
功能:将指定的pathname管道文件卸载,同时从文件系统中删除。
参数: ptahtname 要卸载的有名管道 
返回值:成功  0
              失败  -1


01fifo_w.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, char *argv[])
{
    int ret = mkfifo("myfifo",0666);    
    if(-1 == ret)
    {
        //如果是管道文件已存在错误,让程序继续运行
        if(EEXIST== errno)
        {

        }else 
        {
            perror("mkfifo");
            exit(1);
        }
    }
    //open 会阻塞,等到另一端读段打开,解除阻塞
    int fd = open("myfifo",O_WRONLY);
    if(-1 == fd)
    {
        perror("open");
        exit(1);
    }

    char buf[256]="hello,fifo,test";
    write(fd,buf,strlen(buf));
    close(fd);

    return 0;
}

02fifo_r.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

int main(int argc, char *argv[])
{
    int ret = mkfifo("myfifo",0666);    
    if(-1 == ret)
    {
        //如果是管道文件已存在错误,让程序继续运行
        if(EEXIST== errno)
        {
        
        }else 
        {
            perror("mkfifo");
            exit(1);
        }
    }

    int fd = open("myfifo",O_RDONLY);
    if(-1 == fd)
    {
        perror("open");
        exit(1);
    }

    char buf[256]={0};
    read(fd,buf,sizeof(buf));
    printf("fifo %s\n",buf);
    close(fd);
    //remove("myfifo");

    return 0;
}


1、是否需要同步,以及同步的位置。
        读端关闭 是否可以写,不能写什么原因。
        写端关闭 是否可以读。

        结论:有名管道执行过程过必须有读写端同时存在。
                   如果有一端没有打开,则默认在open函数部分阻塞。

2、有名管道是否能在fork之后的亲缘关系进程中使用。
        结论: 可以在有亲缘关系的进程间使用。
        注意: 启动的次序可能会导致其中一个稍有阻塞。

3、能否手工操作有名管道实现数据的传送。
        读: cat  fifoname
        写: echo "asdfasdf" > fifoname

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1886215.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AD快速导入立创3D模型

在AD绘制PCB时&#xff0c;可以添加3D模型&#xff0c;在绘制完成PCB后就可以导出3D图给结构工程师核对&#xff0c;方便产品的开发。这里介绍一种可以比较快完成3D导入的方式。 一、PyCharm代码 打开PyCharm&#xff0c;在运行本代码时&#xff0c;需要安装第三方包codecs&a…

synchronized用法解析

锁的意义&#xff1a; 比如我跟我老弟要用电脑&#xff0c;我想学java&#xff0c;他想拿电脑打LOL&#xff0c;如果我敲java代码敲的正嗨皮&#xff0c;他突然把电脑抢了过去&#xff0c;代码还没保存&#xff0c;就被他拿去打LOL了&#xff0c;很✓8&#xff0c;那么如何解决…

基于人脸68特征点识别的美颜算法(一) 大眼算法 C++

1、加载一张原图&#xff0c;并识别人脸的68个特征点 cv::Mat img cv::imread("5.jpg");// 人脸68特征点的识别函数vector<Point2f> points_vec dectectFace68(img);// 大眼效果函数Mat dst0 on_BigEye(800, img, points_vec);2、函数 vector<Point2f&g…

BMA580 运动传感器

型号简介 BMA580是博世&#xff08;bosch-sensortec&#xff09;的一款先进的、超小型加速度传感器。具有独特的骨传导语音活动检测功能和先进的功率模式功能&#xff0c;是世界上最小的加速度传感器&#xff08;1.2 x 0.8 x 0.55 mm&#xff09;。它专为紧凑型设备&#xff08…

Query Rewriting for Retrieval-Augmented Large Language Models

文章目录 题目摘要方法实验 题目 检索增强大语言模型的查询重写 论文地址&#xff1a;https://arxiv.org/abs/2305.14283 项目地址&#xff1a;https://github.com/xbmxb/RAG-query-rewriting 摘要 大语言模型&#xff08;LLM&#xff09;在检索--然后阅读&#xff08;retriev…

Hack The Box-Blazorized

总体思路 Blazor JWT->SPN劫持->登录脚本劫持->DCSync 信息收集&端口利用 nmap -sSVC blazorized.htbStarting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-01 02:37 EDT Nmap scan report for blazorized.htb (10.10.11.22) Host is up (0.30s latency). N…

【网络安全】修改Host文件实现域名解析

场景 开发一个网站或者服务&#xff0c;需要在本地测试时&#xff0c;可以将线上的域名指向本地开发环境的IP地址。从而模拟真实环境中的域名访问&#xff0c;方便调试和开发。 步骤 1、以管理员身份打开命令提示符 2、编辑hosts文件&#xff1a; 输入以下命令打开hosts文…

云卓SKYDROID-H12PRO——只有你想不到的,没有我们做不到的

H12PRO采用高通八核处理器&#xff0c;搭载安卓嵌入式系统&#xff0c;采用先进的OFDM技术&#xff0c;和超级协议栈。让图像更加清晰&#xff0c;延迟更低&#xff0c;距离更远&#xff0c;抗干扰性更强&#xff0c;并支持1080P视频传输。支持SIM、数字摄像头、串口、s.bus、网…

SQL注入实战

1、orderBy报错注入 某大学 www.target.com?orderBy1 注入为orderBy注入&#xff0c;将orderby更改为id测试时并不能造成报错回显故不能当注入点 正常状态下 经过测试可知共14列&#xff0c;orderBy15时报错&#xff0c;由于列名可控?orderby$id 这里使用XPath报错注入&a…

放大器的输入电容Cin对放大电路的影响

1、OPA859构成的放大电路的设计 图中OPA859的增益G设定为1.16 &#xff0c;OPA859的增益带宽积GBP 900M , 放大器的带宽BW GBP / Acl 900 / 1.16 775.86M。 图&#xff1a;OPA859放大电路 由于需要在放大电路上加带宽的限制&#xff0c;所以在OPA859放大电路上有个低通限…

Java + MySQL 实现存储完整 Json

Java + MySQL 实现存储完整 Json 一、应用场景二、数据库配置三、后端代码配置1、实体类2、Service 实现类3、xml 文件四、测试1、新增接口2、查询接口3、数据表内容一、应用场景 将前端传过来的 Json 完整存储到 MySQL 中,涉及技术栈为 Java、MyBatis、MySQL。 注意:MySQL…

idea xml ctrl+/ 注释格式不对齐

处理前 处理后 解决办法 取消这两个勾选

LabVIEW代码性能优化

优化LabVIEW代码以提高软件性能是确保系统高效运行的关键。通过分析代码结构、数据管理、并行处理、内存使用和硬件资源的有效利用&#xff0c;我们可以从多个角度提升LabVIEW程序的执行速度和稳定性。 代码结构优化 模块化编程 将复杂的程序分解成多个子VI&#xff0c;每个子V…

Linux系统中交叉编译opencv库

目标&#xff1a;将opencv进行交叉编译&#xff0c;使其能在rk3326板子上运行使用。 环境&#xff1a; ubuntu&#xff1a;18.04 opencv:4.5.4 opencv源码从挂网下载&#xff1a;opencv源码下载地址 交叉编译链&#xff1a;gcc-arm-10.3-linux-gun 一.环境准备 1.交叉编译链我…

论文学习——使用基于多项式拟合的预测算法求解动态多目标问题

论文题目&#xff1a;Solving dynamic multi-objective problems using polynomial fitting-based prediction algorithm 使用基于多项式拟合的预测算法求解动态多目标问题&#xff08;Qingyang Zhang , Xiangyu He,Shengxiang Yang , Yongquan Dong , Hui Song , Shouyong Ji…

shopify后台设置为中文

shopify官网&#xff1a;https://link.juejin.cn/?targethttps%3A%2F%2Fshopify.dev%2F 1、点击右上角头像 2、选择个人资料 3、找到Language设置 开发者 1、创建开发商店 2、 3、点击左侧导航在线商店&#xff0c;点击右上角查看你的商店。在线商店链接为https://[商店名…

【FPGA 学习与实践】<初阶> 项目周计划

第1-2周&#xff1a;基础项目 - 4位加法器和计数器 目标&#xff1a;掌握Verilog基本语法和模块设计。 第1周&#xff1a; 学习Verilog的基本语法和结构&#xff08;模块、端口、数据类型&#xff09;。设计并实现一个4位加法器。编写测试平台&#xff08;Testbench&#xff0…

38、shell之免交互

免交互 交互&#xff1a;我们发出指令控制程序的运行&#xff0c;程序在接收到指令之后按照指令的效果做出对应的反应。 免交互&#xff1a;间接的&#xff0c;通过第三方的方式把指令传送给程序&#xff0c;不用直接的下达指令。 一、Here Document 免交互&#xff1a; 这…

谈谈在不同公司中的SAP职位

今天反客为主&#xff0c;聊一下这个HR的话题&#xff0c;考虑到SAP职位的专业性&#xff0c;感觉还是有必要谈一谈这个话题。最近跟几位HR的小伙伴聊了一下&#xff0c;讨论了下不同公司的SAP职位的招聘要求&#xff0c;感觉还是有那么几个存在的问题&#xff1a; 追求完美的…

goframe框架规范限制(but it should be named with “Res“ suffix like “XxxRes“)

背景&#xff1a; 首页公司最近要启动一个项目&#xff0c;公司主要业务是用java开发的&#xff0c;但是目前这个方向的项目&#xff0c;公司要求部署在主机上&#xff0c;就是普通的一台电脑上&#xff0c;电脑配置不详&#xff0c;还有经常开关机&#xff0c;所以用java面临…