Linux -- 进程间通信、初识匿名管道

news2024/11/26 11:13:55

目录

进程间通信

什么是进程间通信

进程间通信的一般规律

前言:

管道

代码预准备:

如何创建管道 -- pipe 函数

参数:

返回值:

wait 函数

参数:

验证管道的运行:

源文件 test.c :

makefile 文件:

 运行结果:


进程间通信

什么是进程间通信

进程间通信(Inter-Process Communication, IPC)是操作系统中非常重要的一个概念,它指的是不同进程之间进行数据交换或者传递消息的机制

进程间通信的主要原因和目的是:

  1. 资源共享不同的进程可能需要访问相同的资源或数据,例如文件、数据库等。通过IPC,可以实现对这些共享资源的有效管理和同步访问。

  2. 任务协作:在很多情况下,一个复杂的任务可能被分解为多个子任务,由不同的进程来执行。为了完成整个任务,这些进程之间需要相互通信,以协调它们的工作流程。

  3. 提高效率:对于一些计算密集型的任务,可以通过将工作分配给多个进程来并行处理,从而加速任务的完成。这时就需要有效的通信机制来保证各部分工作的正确性与一致性。

  4.  模块化设计:软件开发时采用模块化的设计思想,即将程序划分为相对独立但又能相互作用的功能单元(即进程)。这样做不仅有利于维护,而且也使得系统更加灵活可扩展。良好的IPC支持能够促进这种架构模式的应用。

  5. 跨网络服务调用:随着分布式系统的普及,在不同主机上的进程也需要能够互相通信。这涉及到更高级别的IPC形式,如RPC (Remote Procedure Call) 等技术。

进程间通信的一般规律

让不同的进程看到同一份资源!!!

前言:

假设现在有A、B进程,在A进程中开辟一块空间并写入数据,让 B 进程去 A 进程的这块空间读取数据,虽然确实让不同的进程看到了同一份资源,但是破坏了进程的独立性。

所以进程间通信需要有交换数据的空间,且这块空间不能由通信双方任何一个提供,那么这块空间只能由操作系统提供。

我们回顾一下父子进程,假设父进程对同一个文件分别用读方式和写方式打开,父进程将会得到两个文件描述符对象。

为什么对同一个文件分别用读方式打开和写方式打开,会创建两个文件描述符对象?

当你使用读取模式(例如 open("file.txt", "r"))和写入模式(例如 open("file.txt", "w"))分别打开同一个文件时,操作系统会为每次打开操作分配一个独立的文件描述符。这样做有几个原因:

  1. 独立性:每个文件描述符代表了对文件的一个独立访问路径。这意味着你可以同时从一个文件描述符读取数据,而从另一个文件描述符写入数据,即使它们指向的是同一个物理文件。这种独立性允许更灵活地处理文件。

  2. 位置指针:每个文件描述符都有自己的文件偏移量或位置指针。当你通过不同的文件描述符读写文件时,每个描述符的位置指针可以独立移动。这样,在进行多线程或多进程操作时,各个进程/线程可以安全地在不同位置上工作而不互相干扰。

  3. 权限控制:以不同模式打开文件提供了对文件的不同级别的访问权限。比如,只读模式下你只能读取文件内容,而在写入模式下还可以修改文件。拥有两个文件描述符意味着可以根据需要选择适当的访问级别,同时也增加了安全性,因为不需要给所有操作都赋予完全相同的权限。

  4. 性能与资源管理:尽管是同一份文件,但根据具体的操作需求(如顺序读取、随机写入等),操作系统可能采取不同的策略来优化I/O性能。此外,维护多个文件描述符也便于系统更好地跟踪哪些程序正在使用该文件,并且有助于实现诸如引用计数这样的机制,从而有效地管理文件相关的系统资源。

总之,虽然这两个文件描述符对应于同一物理文件,但是它们各自保持了自己的状态信息,这使得在同一时间内能够执行更加复杂的并发操作,同时也增强了系统的灵活性和安全性。

父进程得到两个文件描述符对象之后,我们创建子进程,子进程继承父进程的文件描述符表,父子进程指向同一个文件和缓冲区!这也就实现了父子进程看到同一份资源,就可以实现进程间通信!

管道

从前言中就可以看出,管道的本质是文件!

在 Linux 中,管道(pipe)是一种进程间通信(IPC, Inter-Process Communication)的机制,它允许一个进程的输出直接作为另一个进程的输入。

管道可以看作是连接两个或多个命令的数据流通道,它使得数据可以在不同的程序之间流动而不需要通过临时文件。

标准的管道是单向的,即数据只能从写端流向读端。

匿名管道: 

在前言中,父进程和子进程的文件的读端和写端都是打开的,为了符合管道是单向的,我们可以选择让 父进程作为写端,子进程作为读端 或者 父进程作为读端、子进程作为写端!

如下图,我们让父进程作为写端,子进程作为读端:

代码预准备:

如何创建管道 -- pipe 函数

#include <unistd.h>

int pipe(int pipefd[2]);

该函数用于创建一个匿名管道

参数:

