Linux 系统中,进程间通信机制

ops/2025/2/13 20:17:04/

在 Linux 系统中,进程间通信(Inter-Process Communication, IPC)是多个进程之间交换数据和同步操作的机制。Linux 提供了多种 IPC 方式,每种方式适用于不同的场景。以下是常见的 IPC 方式及其详解:


1. 管道(Pipe)

管道是一种半双工的通信方式,数据只能单向流动。通常用于父子进程或兄弟进程之间的通信。

(1)无名管道(Anonymous Pipe)
  • 特点
    • 只能在具有亲缘关系的进程之间使用(如父子进程)。
    • 通过 pipe() 系统调用创建。
    • 数据是字节流,没有消息边界。
  • 示例
    #include <unistd.h>
    #include <stdio.h>int main() {int fd[2];pipe(fd); // 创建管道if (fork() == 0) { // 子进程close(fd[0]); // 关闭读端write(fd[1], "Hello", 6); // 写入数据close(fd[1]);} else { // 父进程close(fd[1]); // 关闭写端char buf[6];read(fd[0], buf, 6); // 读取数据printf("Received: %s\n", buf);close(fd[0]);}return 0;
    }
    
(2)命名管道(Named Pipe, FIFO)
  • 特点
    • 可以在无关进程之间使用。
    • 通过 mkfifo() 创建,是一个特殊的文件。
    • 数据是字节流,没有消息边界。
  • 示例
    #include <unistd.h>
    #include <fcntl.h>
    #include <stdio.h>int main() {mkfifo("my_fifo", 0666); // 创建命名管道if (fork() == 0) { // 子进程int fd = open("my_fifo", O_WRONLY);write(fd, "Hello", 6);close(fd);} else { // 父进程int fd = open("my_fifo", O_RDONLY);char buf[6];read(fd, buf, 6);printf("Received: %s\n", buf);close(fd);}return 0;
    }
    

2. 消息队列(Message Queue)

消息队列是一种全双工的通信方式,允许进程通过消息的形式交换数据。

  • 特点
    • 消息是有边界的,发送和接收的是完整的消息。
    • 消息队列独立于进程存在,即使进程结束,消息队列仍然存在。
    • 通过 msgget()msgsnd()msgrcv() 等系统调用操作。
  • 示例
    #include <sys/ipc.h>
    #include <sys/msg.h>
    #include <stdio.h>
    #include <string.h>struct msg_buffer {long msg_type;char msg_text[100];
    };int main() {int msgid = msgget(IPC_PRIVATE, 0666 | IPC_CREAT); // 创建消息队列struct msg_buffer message;message.msg_type = 1;strcpy(message.msg_text, "Hello");msgsnd(msgid, &message, sizeof(message), 0); // 发送消息msgrcv(msgid, &message, sizeof(message), 1, 0); // 接收消息printf("Received: %s\n", message.msg_text);msgctl(msgid, IPC_RMID, NULL); // 删除消息队列return 0;
    }
    

3. 共享内存(Shared Memory)

共享内存允许多个进程共享同一块内存区域,是最高效的 IPC 方式。

  • 特点
    • 数据直接存储在内存中,无需内核介入。
    • 需要同步机制(如信号量)来避免竞争条件。
    • 通过 shmget()shmat()shmdt() 等系统调用操作。
  • 示例
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <stdio.h>
    #include <string.h>int main() {int shmid = shmget(IPC_PRIVATE, 1024, 0666 | IPC_CREAT); // 创建共享内存char *shmaddr = (char *)shmat(shmid, NULL, 0); // 附加共享内存if (fork() == 0) { // 子进程strcpy(shmaddr, "Hello");shmdt(shmaddr); // 分离共享内存} else { // 父进程wait(NULL); // 等待子进程完成printf("Received: %s\n", shmaddr);shmdt(shmaddr); // 分离共享内存shmctl(shmid, IPC_RMID, NULL); // 删除共享内存}return 0;
    }
    

4. 信号量(Semaphore)

信号量用于进程间的同步,避免竞争条件。

  • 特点
    • 通常与共享内存一起使用。
    • 通过 semget()semop() 等系统调用操作。
  • 示例
    #include <sys/ipc.h>
    #include <sys/sem.h>
    #include <stdio.h>int main() {int semid = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT); // 创建信号量semctl(semid, 0, SETVAL, 1); // 初始化信号量值为 1struct sembuf op = {0, -1, 0}; // P 操作semop(semid, &op, 1);printf("Critical section\n");op.sem_op = 1; // V 操作semop(semid, &op, 1);semctl(semid, 0, IPC_RMID); // 删除信号量return 0;
    }
    

