Linux系统编程——IPC进程间通信

目录

[一、Linux IPC 的核心种类](#一、Linux IPC 的核心种类)

1.古老的通信方式

[2.IPC 对象通信(system v 标准)](#2.IPC 对象通信(system v 标准))

[3.socket 通信](#3.socket 通信)

二、无名管道(匿名管道)

[1. 核心特性](#1. 核心特性)

2.读写行为规则

3.编程顺序

4.核心函数:pipe

5.示例代码:父子进程通过无名管道通信

三、有名管道

1.核心特性

2.编程顺序

3.核心函数:mkfifo

[4.示例代码:两个无亲缘进程通过 FIFO 通信](#4.示例代码:两个无亲缘进程通过 FIFO 通信)

四、无名管道与有名管道核心对比

五、总结


一、Linux IPC 的核心种类

1.古老的通信方式

是 Linux 早期的基础 IPC 实现,包括:

  • 无名管道
  • 有名管道
  • 信号

2.IPC 对象通信(system v 标准)

基于内核对象的通信方式,常用的有:

  • 消息队列*(使用相对较少,这里不讨论)*
  • 共享内存
  • 信号量集

3.socket 通信

支持跨主机的网络级通信,核心场景是:

  • 网络通信

注:管道的底层实现是队列**,数据遵循 "先进先出" 规则。

二、无名管道(匿名管道)

无名管道对应 pipe,是仅支持亲缘关系进程(如父子、兄弟进程)通信的方式。

1. 核心特性

  • 仅能给亲缘关系进程通信;
  • 半双工工作模式(实际编程按单工使用);
  • 是特殊文件,不支持定位操作(lseek 对管道文件描述符 / 文件指针无效);
  • 依赖文件 IO / 标准 IO 操作。

2.读写行为规则

管道的读写逻辑受缓冲区(默认 64K)和两端状态影响:

  1. 读端存在时,写端持续写超 64K 会阻塞(写得太快);
  2. 写端存在时,读端读空管道会阻塞(读得太快);
  3. 读端关闭后,写端写管道会导致写进程崩溃(管道破裂);
  4. 写端关闭后,读端读完管道内容,read 会返回 0,标志进程间通信结束。

3.编程顺序

创建管道 → fork子进程 → 读写管道 → 关闭管道

4.核心函数:pipe

cpp 复制代码
int pipe(int pipefd[2]);
  • 功能:创建并打开一个无名管道;
  • 参数:pipefd0 是无名管道的固定读端,pipefd1 是固定写端;
  • 返回值:成功返回 0,失败返回 - 1。

5.示例代码:父子进程通过无名管道通信

cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>

int main() 
{
    int pipe_fd[2];
    pid_t pid;
    char read_buf[1024] = {0};
    const char *write_data = "Hello from parent (pipe)!";

    // 1. 创建无名管道
    if (pipe(pipe_fd) == -1) 
    {
        perror("pipe create failed");
        return -1;
    }

    // 2. fork创建子进程(建立亲缘关系)
    pid = fork();
    if (pid == -1) 
    {
        perror("fork failed");
        return -1;
    }

    // 3. 父进程:关闭读端,向管道写数据
    if (pid > 0) 
    {
        close(pipe_fd[0]);  // 父进程仅写,关闭读端
        write(pipe_fd[1], write_data, strlen(write_data));
        close(pipe_fd[1]);  // 写完关闭写端
        wait(NULL);         // 等待子进程执行完毕
    }
    // 4. 子进程:关闭写端,从管道读数据
    else 
    {
        close(pipe_fd[1]);  // 子进程仅读,关闭写端
        read(pipe_fd[0], read_buf, sizeof(read_buf));
        printf("Child read: %s\n", read_buf);
        close(pipe_fd[0]);  // 读完关闭读端
    }

    return 0;
}

三、有名管道

有名管道对应 fifo,突破了亲缘关系限制,支持任意单机进程通信(只要知道管道的文件路径),且在文件系统中可见(有明确的路径名称)。

1.核心特性

  • 可给任意单机进程通信,文件系统中可见(有路径);
  • 基础特性与无名管道一致(半双工、特殊文件、不支持定位等);
  • 额外特性:若管道一端未打开,open 函数会默认阻塞。

2.编程顺序

创建有名管道 → 打开有名管道 → 读写管道 → 关闭管道 → 卸载有名管道

3.核心函数:mkfifo

cpp 复制代码
int mkfifo(const char *pathname, mode_t mode);
  • 功能:在指定路径下创建一个有权限的有名管道文件;
  • 参数:pathname 是有名管道的路径 + 名称,mode 是 8 进制的文件权限(如0666);
  • 返回值:成功返回 0,失败返回 - 1。

4.示例代码:两个无亲缘进程通过 FIFO 通信

  • 写进程(fifo_write.c):
cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>

#define FIFO_PATH "/tmp/my_fifo"

int main() 
{
    // 1. 创建FIFO文件(已存在则忽略)
    if (mkfifo(FIFO_PATH, 0666) == -1) 
    {
        perror("mkfifo failed (ignore if exist)");
    }

    // 2. 打开FIFO文件(写模式)
    int fd = open(FIFO_PATH, O_WRONLY);
    if (fd == -1) 
    {
        perror("open fifo failed");
        return -1;
    }

    // 3. 向FIFO写数据
    const char *msg = "Hello from FIFO write process!";
    write(fd, msg, strlen(msg));
    printf("Write to FIFO: %s\n", msg);

    // 4. 关闭并卸载FIFO
    close(fd);
    unlink(FIFO_PATH);
    return 0;
}
  • 读进程(fifo_read.c):
cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>

#define FIFO_PATH "/tmp/my_fifo"

int main() 
{
    char buf[1024] = {0};

    // 1. 打开FIFO文件(读模式,阻塞等待写端)
    int fd = open(FIFO_PATH, O_RDONLY);
    if (fd == -1) {
        perror("open fifo failed");
        return -1;
    }

    // 2. 从FIFO读数据
    read(fd, buf, sizeof(buf));
    printf("Read from FIFO: %s\n", buf);

    // 3. 关闭FIFO
    close(fd);
    return 0;
}

四、无名管道与有名管道核心对比

对比维度 无名管道(pipe) 有名管道(FIFO)
通信范围 仅亲缘关系进程 任意单机进程
文件系统可见性 不可见(内核维护) 可见(有路径的特殊文件)
打开特性 fork 后继承文件描述符 一端未打开时 open 默认阻塞
生命周期 随进程退出自动释放 需手动 unlink 删除
创建方式 pipe () 函数 mkfifo () 函数

五、总结

  1. 管道是 Linux 最基础的 IPC 机制,核心分为无名管道(pipe)和有名管道(FIFO)两类,均为半双工、基于队列的特殊文件;
  2. 无名管道仅支持亲缘进程通信,无需手动清理;有名管道支持任意单机进程通信,需手动创建 / 删除;
  3. 管道读写需遵循核心规则,尤其注意 "读 / 写端关闭" 后的行为,避免进程崩溃或数据异常。
相关推荐
lisanmengmeng几秒前
搭建elk环境并接入frostmourne,实现监控报警效果(一)
运维·elk·jenkins
王志来1379447300826 分钟前
聚焦五大核心场景:工控服务器机箱平台的垂直深耕之路
运维·服务器·python
ii_best41 分钟前
手机自动化脚本按键精灵实战:随机布局安全数字键盘的自动化输入方案
android·运维·ios·自动化·手机
鲁邦通物联网42 分钟前
充电站底层脱机DLB引擎解构:基于Linux调度的边缘计算网关并发控制实战
linux·运维·人工智能·边缘计算·边缘计算网关·5g数采·工业级边缘计算网关
zhonyu鱼1 小时前
RustDesk:开源免费的远程桌面软件,可自建服务器掌控全部数据
运维·服务器·开源
便利店10241 小时前
边界与远程:墙、洞与加密通道
运维·服务器·防火墙·acl·nat
LHX sir1 小时前
HubPort 和 SCADA / MES 是什么关系?是替代还是增强
网络·工业互联网·scada·mes
Zhang~Ling1 小时前
Linux多线程互斥锁:从现象到原理解析
linux·运维·网络
KaiwuDB1 小时前
KaiwuDB 运维实战 03:双副本仲裁节点部署与高可用实践
运维·时序数据库·raft·kaiwudb·数据库运维·双副本高可用·仲裁节点
ambition202424 小时前
操作系统同步:读者-写者问题与读写公平法详解(附每个 PV 操作含义)
linux·开发语言·数据结构·unix