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

news2024/10/7 12:23:35

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

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

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

相关文章

elasticsearch-8.1.0安装记录

目录 零、版本说明一、安装二、使用客户端访问 零、版本说明 centos [rootnode1 ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core)elasticsearch elasticsearch-8.1.0-linux-x86_64一、安装 systemctl stop firewalld.servicesystemctl disable firewal…

【国产替代】航空电子通信总线航空电子通信总线产品为MIL-STD-1553和ARINC 429等协议提供原生支持

航空电子通信总线 航空电子通信总线产品为MIL-STD-1553和ARINC 429等协议提供原生支持。这些产品用于进行航空电子应用所需的开发、生产和系统测试。 PXIe&#xff0c;2通道PXI ARINC-664接口模块 AIM ARINC-664具有板载处理器&#xff0c;可自动处理所有与协议相关的活动&…

python绘图时渐变的处理——以一个扇形图的渐变为例

python绘图时渐变的处理——以一个扇形图的渐变为例 使用matplotlib绘制扇形的圆环 from matplotlib.patches import Wedge wedgeWedge((0,0),1,0,60,width0.3,colorred) wedge.set_edgecolor(k) fig,axplt.subplots(1,1) ax.add_patch(wedge) # 设置坐标轴的比例 plt.axis(e…

DaPy:实现数据分析与处理

DaPy&#xff1a;实现数据分析与处理 DaPy是一个用于数据分析和处理的Python库&#xff0c;它提供了一系列强大的工具和功能&#xff0c;使开发者能够高效地进行数据清洗、转换和分析。本文将深入解析DaPy库的特点、功能以及使用示例&#xff0c;帮助读者了解如何利用DaPy库处理…

数据库之数据库恢复技术思维导图+大纲笔记

大纲笔记&#xff1a; 事务的基本概念 事务 定义 用户定义的一个数据库操作系列&#xff0c;这些操作要么全做&#xff0c;要么全不做&#xff0c;是一个不可分割的基本单位 语句 BEGIN TRANSACTION 开始 COMMIT 提交&#xff0c;提交事务的所有操作 ROLLBACK 回滚&#xff0c…

CAN通信简单入门(一)

1.IIC和CAN通信的主要区别 IIC至少需要3根线&#xff0c;SCL,SDA,GND 但是CAN只需要两条线&#xff0c;CAN_H以及CAN_L 2.CAN简介 3.主流通信协议详解 反正CAN通信最大的优势就是&#xff1a;可以多个主机同时进行通信 4.CAN协议详解 4.1 CAN硬件电路 在闭环电路当中&…

Android Studio 报错:AVD Pixel_3a_API_30_x86 is already running

在我的Android Studio和虚拟机运行时&#xff0c;我的电脑不小心关机了&#xff0c;在启动后再次打开Android Studio并运行虚拟机时发现报错。 Error while waiting for device: AVD Pixel_3a_API_30_x86 is already running. If that is not the case, delete the files at C…

数据结构实验(三)

算法设计 一、判断回文序列 1、算法思路&#xff1a; 输入想要判断的字符串&#xff0c;用数组来存放该字符串&#xff0c;给数组一个最左的下标low,和最右的下标right.比较两端的字符是否相等&#xff0c;如果相等那么low,right--.直到遍历完字符串&#xff0c;如果字符不相…

机器人系统开发ros2-基础实践01-学会自定义一个机器人动作aciton实体类

您之前在了解操作教程中了解了action 。与其他通信类型及其各自的接口&#xff08;主题/消息和服务/srv&#xff09;一样&#xff0c;您也可以在包中自定义操作。本教程向您展示如何定义和构建可与您将在下一个教程中编写的action服务器和action 客户端一起使用的操作。 需要理…

Jenkins 打包报错记录 error: index-pack died of signal 15

问题背景&#xff0c;打包每次到92%时就会报错&#xff0c;试了好几次都是同样的错误 14:56:53 fatal: index-pack failed 14:56:53 14:56:53 at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandIn(CliGitAPIImpl.java:2734) 14:56:53 at org.jenkinsci.plugi…

WPF4 数据模板

数据模板 数据模板常用在3种类型的控件, 下图形式: 1.Grid这种列表表格中修改Cell的数据格式, CellTemplate可以修改单元格的展示数据的方式。 2.针对列表类型的控件, 例如树形控件&#xff0c;下拉列表&#xff0c;列表控件, 可以修改其中的ItemTemplate。 3.修改ContentT…

使用API有效率地管理Dynadot域名,自查账户信息

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…

【QT进阶】Qt http编程之实现websocket client客户端

往期回顾 【QT进阶】Qt http编程之nlohmann json库使用的简单介绍-CSDN博客 【QT进阶】Qt http编程之websocket的简单介绍-CSDN博客 【QT进阶】Qt http编程之实现websocket server服务器端-CSDN博客 【QT进阶】Qt http编程之实现websocket client客户端 一、最终效果 通过给定…

随笔Ubuntu上的的一些使用

Ubuntu简易使用 常用指令 cdlsmkdirrf -rm 路径 换源 备份镜像 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak编辑文件设置 sudo gedit /etc/apt/sources.list清华源 # 阿里源 deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe mul…

Elasticsearch集群部署(Linux)

1. 准备环境 这里准备三台Linux虚拟机&#xff0c;用于配置Elasticsearch集群和部署可视化工具Kibana。 角色IP域名集群名称节点名称版本操作系统ES192.168.243.100linux100cluster-eses-node-1007.12.0CentOS 7192.168.243.101linux101cluster-eses-node-101192.168.243.102…

Linux——进程基本概念下篇

Linux——进程基本概念下篇 文章目录 Linux——进程基本概念下篇一、环境变量1.1 环境变量的定义1.2 环境变量的相关命令1.3 命令行参数1.4 本地变量和环境变量1.5 常规命令和内建命令 二、进程地址空间2.1 地址空间的概念2.2 页表和MMU2.3 地址空间的作用2.4 地址空间的好处 一…

学习配置文件

1.yml的语法格式问题&#xff1a; 2.配置文件获取数据&#xff1a; Value方式&#xff1a; Environment&#xff1a; 获取自定义对象的方式&#xff1a; 设置get和set方法&#xff0c;还有toString方法。 3. 日志配置&#xff1a; logo的配置&#xff1a; 日志插件&#xff…

stable-diffusion-webui安装与使用过程中的遇到的error合集

stable-diffusion-webui1.9.2踩坑安装 1. 安装过程1.1 stable-diffusion-webui1.2 在win11或win10系统安装&#xff0c;需修改两个启动脚本1.2.1 修改webui-user.bat1.2.2 修改webui.bat 1.3 双击 webui-user.bat 启动脚本1.3.1 no module xformers. Processing without on fre…

MySQL主要内容

1&#xff0c;在表中插入数据 插入值的类型&#xff0c;必须和字段的类型保持一致 - 如果数据类型是字符串&#xff0c;必须引号引起来&#xff0c;数字的话&#xff0c;可以不加 - 插入的数据顺序和字段的顺序必须保持一致 格式一&#xff1a;向表中插入数据 insert in…

鸿蒙官网学习3

鸿蒙官网学习3 每日小提示项目的模块类型跨设备预览调试阶段应用的替换方式有两种 打开老的demo工程报错UIAbility 每日小提示 项目的模块类型 moduleType分为三种&#xff0c;只有1&#xff0c;2的模块支持直接调试和运行 entryfeaturehar 跨设备预览 需要手动在config.j…