5. 套接字(Socket)

套接字是一种通用的 IPC 方式,可以用于本地或网络通信。

  • 特点
    • 支持跨机器的进程通信。
    • 通过 socket()bind()listen()accept() 等系统调用操作。
  • 示例
    #include <sys/socket.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>int main() {int sockfd = socket(AF_UNIX, SOCK_STREAM, 0); // 创建套接字struct sockaddr_un addr;addr.sun_family = AF_UNIX;strcpy(addr.sun_path, "my_socket");bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)); // 绑定地址listen(sockfd, 5); // 监听连接int clientfd = accept(sockfd, NULL, NULL); // 接受连接write(clientfd, "Hello", 6); // 发送数据close(clientfd);close(sockfd);return 0;
    }
    

6. 信号(Signal)

信号是一种异步通信机制,用于通知进程发生了某个事件。

  • 特点
    • 信号是异步的,进程无法预测何时收到信号。
    • 通过 kill() 发送信号,通过 signal()sigaction() 处理信号。
  • 示例
    #include <signal.h>
    #include <stdio.h>
    #include <unistd.h>void handler(int sig) {printf("Received signal: %d\n", sig);
    }int main() {signal(SIGINT, handler); // 注册信号处理函数while (1) {printf("Running...\n");sleep(1);}return 0;
    }
    

总结

IPC 方式特点
管道半双工,适用于亲缘进程。
消息队列全双工,消息有边界。
共享内存高效,需要同步机制。
信号量用于同步,避免竞争条件。
套接字通用,支持本地和网络通信。
信号异步通信,用于事件通知。

根据具体需求选择合适的 IPC 方式,可以高效地实现进程间的通信和同步。


http://www.ppmy.cn/ops/158121.html

相关文章

【DeepSeek】从文本摘要到对话生成:DeepSeek 在 NLP 任务中的实战指南

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

JAVA/RUST/C#/Kotlin 各语言语法糖及特性对比表

各语言语法糖及特性对比表 声明&#xff1a;所有数据均由AI整合生成 语法糖/特性说明GoC#KotlinJava (版本及备注)Rust局部方法嵌套方法&#xff0c;可访问外部局部变量✅✅✅✅✅&#xff08;可用闭包&#xff0c;但用 fn 定义的内嵌函数不能捕获环境&#xff09;lock 语句简化…

Spring Cloud+ Sleuth + Zipkin链路追踪

Spring Cloud+ Sleuth + Zipkin链路追踪 01、Spring Cloud Zipkin链路追踪01、Zipkin的来源和背景02、大型互联网公司为什么需要分布式跟踪系统?设计初衷设计理念03、什么是Zipkin?04、Zipkin的默认搭建方式05、传统日志收集的选型06、微服务的链路追踪 -架构模型07、Zipkin搭…

碰一碰发视频源码技术开发,支持OEM

一、引言 在当今数字化信息快速传播的时代&#xff0c;碰一碰发视频这种便捷的数据交互方式正逐渐走进人们的生活。从技术实现角度来看&#xff0c;其后台开发逻辑是确保整个功能稳定运行的关键。本文将深入剖析碰一碰发视频后台开发的核心逻辑&#xff0c;为开发者提供技术参…

使用Python爬虫获取1688公司档案信息:深入解析

一、引言 在当今的商业环境中&#xff0c;获取供应商的详细信息对于采购决策、市场分析和供应链管理至关重要。1688作为中国领先的B2B电子商务平台&#xff0c;提供了丰富的供应商档案信息。通过使用1688的item_get_company API接口&#xff0c;我们可以方便地获取这些信息。本…

开发一个类似小红书的社交电商平台需要综合技术、产品和运营能力

以下是关键步骤和实现思路&#xff0c;供参考&#xff1a; 一、需求分析与定位 核心功能拆解&#xff1a; 小红书模式 内容社区&#xff08;UGC/PGC&#xff09; 社交互动 电商闭环基础功能矩阵&#xff1a;┌───────────────┬──────────────…

LVDS接口总结--(5)IDELAY3仿真

仿真参考资料如下&#xff1a; https://zhuanlan.zhihu.com/p/386057087 timescale 1 ns/1 ps module tb_idelay3_ctrl();parameter REF_CLK 2.5 ; // 400MHzparameter DIN_CLK 3.3 ; // 300MHzreg ref_clk ;reg …

ssm校园二手交易平台小程序

博主介绍&#xff1a;✌程序猿徐师兄、8年大厂程序员经历。全网粉丝15w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…