当前位置: 首页 > news >正文

嵌入式Linux:进程间通信机制

目录

1、进程间通信机制

1.1、UNIX IPC

1.2、System V IPC

1.3、POSIX IPC

1.4、套接字(Socket)通信

2、管道(Pipe)

3、消息队列(Message Queue)

4、共享内存(Shared Memory)

5、信号量(Semaphore)

6、套接字(Socket)

7、信号(Signal)


进程间通信(Interprocess Communication,简称 IPC)是指多个进程之间相互交换数据、共享信息或同步操作的过程。由于每个进程都有自己独立的地址空间,不像线程共享同一地址空间,进程之间的通信需要特定的机制。单个进程内部的模块(如函数)之间的通信相对简单,可以通过全局变量、参数传递等方式实现,但进程间通信相对复杂,因为不同进程彼此隔离,不共享内存。

虽然大多数普通应用程序是单进程、多线程的,不需要进程间通信的复杂性,但在一些复杂或大型应用中,尤其是服务器或图形用户界面(GUI)程序,可能会使用多进程架构来提升性能或简化设计。这种情况下,IPC 机制就变得非常重要。

1、进程间通信机制

Linux 系统继承了 UNIX 系统的丰富 IPC 机制,并对其进行了扩展和改进。UNIX 系统的进程间通信大致可以分为两大流派:

  • System V IPC(由 AT&T 贝尔实验室主导发展):改进了 UNIX 早期的进程间通信手段,形成了适用于单台计算机的 IPC 机制,主要包括信号量、消息队列和共享内存。
  • BSD 套接字通信(由加州大学伯克利分校主导发展):BSD 在网络通信和分布式系统方面做出了重要贡献,跳出了进程间通信局限于单个计算机的限制,形成了基于套接字(Socket)的通信机制,广泛用于网络应用程序。

Linux 将这两大体系都继承了下来,并在此基础上发展了 POSIX IPC。POSIX(Portable Operating System Interface for Unix)标准化了多种 UNIX 系统功能,包括进程间通信,弥补了 System V IPC 的一些不足。

1.1、UNIX IPC

UNIX 传统的 IPC 机制包括管道、FIFO 和信号,这些机制最早由 UNIX 系统引入,适用于简单的单机进程间通信。

  • 管道(Pipe):一种单向、半双工的通信机制,通常用于父子进程间的数据传递。父进程可以写入数据,子进程可以读取。
  • FIFO(命名管道):类似于管道,但通过文件系统实现,任何进程都可以通过路径访问该管道,实现双向通信。
  • 信号(Signal):信号是一种用于进程间异步通知的机制,可以用于进程之间的简单通信或事件通知,例如 SIGINT(Ctrl+C 发送的中断信号)。

1.2、System V IPC

System V IPC 是 UNIX 的增强版本,主要包括信号量、消息队列和共享内存,适合需要更复杂的进程同步与数据共享的场景。

  • 信号量(Semaphore):用于进程间的同步,通常用于控制对共享资源的访问。信号量用于防止多个进程同时访问同一资源,避免资源争用问题。
  • 消息队列(Message Queue):允许进程以消息的形式发送和接收数据。消息队列是一种先进先出(FIFO)的结构,支持不同类型的消息,使得进程可以基于消息类型进行处理。
  • 共享内存(Shared Memory):进程之间共享同一块内存区域,允许它们直接读写数据。这是最有效的 IPC 方式,因为数据不需要在进程之间复制。

1.3、POSIX IPC

POSIX IPC 是 System V IPC 的改进版本,旨在解决 System V IPC 在灵活性和可移植性上的一些不足。POSIX 标准为 UNIX 系统间的兼容性提供了统一的接口,使得程序可以更方便地在不同的 UNIX 系统间移植。

  • POSIX 信号量:与 System V 信号量类似,用于进程同步,但提供了更灵活的接口和更强的实时性支持。
  • POSIX 消息队列:改进了 System V 消息队列,允许指定消息的优先级,并提供更简单的接口。
  • POSIX 共享内存:与 System V 共享内存类似,但具有更好的兼容性和可移植性,接口设计更加现代化。

