Linux 进程间通讯

Linux IPC 方式

在Linux系统中,进程间通信(IPC)是多个运行中的程序或进程之间交换数据和信息的关键机制。Linux提供了多种IPC机制,每种机制都有其特定的用途和优势。以下是Linux上主要的IPC通信方式:

  1. 管道(Pipes)

    • 管道是Linux中最古老的IPC机制之一,它允许数据从一个进程(生产者)流向另一个进程(消费者)。管道是半双工的,即数据只能在一个方向上传输。
    • 无名管道:仅在具有亲缘关系的进程(如父进程和子进程)之间可用,一旦创建了管道,它就与创建它的进程相关联。
    • 命名管道(FIFO):可以在没有亲缘关系的进程之间使用,它们是文件系统中的特殊文件,可以跨启动会话使用。
  2. 消息队列(Message Queues)

    • 消息队列允许进程之间传递结构化的消息,每个消息都有一个类型,这使得消息的过滤成为可能。
    • 消息队列是系统V IPC的一部分,可以在多个进程中使用,即使进程重启后仍然存在。
  3. 信号量(Semaphores)

    • 信号量用于控制对共享资源的访问,避免竞态条件。它们可以是二进制(只有0和1的状态)或计数信号量(可以有多个单位)。
    • 信号量同样属于系统V IPC的一部分,可以跨进程使用,用于同步进程间的操作。
  4. 共享内存(Shared Memory)

    • 共享内存允许多个进程直接访问同一块内存区域,这是最快的IPC机制,因为数据不需要复制。
    • 使用共享内存时,通常还需要信号量或互斥锁来防止多个进程同时修改同一数据。
  5. 信号(Signals)

    • 信号是软件中断,可以由硬件事件、软件异常或另一个进程发送给进程。它们主要用于通知进程发生了某些事件。
    • 信号本身并不携带大量数据,但是可以触发进程执行特定的操作。
  6. 套接字(Sockets)

    • 套接字提供了进程间通信的网络接口,不仅限于本地进程间通信,还可以用于网络通信。
    • 包括流式套接字(SOCK_STREAM,类似TCP)和数据报套接字(SOCK_DGRAM,类似UDP)。
  7. 流(Streams)

    • 流类似于管道,但它们提供了更复杂的通信机制,支持错误处理、流控制和多路复用。
  8. 内存映射文件(Memory-Mapped Files)

    • 虽然严格来说这不是传统的IPC机制,但通过将文件映射到内存中,进程可以像访问内存一样访问文件,从而实现进程间的数据共享。

选择IPC机制时,应考虑通信的需求(如速度、可靠性、复杂性、数据大小等),以及进程之间的关系(如是否在同一台机器上,是否有亲缘关系等)。例如,对于需要高速数据传输的场景,共享内存可能是最佳选择,而如果需要在网络上的多个机器之间通信,则应使用套接字。

几种常用的方式举例说明

1. 管道(Pipes)

  • 匿名管道(Anonymous Pipes):只能用于有亲缘关系的进程之间(如父子进程)。通过pipe()系统调用创建,数据以字节流的形式在进程之间传输。
    • 示例:
      int fd[2];
      pipe(fd);
      if (fork() == 0) {// 子进程close(fd[1]);char buf[100];read(fd[0], buf, sizeof(buf));printf("Child read: %s\n", buf);close(fd[0]);
      } else {// 父进程close(fd[0]);write(fd[1], "Hello from parent", 17);close(fd[1]);
      }
  • 命名管道(Named Pipes/FIFOs):可以用于没有亲缘关系的进程之间。通过mkfifo()系统调用创建。
    • 示例:
      mkfifo("/tmp/myfifo", 0666);
      if (fork() == 0) {// 子进程int fd = open("/tmp/myfifo", O_RDONLY);char buf[100];read(fd, buf, sizeof(buf));printf("Child read: %s\n", buf);close(fd);
      } else {// 父进程int fd = open("/tmp/myfifo", O_WRONLY);write(fd, "Hello from parent", 17);close(fd);wait(NULL); // 等待子进程结束unlink("/tmp/myfifo"); // 删除FIFO文件
      }

2. 消息队列(Message Queues)

  • 提供了一种基于消息的通信方式,允许发送和接收带类型的消息。通过msgget()msgsnd()msgrcv()系统调用进行操作。
    • 示例:
      key_t key = ftok("somefile", 65);
      int msgid = msgget(key, 0666 | IPC_CREAT);
      struct msg_buffer {long msg_type;char msg_text[100];
      } message;if (fork() == 0) {// 子进程message.msg_type = 1;msgrcv(msgid, &message, sizeof(message.msg_text), 1, 0);printf("Child received: %s\n", message.msg_text);
      } else {// 父进程message.msg_type = 1;strcpy(message.msg_text, "Hello from parent");msgsnd(msgid, &message, sizeof(message.msg_text), 0);wait(NULL); // 等待子进程结束msgctl(msgid, IPC_RMID, NULL); // 删除消息队列
      }

