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

Linux 进程间通信(IPC)

进程间通信(IPC)是指不同进程之间交换数据或信息的机制。在 Unix/Linux 系统中,有多种进程间通信的方式,包括 管道(Pipe)消息队列(Message Queue)共享内存(Shared Memory)信号量(Semaphore) 等。

1. 管道(Pipe)

管道是 Unix/Linux 中最常见的进程间通信方式之一。它允许一个进程将数据写入管道,另一个进程从管道中读取数据。管道通常用于父子进程之间的通信。

示例:父进程和子进程通过管道通信
#include <stdio.h>
#include <unistd.h>
#include <string.h>int main() {int pipefd[2];pid_t pid;char buffer[128];// 创建管道if (pipe(pipefd) == -1) {perror("pipe failed");return 1;}pid = fork();  // 创建子进程if (pid == -1) {perror("fork failed");return 1;}if (pid == 0) {  // 子进程close(pipefd[0]);  // 关闭读取端const char *msg = "Hello from child process!";write(pipefd[1], msg, strlen(msg) + 1);  // 向管道写入数据close(pipefd[1]);} else {  // 父进程close(pipefd[1]);  // 关闭写入端read(pipefd[0], buffer, sizeof(buffer));  // 从管道读取数据printf("Parent received: %s\n", buffer);close(pipefd[0]);}return 0;
}
解释:
  • pipe(pipefd) 创建一个管道,其中 pipefd[0] 是读取端,pipefd[1] 是写入端。
  • 父进程和子进程通过 fork() 创建,父进程从管道中读取数据,子进程向管道写入数据。
  • write()read() 分别用于写入和读取管道数据。

2. 消息队列(Message Queue)

消息队列是一个允许进程通过向队列中发送和接收消息来交换信息的机制。它提供了一种可靠的、灵活的通信方式,可以用来实现复杂的进程间通信。

示例:使用消息队列进行进程间通信
#include <stdio.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>#define MSG_SIZE 128// 消息结构体
struct message {long msg_type;char msg_text[MSG_SIZE];
};int main() {key_t key = ftok("msgfile", 65);  // 创建消息队列的键值int msgid = msgget(key, 0666 | IPC_CREAT);  // 获取消息队列IDif (msgid == -1) {perror("msgget failed");return 1;}pid_t pid = fork();  // 创建子进程if (pid == -1) {perror("fork failed");return 1;}if (pid == 0) {  // 子进程发送消息struct message msg;msg.msg_type = 1;strcpy(msg.msg_text, "Hello from child process!");if (msgsnd(msgid, &msg, sizeof(msg), 0) == -1) {perror("msgsnd failed");return 1;}printf("Child sent message: %s\n", msg.msg_text);} else {  // 父进程接收消息struct message msg;if (msgrcv(msgid, &msg, sizeof(msg), 1, 0) == -1) {perror("msgrcv failed");return 1;}printf("Parent received message: %s\n", msg.msg_text);}// 删除消息队列msgctl(msgid, IPC_RMID, NULL);return 0;
}
解释:
  • msgget() 创建一个消息队列,msgsnd() 用于发送消息,msgrcv() 用于接收消息。
  • 父进程和子进程通过消息队列进行通信,子进程发送消息,父进程接收并打印。

3. 共享内存(Shared Memory)

共享内存允许多个进程访问同一块内存区域,提供高效的进程间通信方式。可以通过共享内存来交换数据,无需通过内核中转。

示例:父进程和子进程通过共享内存通信
#include <stdio.h>
#include <sys/shm.h>
#include <unistd.h>
#include <string.h>#define SHM_SIZE 128int main() {key_t key = ftok("shmfile", 65);  // 创建共享内存的键值int shm_id = shmget(key, SHM_SIZE, 0666 | IPC_CREAT);  // 获取共享内存IDif (shm_id == -1) {perror("shmget failed");return 1;}char *shm_ptr = shmat(shm_id, NULL, 0);  // 将共享内存映射到进程地址空间if (shm_ptr == (char *) -1) {perror("shmat failed");return 1;}pid_t pid = fork();  // 创建子进程if (pid == -1) {perror("fork failed");return 1;}if (pid == 0) {  // 子进程写入共享内存const char *msg = "Hello from child process!";strcpy(shm_ptr, msg);  // 写入数据到共享内存} else {  // 父进程读取共享内存sleep(1);  // 确保子进程先写入数据printf("Parent received: %s\n", shm_ptr);}// 分离共享内存shmdt(shm_ptr);// 删除共享内存shmctl(shm_id, IPC_RMID, NULL);return 0;
}
解释:
  • shmget() 创建一个共享内存段,shmat() 将共享内存附加到进程的地址空间。
  • 父进程和子进程通过共享内存进行数据交换。
  • shmdt()shmctl() 分别用于分离和删除共享内存。

