linux——IPC 进程间通信

 IPC   进程间通信  interprocess communicate

IPC(Inter-Process Communication),即进程间通信,其产生的原因主要可以归纳为以下几点:

进程空间的独立性

  1. 资源隔离:在现代操作系统中,每个进程都拥有自己独立的代码和数据空间。这种隔离机制确保了进程之间的安全性和稳定性,但同时也使得进程间无法直接访问对方的资源。

  2. 资源无法共享:由于进程空间的独立性,一个进程无法直接读取或修改另一个进程的内存空间中的数据。这种情况下,如果需要进行数据交换或共享资源,就需要通过特定的机制来实现。

进程间协作的需求

  1. 数据交换:在多进程操作系统中,不同的进程可能需要交换数据以完成共同的任务。例如,一个进程可能负责生成数据,而另一个进程则负责处理这些数据。为了实现这种数据交换,就需要使用IPC机制。

  2. 资源共享:进程间通信还允许进程共享资源,如文件、数据库、内存等。通过IPC,进程可以协调对共享资源的访问,避免冲突和竞争条件。

  3. 任务协调:在分布式系统或并发编程中,多个进程可能需要协同工作以完成复杂的任务。IPC提供了进程间同步和互斥的机制,确保任务能够按照预定的顺序和条件执行。

IPC的必要性

  1. 提高系统并发性:通过IPC,多个进程可以并行处理不同的任务,从而提高系统的并发处理能力。

  2. 优化资源利用:IPC允许进程共享资源,减少了资源的重复分配和浪费,提高了资源利用率。

  3. 实现复杂功能:在构建复杂的软件系统时,往往需要多个进程协同工作。IPC为这些进程之间的通信和协作提供了必要的支持。

IPC的实现方式

IPC的实现方式多种多样,包括但不限于以下几种:

  1. 管道(Pipe):一种单向通信方式,常用于具有亲缘关系的进程间通信。

  2. 消息队列(Message Queue):允许多个进程从同一个队列中读取数据,具有独立性和异步性。

  3. 共享内存(Shared Memory):一段可以被多个进程同时访问的物理内存区域,提高了进程间的数据交换效率。

  4. 信号(Signal):一个进程向另一个进程发送信号来传递某种信息或通知某个事件的发生。

  5. 套接字(Socket):用于不同主机之间的进程通信,提供了网络通信的能

管道==》无名管道、有名管道

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


    管道的特性:
    1、管道是 半双工的工作模式(收或者发)
    2、所有的管道都是特殊的文件不支持定位操作。不支持lseek->> fd  fseek ->>FILE* 
    3、管道是特殊文件,读写使用文件IO。fgets,fread,fgetc,

       一般情况下使用open,read,write,close;

主要看是否是二进制文件,如果是文本文件使用fges之类的标准io。

注意事项:  
   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[]="hello,world";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;
}

   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[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};
//        read(pipefd[0],buf,sizeof(buf));//      printf("pipe %s\n",buf);while(1)sleep(1);}else {perror("fork");exit(1);}return 0;
}

  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. read 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;
}

 if(rd_ret<=0)
            {
                break;
            }

如果读端进程调用read()函数从管道中读取数据,并且管道已经为空(即没有任何待读取的数据),同时写端已经被关闭,那么read()函数将会立即返回,并且返回值为0。这个返回值0是一个特殊的信号,它告诉读端进程,管道的写端已经被关闭,并且管道中没有更多的数据可以读取了。

使用框架:
    创建管道 ==》读写管道 ==》关闭管道

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

   

流程:
    创建并打开管道: pipe函数

先创建管道再fork();

关闭管道1或者0用,close(xx);
#include <unistd.h>
int pipe(int pipefd[2]);
功能:创建并打开一个无名管道
参数:pipefd[0] ==>无名管道的固定读端
      pipefd[1] ==>无名管道的固定写端
返回值:成功 0
        失败 -1;

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

关闭管道: close();

通过管道的方式实现文件的复制:

#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、父子进程是否都有fd[0] fd[1],
   如果在单一进程中写fd[1]能否直接从fd[0]中读到。

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

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

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

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

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


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

    
练习:
    如何用管道实现一个双向通信功能
    将从父进程发送的消息在发回给父
    进程。
    
    
    pipe,
    
    fork()
    
    if(pid>0)
    {
        read(file,,)
        wirte(fd[1]);
    }
    
    if(0 == pid)
    {
            read(fd[0]);
            write(newfile);
    }
    
    
    
    person
    {
        char name[];
        int age;
        char phone;
    }
    
    
    pipe[];
    fork();
    
    > 0
    fgets 获得输入
    填结构体,
    写入管道,
    ==0
    
    read,
    填结构体,,
    
    显示到。。。
    
    hello
    pipe:hello 
    wordld
    pipe2 ::world;
    
    
    
    
    
    

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

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

