使用Linux命名管道(FIFO)实现无血缘关系进程间的通信

 更新时间:2025年11月24日 09:39:48   作者:郝学胜-神的一滴  
在Linux系统中,进程间通信(IPC)是编程中常见的需求,传统上,有血缘关系的进程(如父子进程)可以通过管道进行通信,但无血缘关系的进程则需要其他IPC机制,本文将介绍如何使用Linux命名管道(FIFO)实现无血缘关系进程间的通信,需要的朋友可以参考下

1. 引言

在Linux系统中,进程间通信(IPC)是编程中常见的需求。传统上,有血缘关系的进程(如父子进程)可以通过管道进行通信,但无血缘关系的进程则需要其他IPC机制。本文将介绍如何使用Linux命名管道(FIFO)实现无血缘关系进程间的通信,展示其原理、实现方法和实际应用场景。

2. 命名管道(FIFO)概述

命名管道(FIFO, First In First Out)是一种特殊的文件类型,它允许不相关的进程之间进行通信。与匿名管道不同,命名管道不要求通信的进程之间有血缘关系,因此可以用于任意两个进程之间的通信。

命名管道的主要特点包括:

  1. 命名管道存在于文件系统中,可以通过路径名访问
  2. 命名管道是单向的,数据只能在一个方向上流动
  3. 命名管道不要求通信的进程之间有血缘关系
  4. 命名管道在内核中维护,不占用磁盘空间
  5. 当所有进程关闭了命名管道的文件描述符时,命名管道的内容会被销毁

3. 创建和使用命名管道

3.1 使用命令行创建命名管道

可以使用mkfifo命令在命令行中创建命名管道:

mkfifo my_pipe

这将在当前目录下创建一个名为my_pipe的命名管道文件。

3.2 使用C语言创建命名管道

在C语言中,可以使用mkfifo函数来创建命名管道:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
    const char *fifo_path = "/tmp/my_fifo";
    
    // 创建命名管道
    if (mkfifo(fifo_path, 0666) == -1) {
        perror("mkfifo");
        exit(EXIT_FAILURE);
    }
    
    printf("Named pipe created: %s\n", fifo_path);
    return 0;
}

4. 实现无血缘关系进程间通信

4.1 写进程示例

下面是一个写进程的示例代码,它向命名管道写入数据:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int main() {
    const char *fifo_path = "/tmp/my_fifo";
    const char *message = "Hello from writer process!";
    
    // 以只写方式打开命名管道
    int fd = open(fifo_path, O_WRONLY);
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }
    
    // 向命名管道写入数据
    write(fd, message, strlen(message));
    
    printf("Message sent: %s\n", message);
    
    // 关闭命名管道
    close(fd);
    
    return 0;
}

4.2 读进程示例

下面是一个读进程的示例代码,它从命名管道读取数据:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define BUFFER_SIZE 256

int main() {
    const char *fifo_path = "/tmp/my_fifo";
    char buffer[BUFFER_SIZE];
    
    // 以只读方式打开命名管道
    int fd = open(fifo_path, O_RDONLY);
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }
    
    // 从命名管道读取数据
    int bytes_read = read(fd, buffer, BUFFER_SIZE - 1);
    if (bytes_read == -1) {
        perror("read");
        exit(EXIT_FAILURE);
    }
    
    buffer[bytes_read] = '\0'; // 确保字符串以null结尾
    printf("Message received: %s\n", buffer);
    
    // 关闭命名管道
    close(fd);
    
    return 0;
}

4.3 运行示例

要运行这个示例,首先需要创建命名管道,然后分别编译和运行写进程和读进程。需要注意的是,读进程应该先于写进程启动,因为读进程在打开命名管道时会阻塞,直到有另一个进程以写方式打开同一个命名管道。

# 创建命名管道
mkfifo /tmp/my_fifo

# 编写进程
gcc writer.c -o writer
./writer &

# 读进程
gcc reader.c -o reader
./reader

5. 命名管道的高级特性

5.1 非阻塞打开命名管道

默认情况下,以只读或只写方式打开命名管道会导致进程阻塞,直到有另一个进程以相反的方式打开同一个命名管道。为了避免阻塞,可以在打开命名管道时指定O_NONBLOCK标志:

// 非阻塞方式打开命名管道
int fd = open(fifo_path, O_RDONLY | O_NONBLOCK);

5.2 使用select或poll监控命名管道

可以使用selectpoll函数来监控命名管道的可读性或可写性,从而避免阻塞:

#include <sys/select.h>
#include <poll.h>

// 使用select监控命名管道
fd_set read_fds;
struct timeval timeout;

FD_ZERO(&read_fds);
FD_SET(fd, &read_fds);

timeout.tv_sec = 5; // 5秒超时
timeout.tv_usec = 0;

int ret = select(fd + 1, &read_fds, NULL, NULL, &timeout);
if (ret > 0) {
    if (FD_ISSET(fd, &read_fds)) {
        // 命名管道可读
        // 执行读取操作
    }
}

// 使用poll监控命名管道
struct pollfd fds;

fds.fd = fd;
fds.events = POLLIN; // 监控可读事件