4. 信号量(Semaphore)

信号量用于控制多个进程对共享资源的访问,常用于解决同步和互斥问题。

示例:使用信号量进行同步(此处示例比较简化)
#include <stdio.h>
#include <sys/sem.h>
#include <unistd.h>int main() {key_t key = ftok("semfile", 65);int sem_id = semget(key, 1, 0666 | IPC_CREAT);if (sem_id == -1) {perror("semget failed");return 1;}struct sembuf sb = {0, -1, 0};  // 信号量P操作pid_t pid = fork();  // 创建子进程if (pid == -1) {perror("fork failed");return 1;}if (pid == 0) {  // 子进程semop(sem_id, &sb, 1);  // 等待信号量printf("Child process has acquired the semaphore!\n");} else {  // 父进程sleep(1);  // 等待子进程sb.sem_op = 1;  // 信号量V操作semop(sem_id, &sb, 1);  // 释放信号量printf("Parent process has released the semaphore!\n");}semctl(sem_id, 0, IPC_RMID);  // 删除信号量return 0;
}
解释:
  • semget() 创建信号量,semop() 用于对信号量进行操作。
  • 父子进程通过信号量进行同步,控制对资源的访问。

总结

在 Unix/Linux 系统中,常见的进程间通信方式包括:

  • 管道(Pipe):父子进程之间通过管道传输数据。
  • 消息队列(Message Queue):进程间传递消息,可以支持多个进程通信。
  • 共享内存(Shared Memory):多个进程直接访问共享内存区。
  • 信号量(Semaphore):用于进程间的同步和互斥控制。

如果需要高效的数据交换,共享内存 是一个非常好的选择。如果需要管理多个进程之间的消息,消息队列 可能更适合。

http://www.xdnf.cn/news/1424485.html

相关文章:

  • 大型语言模型微调 内容预告(69)
  • 【Docker】2025版Ubuntu 22.04 安装 Docker Docker Compose 指南
  • 电力工程师的AI时代已来,这6大功能彻底颠覆传统工作模式
  • 系统性学习数据结构-第二讲-顺序表与链表
  • 金融数据安全
  • 基于单片机汽车防盗系统/汽车安全防丢系统
  • 动态代理设计模式
  • 多模态大语言模型部署
  • Java泛型通配符详解:搞懂?/extends/super用法,避开集合操作踩坑点
  • 二、感知机
  • 高防IP防护效果评估全攻略:从指标解读到实战测试
  • langgraph / openmanus / suna 对比
  • 数据安全不用愁,群晖NAS让你存得放心、用得安心
  • 深度学习环境搭建运行(二) Ubuntu22.04安装基于CUDA11.8的ONNXRuntime-gpu1.18.1详细步骤(新手入门)
  • 联邦学习的文献复现与创新思路指导
  • Qt 项目文件(.pro)中添加 UI 文件相关命令
  • 深度学习】--卷积神经网络
  • k8s--etcd
  • h5实现内嵌微信小程序支付宝 --截图保存海报分享功能
  • authentication port-control auto 和 dot1x port-control auto
  • Linux ARP老化机制/探测机制/ip neigh使用
  • Paimon MergeTreeWrite、Compaction 和 快照构建
  • 甲烷浓度时空演变趋势分析与异常值计算(附下载脚本)
  • 基于docker-compose搭建EFK(Elasticsearch+fluentd+kibana)的日志平台
  • 2025年工作后值得考的财会行业证书推荐,尤其是第二个!
  • 从网络层接入控制过渡到应用层身份认证的过程
  • 如何在SptingBoot项目中引入swagger生成API文档
  • HarvardX TinyML小笔记2(番外3:数据工程)
  • 技术速递|构建你的第一个 MCP 服务器:如何使用自定义功能扩展 AI 工具
  • Linux之Shell编程(四)函数、数组、正则