【003_音频开发_基础篇_Linux进程通信(20种你了解几种?)】

003_音频开发_基础篇_Linux进程通信(20种你了解几种?)

文章目录

  • 003_音频开发_基础篇_Linux进程通信(20种你了解几种?)
    • 创作背景
    • `Linux` 进程通信类型
    • `fork()` 函数
      • `fork()` 输出 `2` 次
      • `fork()` 输出 `8` 次
      • `fork()` 返回值
      • `fork()` 创建子进程 方式一
      • `fork()` 创建子进程 方式二
      • `fork()` 创建子进程 方式三
      • `fork()` 创建子进程 方式四
      • `fork()` 复制父进程上下文
    • `Socket` 套接字(待更新)
    • `Socket` - (`Linux IP` 协议)
    • `Socket` - `UDS`
    • `IP 协议` VS. `UDS`
    • `UDS` 应用场景 —— `Docker Daemon`
    • `UDS` 应用场景 —— `Azure IoT Edge`
    • Socket Activation
    • 管道 `pipe`
      • 匿名管道 `Anonymous pipes`
      • 命名管道 `Named pipe/FIFOs`
    • 消息队列
    • 共享内存
    • 信号量
    • 文件锁
    • 共享文件
    • RPC (Remote Procedure Call)
    • Protocol Buffer
    • gRPC
    • RabbitQM
    • ZeroMQ
    • RPC over HTTP
    • FlatBuffers

创作背景

学历代表过去、能力代表现在、学习力代表将来。 一个良好的学习方法是通过输出来倒逼自己输入。写博客既是对过去零散知识点的总结和复盘,也是参加了 零声教育 写博客活动。

零声教育体验课:https://xxetb.xetslk.com/s/3fbO81

本文是开发过程中的知识点总结,供大家学习交流使用,如有任何错误或不足之处,请在评论区指出。

Linux 进程通信类型

如下表描述了Linux常用进程间通信方式了,包含了多种技术,例如基于系统调用、套接字、共享内存和消息队列等,用于实现进程之间的数据传输、同步和协作,以满足不同应用场景下的需求。

序号中文名英文名描述
1管道Pipe匿名管道 在父子进程或兄弟进程之间进行通信。
命名管道 独立进程间通信
2消息队列Message Queues进程之间通过消息队列进行通信,可以实现异步通信。
3共享内存Shared Memory进程可以通过映射共享内存区域来实现共享数据,提高通信效率。
4信号Signals进程可以通过信号来通知其他进程发生了某些事件。
5信号量Semaphores用于控制对共享资源的访问,防止多个进程同时访问造成冲突。
6文件锁File Locks进程可以通过文件锁来实现对共享文件的互斥访问。
7共享文件Shared Files进程可以通过读写共享文件来进行通信,但需要注意同步和并发访问的问题。
8Memory Mapped FilesMemory Mapped Files进程可以将文件映射到它们的地址空间中,实现对文件内容的共享访问。
9直接操作内存Direct Memory Access进程可以直接读写其他进程的内存来进行通信,但这通常需要特殊的权限和保护机制。
10Event LoopsEvent Loops进程可以使用事件循环来监听和处理事件,实现进程间的消息传递和通知。
11套接字/UDSUnixUnix域套接字(Unix Domain Socket),用于本地进程间通信。
12DBusdbusD-Bus 是一个进程间通信机制,常用于 Linux 桌面环境中实现进程间通信和协作。
13套接字/IPIPInternet套接字(Internet Domain Socket),用于在网络中进行通信。
14Remote Procedure CallsRPC允许进程调用另一个进程中的函数,实现远程通信和协作。
15RPC over HTTPRPC over HTTP使用HTTP协议作为传输层,通过远程过程调用(RPC)来进行进程间通信。
16ZeroMQZeroMQZeroMQ 是一个开源的消息队列库,提供了丰富的 API 和通信模式,用于实现进程间通信。
17Socket ActivationSocket Activationsystemd中的一种机制,允许在需要时才启动服务进程。通过UNIX域套接字传递连接。
18RabbitMQRabbitMQ基于AMQP协议的开源消息代理,用于实现可靠的异步通信。
19gRPCgRPCgRPC 是一个高性能、开源的远程过程调用(RPC)框架,可以用于实现进程间通信。
20Protocol BuffersProtocol Buffers使用序列化格式将数据结构编码后进行传输,实现进程间通信。
21FlatBuffersFlatBuffers使用序列化格式将数据结构编码后进行传输,实现进程间通信。