pipefd:这是一个指向两个整数的指针。pipe() 成功后,这两个整数会被设置为新创建的管道的读端和写端的文件描述符。读端通常为 fd[0],写端通常为 fd[1]

返回值:

  • 它在成功时返回 0,并且通过其参数(一个包含两个整数的数组)来传递两个文件描述符;
  • 如果调用失败,pipe() 会返回-1,并设置全局变量 errno 来指示具体的错误原因。

wait 函数

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

pid_t wait(int *status);

wait() 函数是 Unix 和 Linux 系统中用于进程控制的一个重要函数。它允许一个进程(通常是父进程)等待其子进程结束,并获取子进程的退出状态wait() 函数会阻塞调用者,直到至少有一个子进程终止或接收到一个信号。

参数:

status:这是一个指向整数的指针,用来存储子进程的退出状态信息如果不需要这个信息,可以传递 NULL

返回值:

  • 如果有子进程成功终止,则返回该子进程的 PID;
  • 如果没有子进程或者所有子进程都还在运行,wait() 将一直阻塞,直到至少有一个子进程终止。
  • 如果发生错误(如被信号中断),则返回-1,并设置 errno

验证管道的运行:

源文件 test.c :

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>

void writer(int wfd)
{
    const char *str="hello father,I am child";
    char buffer[128];
    int cnt=0;
    pid_t pid=getpid();//获得进程pid
    while(1)
    {
        //向缓冲区里写入内容
        snprintf(buffer,sizeof(buffer),"message:%s,pid:%d,count:%d\n",str,pid,cnt);

        //把缓冲区里的内容写入到管道
        write(wfd,buffer,sizeof(buffer));
        cnt++;
        sleep(1);
    }
}

void reader(int rfd)
{
    char buffer[128];
    while(1)
    {
        //读取管道里的内容
        ssize_t n=read(rfd,buffer,sizeof(buffer)-1);
        printf("father get a message: %s",buffer);
    }
}

int main()
{
    int pipefd[2];
    int n=pipe(pipefd);
    if(n<0)
    {
        return 1;
    }
    printf("%d %d\n",pipefd[0],pipefd[1]);

    pid_t id=fork();
    if(id==0)
    {
        //子进程创建成功
        //关闭读端
        close(pipefd[0]);

        writer(pipefd[1]);//写
        exit(0);
        
    }

    //父进程关闭写端
    close(pipefd[1]);
    reader(pipefd[0]);//读

    wait(NULL);

    return 0;
}

makefile 文件:

testpipe:test.c
	gcc -o $@ $^

.PHONY:clean
clean:
	rm -f testpipe

 运行结果:

从下面的运行结果可以看出,父进程接收到了子进程写的数据:

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

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

相关文章

Python•for

很高兴认识你 for列表字典打印字典默认打印格式控制格式打印字典 定义输入与打印拓展 range()函数元组集合 加油站&#x1f970; 都是用示例帮助理解哦~ 代码都只给图片哦&#xff0c;本人亲身经历&#xff0c;自己手敲会注意到更多细节&#x1fae7; 一起进步吧&#x1f970; …

(二十二)、k8s 中的关键概念

文章目录 1、总体概览2、第一层&#xff1a;物理机、集群、Node、Pod 之间的关系2、第二层&#xff1a;命名空间 Namespace3、定义4、控制平面&#xff08;Control Plane&#xff09;5、特别的概念 Service6、Deployment 经过 之前几篇文章对 k8s 的实践&#xff0c;结合实践&…

立仪科技:光谱共焦传感器在玻璃领域的革命性突破

光谱共焦传感器&#xff0c;一种基于光谱共焦原理的高精度位移测量装置&#xff0c;近年来在玻璃等透明材料的厚度测量和表面形貌检测中展现出了巨大的应用潜力。立仪科技小编将深入探讨光谱共焦传感器在玻璃测量中的技术优势&#xff0c;并分析其解决方案。 一、光谱共焦传感器…

庆祝程序员节:聊一聊编程语言的演变

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

毕业设计 基于STM32单片机健康检测/老人防跌倒系统 心率角度检测GSM远程报警 (程序+原理图+元件清单全套资料)

文章目录 前言一、主要功能介绍二、硬件设计硬件实物展示 三、软件设计四、总结资料与实物获取方式 前言 近年来&#xff0c;毕业设计和答辩的要求与难度逐渐加大&#xff0c;传统的毕业设计题目往往缺乏创新性和亮点&#xff0c;难以满足毕业答辩的标准。 为了帮助大家顺利完…

STM32L476芯片在KEIL环境下BOOT跳转APP注意事项

BOOT工程 分配BOOT程序地址、设置参数地址、APP程序地址、下载缓冲区地址 #define BOOT_SECTOR_ADDR 0x08000000 #define BOOT_SECTOR_SIZE 0x0000A000 #define SETTING_SECTOR_ADDR 0x0800A000 #define SETTING_SECTOR_SIZE 0x00002000 #define APP_S…

Spring Boot:植物健康监测的智能管家

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

python——数据类型(数字,字符串)