3. 共享内存(Shared Memory)

  • 允许多个进程直接访问同一块内存区域,通过shmget()shmat()shmdt()系统调用进行操作,通常需要配合信号量或互斥锁来控制访问。
    • 示例:
      key_t key = ftok("somefile", 65);
      int shmid = shmget(key, 1024, 0666 | IPC_CREAT);
      char *str = (char*) shmat(shmid, NULL, 0);if (fork() == 0) {// 子进程sleep(1); // 确保父进程先写入printf("Child read: %s\n", str);shmdt(str);
      } else {// 父进程strcpy(str, "Hello from parent");wait(NULL); // 等待子进程结束shmdt(str);shmctl(shmid, IPC_RMID, NULL); // 删除共享内存
      }

4. 信号量(Semaphores)

  • 用于控制对共享资源的访问,通过semget()semop()semctl()系统调用进行操作。
    • 示例:
      key_t key = ftok("somefile", 65);
      int semid = semget(key, 1, 0666 | IPC_CREAT);
      semctl(semid, 0, SETVAL, 1); // 初始化信号量为1
      struct sembuf sb = {0, -1, 0}; // P操作if (fork() == 0) {// 子进程semop(semid, &sb, 1); // P操作printf("Child in critical section\n");sleep(2);sb.sem_op = 1; // V操作semop(semid, &sb, 1);
      } else {// 父进程semop(semid, &sb, 1); // P操作printf("Parent in critical section\n");sleep(2);sb.sem_op = 1; // V操作semop(semid, &sb, 1);wait(NULL); // 等待子进程结束semctl(semid, 0, IPC_RMID); // 删除信号量
      }

5. 套接字(Sockets)

  • 适用于网络通信,也可以用于同一台机器上的进程间通信,支持面向连接的TCP和无连接的UDP协议。
    • 示例(Unix域套接字):
      int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
      struct sockaddr_un addr = {0};
      addr.sun_family = AF_UNIX;
      strcpy(addr.sun_path, "/tmp/mysocket");if (fork() == 0) {// 子进程sockfd = socket(AF_UNIX, SOCK_STREAM, 0);connect(sockfd, (struct sockaddr*)&addr, sizeof(addr));char buf[100];read(sockfd, buf, sizeof(buf));printf("Child read: %s\n", buf);close(sockfd);
      } else {// 父进程bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));listen(sockfd, 5);int connfd = accept(sockfd, NULL, NULL);write(connfd, "Hello from parent", 17);close(connfd);close(sockfd);wait(NULL); // 等待子进程结束unlink("/tmp/mysocket"); // 删除套接字文件
      }

这些IPC机制在实际开发中各有其适用场景,选择适合的方式可以有效地实现进程间的通信和数据共享。

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

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

相关文章

前后端分离对软件行业及架构设计的影响

在软件开发领域,前后端分离是一种越来越流行的架构设计模式。这种方法将用户界面(前端)与服务器逻辑(后端)分离开来,允许它们独立开发、测试和部署。本文将探讨前后端分离对软件行业和架构设计的影响&#…

开发Qt上位机获取阿里云IOT设备数据(开发上位机对接阿里云IOT平台)

一、前言 随着物联网技术的快速发展,越来越多的设备开始接入互联网,实现远程监控和管理。为了方便用户实时查看设备的运行状态和数据,本文将介绍如何使用Qt框架开发一款上位机软件,调用阿里云物联网平台的API接口,获取设备最新上传的实时数据,并在Qt设计的软件界面上展示…

添加用户页面(Flask+前端+MySQL整合)