1、创建:mkfifo
#include <sys/types.h>
#include <sys/stat.h>
 remove();

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

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

    不能是 O_RDWR 方式打开文件。
    不能有 O_CREAT 选项,因为创建管道有指定的mkfifo函数


3、管道的读写: 文件IO

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

4、关闭管道:
        close(fd);

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

open会阻塞,等到另一端读端打开,解除阻塞。

函数是否会阻塞,具体根据操作的对象有关。


#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;
}
#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;
}

remove可以在命令行调用。

运行方法:

练习:
    编写一个非亲缘关系进程间通信程序,可以从
    A程序向B程序连续发送不同的数据,并从B中
    将发送的信息打印输出,当双方收到quit的时候
    程序全部退出。

思考题:
    是否每次启动程序必须进行有名管道的创建工作
    能否有一个独立的维护工具,可以任意创建并删除
    有名管道?
    比如:
        ./fifo_tool -A fifo  ==>创建一个有名管道fifo
        ./fifo_tool -D fifo  ==>删除一个有名管道fifo

作业:

    有名管道的操作函数封装:
    int fifo_read(char *fifoname,void *s,int size);
    int fifo_write(char *fifoname,void *s,int size);

    编写测试程序验证以上两个函数效果。

    gstream

  有名管道 ===》

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

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

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

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

 

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

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

相关文章

图解 Kafka 架构

写在前面 Kafka 是一个可横向扩展&#xff0c;高可靠的实时消息中间件&#xff0c;常用于服务解耦、流量削峰。 好像是 LinkedIn 团队开发的&#xff0c;后面捐赠给apache基金会了。 kafka 总体架构图 Producer&#xff1a;生产者&#xff0c;消息的产生者&#xff0c;是消息的…

怎么把录音转文字?推荐几个简单易操作的方法

在小暑这个节气里&#xff0c;炎热的天气让人分外渴望效率up&#xff01;Up&#xff01;Up&#xff01; 对于那些在会议或课堂中急需记录信息的朋友们&#xff0c;手写笔记的速度往往难以跟上讲话的节奏。此时&#xff0c;电脑录音转文字软件就像一阵及时雨&#xff0c;让记录…

PHP pwn 学习 (1)

文章目录 A. PHP extensions for C1. 运行环境与工作目录初始化2. 构建与加载3. 关键结构定义PHP_FUNCTIONINTERNAL_FUNCTION_PARAMETERSzend_execute_data等ZEND_PARSE_PARAMETERS_START等zend_parse_arg_stringzend_module_entryzend_function_entry等PHP类相关 原文链接&…

Python 作业题1 (猜数字)

题目 你要根据线索猜出一个三位数。游戏会根据你的猜测给出以下提示之一&#xff1a;如果你猜对一位数字但数字位置不对&#xff0c;则会提示“Pico”&#xff1b;如果你同时猜对了一位数字及其位置&#xff0c;则会提示“Fermi”&#xff1b;如果你猜测的数字及其位置都不对&…

Flower花所:稳定运营的数字货币交易所

Flower花所是一家稳定运营的数字货币交易所&#xff0c;致力于为全球用户提供安全、高效的数字资产交易服务。作为一家长期稳定运营的数字货币交易平台&#xff0c;Flower花所以其可靠的技术基础和优质的客户服务而闻名。 平台稳定性与可靠性&#xff1a; 持续运营&#xff1a;…

Vue前端练习

此练习项目只涉及前端&#xff0c;主要是vue和ElementUI框架的使用。&#xff08;ElementUI官网&#xff1a;Element - The worlds most popular Vue UI framework&#xff09; 一、环境准备 安装idea 安装Node.js 一键式安装(不需要做任何配置) npm -v&#xff08;也可用nod…

mysql-sql-第十五周

学习目标&#xff1a; sql 学习内容&#xff1a; 41.查询没有学全所有课程的同学的信息 select *from students where students.stunm not in (select score.stunm from score group by score.stunm having count(score.counm) (select count(counm) from course)) 42.查询…

数据结构_线性表

线性表的定义和特点 线性表是具有相同特性的数据元素的一个有限序列 :线性起点/起始节点 :的直接前驱 :的直接后继 :线性终点/终端节点 n:元素总个数,表长 下标:是元素的序号,表示元素在表中的位置 n0时称为空表 线性表 由n(n>0)个数据元素(结点),组成的有限序列 将…