fork() 函数

  • fork() 是一个系统调用,用于创建一个与当前进程完全相同的新进程。
  • 原进程称为 父进程,新创建的进程称为 子进程
  • 在父进程中,fork() 返回子进程的进程 ID;在子进程中,fork() 返回 0
  • 在调用 fork() 时,两个内存空间具有相同的内容。
  • 一个进程进行的内存写操作、文件映射和解除映射操作不会影响另一个进程。
  • 注意: fork() 调用会有 2 次返回,正常我们的函数调用只有一次返回。

fork() 输出 2

fork() 函数调用后输出两次:当前进程 +  子进程

int main(void)
{
    printf("#### Start pid=%d, parent pid=%d\n\n", getpid(), getppid());
    fork();
    printf("#### Exit pid=%d, parent pid=%d\n", getpid(), getppid());
    
    return 0;
}

img_fork_output_twice

fork() 输出 8

int main(void)
{
    printf("#### Start pid=%d, parent pid=%d\n\n", getpid(), getppid());
     
    fork(); 
    fork(); 
    fork();
    printf("#### Exit pid=%d, parent pid=%d\n", getpid(), getppid());
    return 0;
}

img_fork_output_8_times

fork() 返回值

fork() 函数在父进程中返回子进程的进程 ID,而在子进程中返回 0。调用失败,它将返回一个负值,通常是 -1,表示创建新进程失败。

int main(void)
{
    printf("#### Start pid=%d, parent pid=%d\n\n", getpid(), getppid());
    pid_t pid = fork();
    if (0 == pid)
    {
        printf("child pid=%d, parent pid=%d\n", getpid(), getppid());
    }
    else if (0 < pid)
    {
        printf("pid=%d, parent pid=%d\n", getpid(), getppid());
    }
    else
    {
        printf("fork() failed.\n");
    }
    printf("#### Exit pid=%d, parent pid=%d\n", getpid(), getppid());
    return 0;
}

img_fork_return_value

fork() 创建子进程 方式一

父进程创建 2 个子进程

img_fork_way1

int main()
{
    printf("#### Start pid=%d, parent pid=%d\n\n", getpid(), getppid());
    // 1. parent
    pid_t id = fork();
    if (id == 0) // 2. new child
    {
        fork(); // 3. return twice (one is new child)
    }
    // total: 3 thread = 1 current + 2 child
    printf("#### Exit pid=%d, parent pid=%d\n", getpid(), getppid());
    return 0;
}

img_fork_way1_test_result

fork() 创建子进程 方式二

父进程创建 4 个子进程

img_fork_way2

int main()
{
    printf("#### Start pid=%d, parent pid=%d\n\n", getpid(), getppid());    // 1. parent
    pid_t id = fork();
    if (id == 0) // 2. new child
    {
        id = fork();
        if (id == 0) // 3. new child
        {
            id = fork();
            if (id == 0) // 4. new child
            {
                fork(); // 5. return twice (one is new child)
            }
        }
    }    // total: 3 thread = 1 parent + 4 child    printf("#### Exit pid=%d, parent pid=%d\n", getpid(), getppid());
    return 0;
}

img_fork_way2_test_result

fork() 创建子进程 方式三

父进程创建 4 个子进程

img_fork_way3

int main(void) {
    printf("#### Start pid=%d, parent pid=%d\n\n", getpid(), getppid());    pid_t id[4];    // 1. parent
    for (int i = 0; i < 4; i++)
    {
        id[i] = fork();
        if (id[i] == 0) // 2. new 4 child, by the same parent.
        {
            printf("\tI'm child pid=%d, parent pid=%d\n", getpid(), getppid());
            break;
        }
        else if (id[i] > 0)
        {
            printf("\tI'm parent pid=%d, parent pid=%d\n", getpid(), getppid());
        }
        else
        {
            printf("fork() failed.\n");
        }
    }    // total: 5 thread = 1 parent + 4 child    printf("#### Exit pid=%d, parent pid=%d\n", getpid(), getppid()); // print 5 times
    return 0;
}

img_fork_way3_test_result

fork() 创建子进程 方式四

父进程比子进程先退出,子进程会变为“孤儿进程”,被1 号/init --user进程收养,进程编号也会变为 1

img_fork_way4

int main()
{
    printf("#### Start pid=%d, parent pid=%d\n\n", getpid(), getppid());
    pid_t id[4];
    // 1. parent
    for (int i = 0; i < 4; i++)
    {
        id[i] = fork();
        if (id[i] > 0) // 2. new 4 child, child create child.
        {
            break;
        }
        else if (id[i] == 0) // child exit
        {}
        else //failed 
        {}
    }
    // total: 5 thread = 1 parent + 4 child    printf("#### Exit pid=%d, parent pid=%d\n", getpid(), getppid());
    return 0;
}

img_fork_way4_test_result

fork() 复制父进程上下文