int ret = poll(&fds, 1, 5000); // 5秒超时
if (ret > 0) {
    if (fds.revents & POLLIN) {
        // 命名管道可读
        // 执行读取操作
    }
}

6. 命名管道的注意事项

  1. 单向通信:命名管道是单向的,如果需要双向通信,需要创建两个命名管道。
  2. 阻塞行为:默认情况下,打开命名管道会导致进程阻塞,直到有另一个进程以相反的方式打开同一个命名管道。
  3. 数据完整性:写入命名管道的数据可能会被截断,特别是在写入大量数据时。因此,需要确保数据的完整性。
  4. 错误处理:在使用命名管道时,需要正确处理各种错误情况,如管道不存在、权限不足等。
  5. 资源清理:使用完命名管道后,应该关闭文件描述符,并在不需要时删除命名管道文件。

7. 实际应用场景

命名管道在实际开发中有多种应用场景,例如:

  1. 日志收集系统:多个不同的应用程序可以将日志写入同一个命名管道,而日志收集进程则从该管道读取日志。
  2. 服务间通信:在微服务架构中,可以使用命名管道作为轻量级的进程间通信机制。
  3. 命令行工具:命令行工具可以使用命名管道接收来自其他程序的输入或发送输出到其他程序。
  4. 测试框架:在测试过程中,可以使用命名管道模拟不同组件之间的交互。

8. 总结

本文介绍了Linux命名管道(FIFO)的基本概念、创建方法以及如何使用它来实现无血缘关系进程间的通信。通过示例代码,展示了如何创建命名管道、打开和关闭命名管道,以及如何使用命名管道进行进程间通信。此外,还介绍了命名管道的高级特性和注意事项。

命名管道是一种简单而有效的进程间通信机制,特别适用于不相关的进程之间的通信。通过合理使用命名管道,可以实现进程间的数据交换和同步,提高程序的灵活性和可扩展性。

以上就是使用Linux命名管道(FIFO)实现无血缘关系进程间的通信的详细内容,更多关于Linux命名管道无血缘关系通信的资料请关注脚本之家其它相关文章!

相关文章

  • Linux使用mutt命令行发送邮件的详细流程

    Linux使用mutt命令行发送邮件的详细流程

    本文介绍了如何在 Linux 或类 Unix 系统中使用 mutt 命令行邮件客户端进行邮件发送,mutt 以其轻量、灵活的特点,广泛应用于服务器自动化通知、备份提醒和系统告警等场景,需要的朋友可以参考下
    2025-11-11
  • ubuntu 添加中文支持实现方法

    ubuntu 添加中文支持实现方法

    这篇文章主要介绍了ubuntu 添加中文支持实现方法的相关资料,需要的朋友可以参考下
    2016-12-12
  • Linux日志查看和分析过程

    Linux日志查看和分析过程

    Linux日志是系统运行状态的重要记录,包括系统启动、服务运行、用户操作和安全事件等信息,对于故障排查、安全审计和系统维护至关重要,文章详细介绍了Linux日志的主要类型、存储位置及作用,并提供了常用的查看和分析命令及工具
    2026-01-01
  • XShell免费版的安装配置教程及使用保姆级教程

    XShell免费版的安装配置教程及使用保姆级教程

    XShell 是一种流行且简单的网络程序,旨在模拟虚拟终端,这篇文章主要介绍了XShell免费版的安装配置教程以及使用教程,需要的朋友可以参考下
    2022-08-08
  • Linux虚拟主机面板 kloxo安装及汉化教程分享

    Linux虚拟主机面板 kloxo安装及汉化教程分享

    Kloxo的前身是lxadmin,是一款免费的虚拟主机管理系统,安装简单,功能强大,可以快速地在red hat,centos系列linux系统的主机上搭建LAMP环境。新版以完全解除限制无限域名绑定
    2012-09-09
  • Centos服务器搭建简单的ftp服务实践

    Centos服务器搭建简单的ftp服务实践

    文章介绍了在Centos服务器上搭建简单的FTP服务,并在私网客户端通过wget、curl和lftp三个工具下载FTP网页内容的过程
    2025-12-12
  • 详解Centos中完全删除mysql的方法

    详解Centos中完全删除mysql的方法

    本篇文章主要介绍了Centos中完全删除mysql的方法,非常具有实用价值,需要的朋友可以参考下。
    2017-01-01
  • Linux集群/分布式环境下session处理的五种策略详解

    Linux集群/分布式环境下session处理的五种策略详解

    这篇文章主要给大家介绍了关于Linux集群/分布式环境下session处理的五种策略,文中通过示例代码及图片介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-09-09
  • 详解linux 关机命令总结

    详解linux 关机命令总结

    本篇文章主要介绍了linux 关机命令总结,linux下常用的关机命令有:shutdown、halt、poweroff、init,有兴趣的可以了解一下。
    2016-12-12
  • 在Linux系统中检查CPU和内存使用情况的常用方法

    在Linux系统中检查CPU和内存使用情况的常用方法

    在 Linux 系统中,CPU 和内存资源的高负载可能会导致系统性能下降,甚至使服务器无法正常响应请求,因此本文将详细介绍如何在 Linux 系统中检查 CPU 和内存的使用情况,并提供针对性解决方案,需要的朋友可以参考下
    2026-02-02

最新评论