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]);
  • 功能:创建并打开一个无名管道;
  • 参数:pipefd[0] 是无名管道的固定读端,pipefd[1] 是固定写端;
  • 返回值:成功返回 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. 管道读写需遵循核心规则,尤其注意 "读 / 写端关闭" 后的行为,避免进程崩溃或数据异常。
相关推荐
violet-lz2 小时前
【Linux】VMware虚拟机中的Ubuntu操作系统主文件夹扩容
linux·运维·ubuntu
HunterMichaelG2 小时前
【openSSH】Linux openEuler-22.03-x86_64升级openSSH至10.2p1版本
linux·运维·服务器
雾江流2 小时前
肉包 1.4.0 | 豆包AI手机平替,开源免费,AI自动化
运维·人工智能·自动化·软件工程
再睡一夏就好3 小时前
深入解析Linux页表:从虚拟地址到物理内存的映射艺术
linux·运维·服务器·c语言·c++·页表·缺页异常
Sinowintop3 小时前
领航自贸港新赛道:EDI 重构企业跨境业务高效增长体系
大数据·运维·服务器·edi·数据交换·国产edi·海南自贸港
2501_915106323 小时前
HTTP 协议详解,HTTP 协议在真实运行环境中的表现差异
网络·网络协议·http·ios·小程序·uni-app·iphone
两千次3 小时前
3d线扫获取图片
运维·服务器
_w_z_j_3 小时前
Linux----线程互斥与同步
linux·运维·开发语言
风华同学3 小时前
【Linux驱动篇】字符设备驱动开发
linux·运维·驱动开发