首先导入Flask库和pymysql库。Flask用于创建Web应用程序,pymysql用于连接和操作MySQL数据库。 from flask import Flask, render_template, request import pymysql创建一个Flask应用实例。__name__参数告诉Flask使用当前模块作为应用的名称。 app Flask(__name_…

打造安全的Linux环境:关键配置指南

打造安全的Linux环境:关键配置指南 Linux作为一款开源的操作系统,因其稳定性、灵活性和安全性而受到广泛欢迎。然而,即使Linux系统本身设计得相对安全,不正确的配置或管理不善也可能导致安全风险。本文将指导你如何通过关键配置来…

Android 11 系统OTA升级到旧版本(去除升级时间戳校验)

简介 由于客户要求能够通过OTA升级到旧版本因此探寻反向升级的方法。 方法一:进入recover模式 adb reboot recovery 点击Apply update from SD card 然后选择以前的OTA升级包就可以了。这种方式实测可以升级到旧的版本。但是我们的客户是通过在线升级软件进行更新…

高效管理客户的秘诀:企业如何建立稳固的客户关系

如今的竞争,从商业模式、产品、服务到销售环节,竞争已经不再是单一层面的,而是全方位的,企业需要打造全价值链竞争优势。在这个过程中,客户管理的作用是无可替代的,成为企业成功的关键因素之一。如何高效地…

基于Java的蛋糕预定系统【附源码+LW】

摘 要 当今社会进入了科技进步、经济社会快速发展的新时代。国际信息和学术交流也不断加强,计算机技术对经济社会发展和人民生活改善的影响也日益突出,人类的生存和思考方式也产生了变化。传统购物方式采取了人工的管理方法,但这种管理方法存…

0628_ARM4

练习&#xff1a; stm32流水灯 .text .global _start _start: 使能GPIOE外设时钟 0X50000A28 RCC_MP_AHB4ENSETR[4]->1 LDR R0,0x50000a28 指定操作的内存地址 LDR R1,[R0] 将R0对应的地址空间中的值读取出来 ORR R1,R1,#(0x3<<4) 将第4,5位设置为1 STR…

.net 8 集成 MinIO文件存储服务,实现bucket管理,以及文件对象的基本操作

一、准备工作 1、本地部署MinIO服务 2、创建MinIO的Access Key 3、创建.net 项目 4、下载MinIO sdk 5、相关文档 二、编写MinIO工具类 三、管理存储桶 1、MyBucket类 &#xff08;1&#xff09;判断bucket是否存在 &#xff08;2&#xff09;新建bucket &#xff08…

获取HTTP请求参数的方法

获取HTTP请求参数的方法 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们来深入探讨一下如何在Java中获取HTTP请求参数的方法。 在Web开发中&#xff0…

AI大模型-关于推理、可解释性和 LLMs_ai 推理模型

引言&#xff1a;以下文章的主题我已经思考了很久&#xff0c;我希望能我的话能引起你的思考&#xff0c;并于一些更悲观的AI评论相均衡。推理和可解释性是充满细微差别的主题——我希望这篇文章能体现这一点。 去年 GPT-4 发布时&#xff0c;我注意到出现了一个特殊的议论&…

新能源行业必会基础知识-----电力市场概论笔记-----经济学基础

新能源行业知识体系-------主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/139946830 目录 1. 什么是市场2. 电力市场机制设计的基本要求 1. 什么是市场 经济学定义 市场是供需双方交易并决定商品价格和产量的机制市场可…

JVM原理(一):JVM运行时数据区域的分析

1. 程序计数器 程序计数器是一块较小的内存空间&#xff0c;它可以看作是当前线程所执行的字节码的行号指示器。 作用 在Java虛拟机的概念模型里&#xff0c;字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令&#xff0c;它是程序控制流的指示…

ASP.NET 使用web.config配置文件的system.webServer/modules标签实现登录验证

前言 modules 标签允许你添加、删除或配置在 IIS 中运行的 HTTP 模块。HTTP 模块是处理 HTTP 请求和响应的组件&#xff0c;它们可以在请求处理管道的不同阶段执行代码。某些 system.webServer 中的设置可能只适用于 IIS 的特定模式&#xff08;如集成模式&#xff09;&#x…

Git拉取、切换分支等操作

当你在本地计算机上通过 git clone 命令克隆了一个 Git 仓库后&#xff0c;你会得到一个与远程仓库相对应的本地副本。这个本地副本包含了远程仓库的所有历史记录、分支、标签等。接下来&#xff0c;我会详细解释在该目录下启动 Terminal 并使用 Git 命令来查看和切换分支&…

【FPGA】Verilog 中的 genvar 和 generate 语句教程

在 Verilog 中&#xff0c;generate 语句用于生成多个结构化的代码块&#xff0c;这些代码块可以是循环&#xff08;使用 for&#xff09;或条件生成&#xff08;使用 if&#xff09;。genvar 是一个在 generate 块中使用的变量&#xff0c;用于迭代生成实例。 什么是 genvar&…

一站式企业服务平台能够帮助企业解决哪些问题?

近年来一站式企业服务平台备受区域政府及园区管理者的青睐&#xff0c;充当着区域政府或园区的千里眼和顺风耳&#xff0c;可以用来捕捉与区域经济发展相关的信息&#xff0c;也可以用来倾听企业的诉求&#xff0c;更是成为了区域深抓企业服务的多面手。 同时&#xff0c;一站式…

高电压技术-冲击高压发生器MATLAB仿真

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 冲击电压发生器是产生冲击电压波的装置&#xff0c;用于检验电力设备耐受大气过电压和操作过电压的绝缘性能&#xff0c;冲击电压发生器能产生标准雷电冲击电压波形&#xff0c;雷电冲击电压截波,标准操作冲击…

SHELL脚本学习(十三)初识 gawk 编辑器

概述 gawk提供了一种编程语言&#xff0c;而不仅仅是编辑器命令。 在gawk语言中&#xff0c;可以实现如下操作&#xff1a; 定义变量保存数据使用算数和字符串运算符处理数据使用结构化编程概念 为数据处理添加处理逻辑提取文件中的数据并将其重新排列组合&#xff0c;最后生…

注解详解系列 - @Bean:定义Spring管理的Bean

注解简介 在今天的注解详解系列中&#xff0c;我们将探讨Bean注解。Bean是Spring提供的一个注解&#xff0c;用于在Java配置类中显式定义一个Spring管理的Bean。通过Bean注解&#xff0c;可以灵活地定义和配置Bean&#xff0c;从而增强应用程序的可维护性和可测试性。 注解定义…