char buffer[64] = "hello world!";
int main()
{
    printf("#### Start pid=%d, parent pid=%d\n\n", getpid(), getppid());
    pid_t pid = fork();
    if (0 < pid) // parent
    {
        printf("\tI'm parent pid=%d, parent pid=%d\n", getpid(), getppid());
        for (int i = 0; i < 10; i++)
        {
            sleep(1);
            printf("\t%d)Parent (%s)\n", i, buffer);
        }
    }
    else if (0 == pid) // child
    {
        printf("\tI'm child pid=%d, parent pid=%d\n", getpid(), getppid());
        for (int i = 0; i < 5; i++)
        {
            if (1 == i) // child thread modify buffer 
            {
                strcpy(buffer, "Sub message.");
            }
            sleep(1);
            printf("\t%d)Sub (%s)\n", i, buffer);
        }
    }
    else
    {
        printf("fork() failed.\n");
    }
    printf("#### Exit pid=%d, parent pid=%d\n", getpid(), getppid());
    return 0;
}

img_fork_duplicate_parent

Socket 套接字(待更新)

Socket - (Linux IP 协议)

Socket - UDS

IP 协议 VS. UDS

UDS 应用场景 —— Docker Daemon

UDS 应用场景 —— Azure IoT Edge

Socket Activation

管道 pipe

匿名管道 Anonymous pipes

命名管道 Named pipe/FIFOs

消息队列

共享内存

信号量

文件锁

共享文件

RPC (Remote Procedure Call)

Protocol Buffer

gRPC

RabbitQM

ZeroMQ

RPC over HTTP

FlatBuffers

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

zkVM选型要点

1. 引言 当选择ZK工具&#xff0c;来做可验证链下计算来扩容区块链时&#xff0c;需考虑&#xff1a; 1&#xff09;为何应选择zkVM&#xff1f;2&#xff09;zkVM有哪些基本功能&#xff1f;3&#xff09;哪些zkVM可提供这些基本功能&#xff1f; 2. 为何应选择zkVM&#x…

OpenCV——图像分块局部阈值二值化

目录 一、算法原理1、算法概述2、参考文献 二、代码实现三、结果展示 OpenCV——图像分块局部阈值二值化由CSDN点云侠原创&#xff0c;爬虫自重。如果你不是在点云侠的博客中看到该文章&#xff0c;那么此处便是不要脸的爬虫。 一、算法原理 1、算法概述 针对目前局部阈值二值…

消息队列 Kafka 入门篇(二) -- 安装启动与可视化工具

一、Windows 10 环境安装 1、下载与解压 首先&#xff0c;访问Apache Kafka的官方下载地址&#xff1a; https://kafka.apache.org/downloads 在本教程中&#xff0c;我们将使用kafka_2.13-2.8.1版本作为示例。下载完成后&#xff0c;解压到您的工作目录的合适位置&#xff…

目标检测——YOLOv6算法解读

论文&#xff1a;YOLOv6: A Single-Stage Object Detection Framework for Industrial Applications (2022.9.7) 作者&#xff1a;Chuyi Li, Lulu Li, Hongliang Jiang, Kaiheng Weng, Yifei Geng, Liang Li, Zaidan Ke, Qingyuan Li, Meng Cheng, Weiqiang Nie, Yiduo Li, Bo …

企业商业活动如何获得央级媒体的采访报道?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 企业想要获得央级媒体的采访报道&#xff0c;确实需要精心策划和准备&#xff1a; 一、如何巧妙给媒体报选题 精准定位&#xff1a;首先要明确企业的核心价值、创新点或行业影响力&…

【C++】手撕list(list的模拟实现)

目录 01.节点 02.迭代器 迭代器运算符重载 03.list类 &#xff08;1&#xff09;构造与析构 &#xff08;2&#xff09;迭代器相关 &#xff08;3&#xff09;容量相关 &#xff08;4&#xff09;访问操作 &#xff08;5&#xff09;插入删除 我们在学习数据结构的时候…

StartAI智能绘图软件出现“缺少Python运行库”怎么办?

StartAI做为一款国产AI界的新秀&#xff0c;是一款贴合AIGC新手的智能绘图软件。新手安装遇见“缺少Python运行库”怎么办”&#xff1f;小编一招搞定~ 解决方法&#xff1a;手动下载【resource文件】&#xff0c;将文件添加到安装目录下。 点击链接进行手动下载噢~ 确保 Star…

图像处理之模板匹配(C++)

图像处理之模板匹配&#xff08;C&#xff09; 文章目录 图像处理之模板匹配&#xff08;C&#xff09;前言一、基于灰度的模板匹配1.原理2.代码实现3.结果展示 总结 前言 模板匹配的算法包括基于灰度的匹配、基于特征的匹配、基于组件的匹配、基于相关性的匹配以及局部变形匹…

Spring-IOC之组件扫描