1.4、套接字(Socket)通信

套接字是一种既可以用于本地进程间通信,也可以用于网络通信的机制,支持双向数据传输。基于套接字的 IPC 可以实现非常灵活的通信模式,例如客户端-服务器架构,适合在多台计算机之间传递数据。

各类 IPC 机制的对比和应用场景:

2、管道(Pipe)

管道是一种半双工(单向)的通信方式,通常用于父子进程之间的通信。一个进程可以向管道写入数据,另一个进程从管道读取数据。Linux 提供了无名管道和命名管道两种类型。

  • 无名管道(Anonymous Pipe):只能在具有亲缘关系的进程间使用,比如父进程和子进程。
  • 命名管道(Named Pipe 或 FIFO):通过文件系统中的路径来创建,任意进程都可以访问。

示例

#include <stdio.h>
#include <unistd.h>int main() {int fd[2];pipe(fd); // 创建无名管道if (fork() == 0) { // 子进程close(fd[0]); // 关闭读取端write(fd[1], "Hello, parent!", 15);close(fd[1]);} else { // 父进程char buffer[20];close(fd[1]); // 关闭写入端read(fd[0], buffer, sizeof(buffer));printf("Received: %s\n", buffer);close(fd[0]);}return 0;
}

3、消息队列(Message Queue)

消息队列是一种先进先出的队列,允许进程以消息的形式发送和接收数据。消息队列可以支持多种类型的消息,通过消息类型实现多种目的的通信。

示例:进程A可以向队列发送一个带有特定类型的消息,而进程B可以根据消息类型进行处理。

#include <sys/msg.h>
#include <stdio.h>struct msgbuf {long mtype;char mtext[100];
};int main() {key_t key = ftok("msgqueue", 65);int msgid = msgget(key, 0666 | IPC_CREAT);struct msgbuf message;message.mtype = 1; // 消息类型snprintf(message.mtext, sizeof(message.mtext), "Hello Message Queue");msgsnd(msgid, &message, sizeof(message.mtext), 0);return 0;
}

4、共享内存(Shared Memory)

共享内存是最快的 IPC 机制之一,因为进程之间直接访问同一块内存区域,而不需要拷贝数据。通常使用 shmget()shmat()shmdt() 函数进行共享内存的创建和访问。

示例

#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>int main() {key_t key = ftok("shmfile",65);int shmid = shmget(key, 1024, 0666|IPC_CREAT);char *str = (char*) shmat(shmid, (void*)0, 0);strcpy(str, "Hello Shared Memory");printf("Data written in memory: %s\n", str);shmdt(str);return 0;
}

5、信号量(Semaphore)

信号量是一种用于进程同步的机制,通常用于控制多个进程对共享资源的访问。嵌入式系统中,信号量通常用来避免多个进程同时访问同一资源,防止数据竞争。

示例:信号量可以通过 semget()semop() 函数来操作,用于锁定或解锁资源。

#include <sys/sem.h>
#include <stdio.h>int main() {key_t key = ftok("semfile",65);int semid = semget(key, 1, 0666 | IPC_CREAT);struct sembuf sem_lock = {0, -1, 0}; // 减1操作struct sembuf sem_unlock = {0, 1, 0}; // 加1操作semop(semid, &sem_lock, 1); // 上锁printf("Critical section\n");semop(semid, &sem_unlock, 1); // 解锁return 0;
}

6、套接字(Socket)

套接字不仅支持本地进程间通信,还可以用于网络通信。基于套接字的 IPC 支持双向通信,比较灵活,适合嵌入式系统中进程之间需要频繁且复杂的数据交互的情况。

示例

#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>int main() {int sv[2];socketpair(AF_UNIX, SOCK_STREAM, 0, sv);if (fork() == 0) { // 子进程close(sv[0]);write(sv[1], "Hello from child", 16);close(sv[1]);} else { // 父进程char buffer[20];close(sv[1]);read(sv[0], buffer, sizeof(buffer));printf("Received: %s\n", buffer);close(sv[0]);}return 0;
}