安卓模拟器如何修改ip地址

最近很多老铁玩游戏的&#xff0c;想多开模拟器一个窗口一个IP&#xff0c;若模拟器窗口开多了&#xff0c;IP一样会受到限制&#xff0c;那么怎么更换自己电脑手机模拟器IP地址呢&#xff0c;今天就教大家一个修改模拟器IP地址的方法&#xff01;废话不多说&#xff0c;直接上…

alibaba EasyExcel 简单导出数据到Excel

导入依赖 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>4.0.1</version> </dependency> 1、alibaba.excel.EasyExcel导出工具类 import com.alibaba.excel.EasyExcel; import …

探索哈希函数:数据完整性的守护者

引言 银行在处理数以百万计的交易时&#xff0c;如何确保每一笔交易都没有出错&#xff1f;快递公司如何跟踪成千上万的包裹&#xff0c;确保每个包裹在运输过程中没有丢失或被替换&#xff1f;医院和诊所为庞大的患者提供有效的医疗保健服务&#xff0c;如何确保每个患者的医疗…

假阳性和假阴性、真阳性和真阴性

在深度学习的分类问题中&#xff0c;真阳性、真阴性、假阳性和假阴性是评估模型性能的重要指标。它们的定义和计算如下&#xff1a; 真阳性&#xff08;True Positive, TP&#xff09;&#xff1a; 定义&#xff1a;模型预测为正类&#xff08;阳性&#xff09;&#xff0c;且实…

电梯修理升级,安装【电梯节能】能量回馈设备

电梯修理升级&#xff0c;安装【电梯节能】能量回馈设备 1、节能率评估 15%—45% 2、降低机房环境温度&#xff0c;改善电梯控制系统的运行环境&#xff1b; 3、延长电梯使用寿命&#xff1b; 4、机房可以不需要使用空调等散热设备的耗电&#xff0c;间接节省电能。 欢迎私询哦…

智能数字人系统的主要功能

智能数字人系统或虚拟数字人系统&#xff0c;是指利用人工智能技术构建的虚拟人物形象&#xff0c;能够与人进行自然交互的系统。数字人系统的主要功能包括以下几个方面。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1. 语言理解与…

昇思25天学习打卡营第2天|初学入门

昇思25天学习打卡营第2天 文章目录 昇思25天学习打卡营第2天网络构建定义模型类模型层nn.Flattennn.Densenn.ReLUnn.SequentialCellnn.Softmax 模型参数 函数式自动微分函数与计算图微分函数与梯度计算Stop GradientAuxiliary data神经网络梯度计算 问题集合打卡记录 网络构建 …

华为DCN之:SDN和NFV

1. SDN概述 1.1 SDN的起源 SDN&#xff08;Software Defined Network&#xff09;即软件定义网络。是由斯坦福大学Clean Slate研究组提出的一种新型网络创新架构。其核心理念通过将网络设备控制平面与数据平面分离&#xff0c;从而实现了网络控制平面的集中控制&#xff0c;为…

移动网络捕获在数字化转型中的重要性

数字化转型重新定义了企业运营和与客户互动的方式。它为组织提供价值的方式带来了根本性的转变&#xff0c;使流程更易于访问、更高效、更具协作性和更安全。然而&#xff0c;跟上不断发展的数字环境可能是一项挑战&#xff0c;而未能接受数字化转型的企业则面临被淘汰的风险。…

【MindSpore学习打卡】应用实践-计算机视觉-ShuffleNet图像分类:从理论到实践

在当今的深度学习领域&#xff0c;卷积神经网络&#xff08;CNN&#xff09;已经成为图像分类任务的主流方法。然而&#xff0c;随着网络深度和复杂度的增加&#xff0c;计算资源的消耗也显著增加&#xff0c;特别是在移动设备和嵌入式系统中&#xff0c;这种资源限制尤为突出。…

25计算机考研,这些学校双非闭眼入,性价比超高!

计算机考研&#xff0c;好的双非院校也很多&#xff01; 对于一些二本准备考研的同学来说&#xff0c;没必要一直盯着985/211这些院校&#xff0c;竞争激烈不说&#xff0c;容易当陪跑&#xff0c;下面这些就是不错的双非院校&#xff1a; 燕山大学南京邮电大学南京信息工程大…

WPS-Word文档表格分页

一、问题描述 这种情况不好描述 就是像这种表格内容&#xff0c;但是会有离奇的分页的情况。这种情况以前的错误解决办法就是不断地调整表格的内容以及间隔显得很乱&#xff0c;于是今天去查了解决办法&#xff0c;现在学会了记录一下避免以后忘记了。 二、解决办法 首先记…