版本 Spring Framework 6.0.9​ 1. 前言 通过自动扫描&#xff0c;Spring 会自动从扫描指定的包及其子包下的所有类&#xff0c;并根据类上的特定注解将该类装配到容器中&#xff0c;而无需在 XML 配置文件或 Java 配置类中逐一声明每一个 Bean。 支持的注解 Spring 支持一系…

Mysql索引详解(索引分类)

文章目录 概述索引对查询速度的影响索引的优缺点索引类型一级索引和二级索引的区别MySQL 回表联合索引&#xff08;最左前缀原则主键索引和唯一索引的区别BTree索引和Hash索引的区别 覆盖索引索引下推加索引能够提升查询效率原因MySQL 索引结构采用 B树原因索引失效的场景MySQL…

JAVASE基础语法(异常、常用类)

一、异常 1.1 什么是异常 异常就是指不正常。是指代码在运行过程中可能发生错误&#xff0c;导致程序无法正常运行。 package com.atguigu.exception;public class TestException {public static void main(String[] args) {int[] arr {1,2,3,4,5};System.out.println(&quo…

前端css中filter(滤镜)的使用

前端css中filter的使用 一、前言二、补充内容说明三、模糊&#xff08;一&#xff09;、模糊效果&#xff0c;源码1&#xff08;二&#xff09;、源码1运行效果1.视频演示2.截图演示 四、阴影&#xff08;一&#xff09;、阴影效果&#xff0c;源码2&#xff08;二&#xff09;…

Linux文件系统与日志

一、inode和block 文件数据包括元信息与实际数据&#xff0c;文件存储在硬盘上&#xff0c;硬盘最小存储单位是扇区&#xff0c;每个扇区存储512字节 1.block(块)&#xff1a;文件系统中用于存储文件实际数据的最小单位&#xff0c;由文件系统进行分配和管理&#xff0c;并通…

JavaSE内部类

内部类概述 1.内部类的基础 内部类的分类&#xff1a;实例化内部类&#xff0c;静态内部类&#xff0c;局部内部类和匿名内部类 public class OutClass {// 成员位置定义&#xff1a;未被static修饰 --->实例内部类public class InnerClass1{}// 成员位置定义&#xff1a;被…

01、创建型-单例模式--只有一个实例

文章目录 前言一、基本介绍1.1 什么是单例模式1.2 为什么要用单例模式1.3 应用场景1.4 单例优缺点 二、单例模式的实现方式2.1 饿汉式单例2.1.1 静态变量方式2.1.2 静态代码块 2.2 懒汉式单例2.2.1 懒汉式单例2.2.2 懒汉式优化①-线程安全2.2.2 懒汉式优化②-双重检查锁2.2.3 懒…

ROS1快速入门学习笔记 - 04创建工作环境与功能包

一、定义 工作空间(workspace)是一个存放工程开发相关文件的文件夹。 src:代码空间&#xff08;Source Space&#xff09;build: 编辑空间&#xff08;Build Space&#xff09;devel:开发空间&#xff08;Development Space&#xff09;install:安装空间&#xff08;Install …

深入理解Linux文件系统于日志分析

目录 一.Inode 和 block 概述 ​编辑 1.inode 的内容 &#xff08;1&#xff09;Inode 包含文件的元信息 &#xff08;2&#xff09;用 stat 命令可以查看某个文件的 inode 信息 &#xff08;3&#xff09; Linux系统文件三个主要的时间属性 &#xff08;4&#xff09;目…

CentOS 系统的优缺点

CentOS &#xff08;社区企业操作系统的缩写&#xff09;是一个基于红帽企业 Linux (RHEL)的免费开源发行版&#xff0c; 旨在为服务器和工作站提供稳定、可靠和安全的平台。 不应将其与CentOS Stream 混淆&#xff0c;后者是即将发布的 RHEL 版本的上游开发平台。 CentOS Li…

第67天:APP攻防-Frida反证书抓包移动安全系统资产提取评估扫描

思维导图 案例一&#xff1a;内在-资产提取-AppinfoScanne AppinfoScanner 一款适用于以 HW 行动/红队/渗透测试团队为场景的移动端(Android、iOS、WEB、H5、静态网站)信息收集扫描工具&#xff0c;可以帮助渗透测试工程师、攻击队成员、红队成员快速收集到移动端或者静态 WEB …

机器学习之sklearn基础教程

ChatGPT Scikit-learn (简称sklearn) 是一个非常受欢迎的Python机器学习库。它包含了从数据预处理到训练模型的各种工具。下面是一个关于如何使用sklearn进行机器学习的基础教程。 1. 安装和导入sklearn库 首先&#xff0c;你需要安装sklearn库&#xff08;如果你还没有安装的…