7、信号(Signal)

信号是用来通知进程发生某种事件的机制。进程可以捕获、忽略或处理信号,典型的信号包括 SIGINT(中断信号)和 SIGKILL(杀死进程信号)。

示例:处理 SIGINT 信号(Ctrl+C)。

#include <signal.h>
#include <stdio.h>void sigint_handler(int sig) {printf("Caught signal %d\n", sig);
}int main() {signal(SIGINT, sigint_handler);while (1) {printf("Running...\n");sleep(1);}return 0;
}

进程间通信的机制多种多样,选择合适的方式取决于应用场景的需求。


文章转载自:
http://chaplaincy.wjrtg.cn
http://asleep.wjrtg.cn
http://brant.wjrtg.cn
http://chiliast.wjrtg.cn
http://aesthetician.wjrtg.cn
http://archdeaconate.wjrtg.cn
http://addlepate.wjrtg.cn
http://chaldaic.wjrtg.cn
http://ceylon.wjrtg.cn
http://bidialectal.wjrtg.cn
http://cheder.wjrtg.cn
http://bogged.wjrtg.cn
http://anhwei.wjrtg.cn
http://aversion.wjrtg.cn
http://arrhythmically.wjrtg.cn
http://breen.wjrtg.cn
http://arcadianism.wjrtg.cn
http://cervantite.wjrtg.cn
http://aeolus.wjrtg.cn
http://blackheart.wjrtg.cn
http://assurgent.wjrtg.cn
http://axial.wjrtg.cn
http://bacardi.wjrtg.cn
http://battlement.wjrtg.cn
http://bengaline.wjrtg.cn
http://chromous.wjrtg.cn
http://alky.wjrtg.cn
http://angrily.wjrtg.cn
http://chart.wjrtg.cn
http://beekeeping.wjrtg.cn
http://www.dtcms.com/a/281122.html

相关文章:

  • AJAX 开发中的注意点
  • ASRPRO系列语音模块(第十天)
  • AI 增强大前端数据加密与隐私保护:技术实现与合规遵
  • Python 程序设计讲义(2):Python 概述
  • pc浏览器页面语音播报功能
  • 多路文件IO的几个模型
  • K-means 聚类在肺炎患者分型中的应用(简单示例)
  • 轻轻松松带你进行-负载均衡LVS实战
  • 随机奖励能提升Qwen数学表现?本质是数据污染
  • brupsuite使用中遇到的一些问题(bp启动后浏览器无法连接)/如何导入证书
  • YCQ340汽油机气缸体总成设计cad【8张】设计说明书
  • 模拟C++简易配置系统(模板类 + 全局管理)
  • 一区 Top (HPJ) | WGAS+WGCNA分析文章套路
  • 零基础学软件测试:超详细软件测试基础理论知识讲解
  • 【实时Linux实战系列】使用系统调用实现实时同步
  • Java项目:基于SSM框架实现的学生档案管理系统【ssm+B/S架构+源码+数据库+毕业论文+开题报告】
  • 智能体技术深度解析:从概念到企业级搭建指南
  • 自学java,什么书比较好?
  • MaxKB使用笔记【持续ing】
  • LeetCode 1888. 使二进制字符串字符交替的最少反转次数
  • 维基框架发布 1.0.11 至中央仓,深化国产化 DevOps 生态整合
  • 3-Nodejs-使用fs文件系统模块
  • kotlin的自学笔记1
  • 文心一言开源版部署及多维度测评实例
  • Listener(监听器)
  • 拓扑排序一>可达性统计
  • [WUSTCTF2020]朴实无华
  • Vue 3的核心机制-解析事件流、DOM更新、数据请求、DOM操作规范及组件库DOM操作的解决方案
  • 日记_7.14_实际开发的进步
  • 使用Spring Cloud LoadBalancer报错java.lang.IllegalStateException