&#xff08;一&#xff09;基本知识 首先我们需要知道&#xff0c;在python中数据类型大体可以分为两类 1.基本数据类型&#xff1a;数字和字符串 2.复合数据类型&#xff1a;列表&#xff0c;元组&#xff0c;字典&#xff0c;集合 &#xff08;二&#xff09;基本数据类型 …

LabVIEW水质监测系统

在面对全球性的海洋污染问题时&#xff0c;利用先进技术进行水质监测成为了保护海洋环境的关键手段之一。开发了一种基于LabVIEW的海洋浮标水质监测系统&#xff0c;该系统能够实时监测并评估近海水域的水质状况&#xff0c;旨在为海洋保护和污染防治提供科技支持。 项目背景 …

【数据结构】专栏开篇 | 1024程序员节

专栏说明&#xff1a;本专栏用于数据结构复习&#xff0c;文章中出现的代码由C语言实现&#xff0c;在专栏中会涉及到部分OJ题目&#xff0c;如对你学习有所帮助&#xff0c;可以点赞鼓励一下博主喔~~~&#x1f493; 博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a…

关于bp抓不到本地包

关于bp抓不到本地包 关于bp抓不到本地包 关于bp抓不到本地包 pikachu练习时&#xff0c;发现用bp抓本地&#xff08;127.0.0.1&#xff09;数据包时&#xff0c;竟然直接放行访问。 是因为系统默认127.0.0.1无法使用代理&#xff0c;因此bp才抓不到本地数据包&#xff0c;需要…

vue中为什么data属性在实例中可以定义成对象,而在组件中定义成对象会抛出错误

在vue组件中将data属性定义成对象会报错 为什么data属性在实例中可以定义成对象&#xff0c;而在组件中定义成对象则会抛出错误&#xff1f; Vue 实例中的 data 属性&#xff1a; 当 data 被定义在一个单一的 Vue 实例中时&#xff0c;这个实例通常是全局唯一的&#xff0c…

数据结构笔记(其七)--树(二叉树)

目录 1.知识总览 2.二叉树的基本概念 &#xff08;1&#xff09;.满二叉树 &#xff08;2&#xff09;.完全二叉树 &#xff08;3&#xff09;.二叉排序树 &#xff08;4&#xff09;.平衡二叉树 3.二叉树常考点 i.叶子结点与二分支结点的数量关系 ii.第i 层的最多结点数&…

如何禁止上班期间浏览无关网站?

禁止员工在上班期间浏览无关网页主要是为了提升工作效率和生产力&#xff0c;确保员工能够专注于工作任务。同时&#xff0c;这种做法有助于降低网络安全风险&#xff0c;防止恶意软件和钓鱼攻击&#xff0c;减少数据泄露和法律风险&#xff0c;维护公司的专业形象&#xff0c;…

【前端开发入门】JavaScript快速入门--js变量

目录 引言一、为什么要定义变量二、定义变量的一些技巧1. 解构赋值1.1 Object解构赋值1.2 Array解构赋值1.3 总结规律 2. 字符串拼接 三、变量作用域四、总结 引言 本系列教程旨在帮助一些零基础的玩家快速上手前端开发。基于我自学的经验会删减部分使用频率不高的内容&#xf…

Unity引擎:游戏开发的核心力量

目录 引言 Unity引擎的发展历程 早期发展 跨平台支持 Unity引擎的核心特性 易用性 社区支持 跨平台能力 Unity在游戏开发中的应用 移动游戏 独立游戏 3A游戏 Unity的未来展望 高级图形和渲染技术 扩展现实&#xff08;XR&#xff09;支持 云服务和多人游戏 结论…

C#判断点是否在多边形内

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff01;人工智能学习网站 前言&#xff1a; 大家好&#xff0c;我是上位机马工&#xff0c;硕士毕业4年年入40万&#xff0c;目前在一家自动化公司担任…

在不支持AVX的linux上使用PaddleOCR

背景 公司的虚拟机CPU居然不支持avx, 默认的paddlepaddle的cpu版本又需要有支持avx才行,还想用PaddleOCR有啥办法呢? 是否支持avx lscpu | grep avx 支持avx的话,会显示相关信息 如果不支持的话,python运行时导入paddle会报错 怎么办呢 方案一 找公司it,看看虚拟机为什么…

logdata-anomaly-miner:一款安全日志解析与异常检测工具

关于logdata-anomaly-miner logdata-anomaly-miner是一款安全日志解析与异常检测工具&#xff0c;该工具旨在以有限的资源和尽可能低的权限运行分析&#xff0c;以使其适合生产服务器使用。 为了确保 logdata-anomaly-miner的正常运行&#xff0c;推荐安装了python > 3.6的…

通过异地组网工具+RustDesk实现虚拟局域网使用远程桌面RDP

通过异地组网工具RustDesk实现虚拟局域网使用远程桌面RDP 预期效果 常见的远程桌面工具就不多说&#xff0c;麻烦而且不好用 QQ 使用普及率高 卡顿、延迟高 TeamViewer 功能强大、兼容性好 官方查询商业用途频繁 向日葵 安全性高、支持多种设备 强制登录、免费用户限速、限…