【Linux】命名管道

发布时间 - 2025-04-18 00:00:00    点击率:

一、命名管道

1、与匿名管道的关系

命名管道通过mkfifo命令创建,是一个文件,需要使用open函数来打开。命名管道与匿名管道的主要区别在于它们的创建和打开方式不同,其他方面基本相同。命名管道也仅能与有“血缘”关系的进程进行通信。

2、工作原理

通过mkfifo命令创建命名管道时,会生成一个大小为0的文件,这就是命名管道文件。

可以看到文件的第一列为p,表示它是特殊文件。在打开普通文件时,操作流程包括文件缓冲区中的数据刷新到硬盘的过程。然而,命名管道文件不涉及刷盘操作,数据仅停留在文件缓冲区中。由于在Linux中,多个进程打开同一个文件会共享同一个文件缓冲区,因此如果有另一个进程以读的方式打开命名管道文件,它们将通过文件缓冲区建立连接,形成与匿名管道相同的结构。

3、系统调用接口

#include 
#include 
int mkfifo(const char *filename, mode_t mode);
// filename:文件路径
// mode:文件权限
// 返回值:如果管道创建成功返回0,如果失败返回-1并设置errno

4、实现两个进程间通信

tests.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define FIFO_NAME "myfifo"
#define BUFFER_SIZE 256
int main(){
    char message[BUFFER_SIZE];
    // 创建命名管道
    if (mkfifo(FIFO_NAME, 0666) == -1)
    {
        if (errno != EEXIST)
        {
            perror("mkfifo");
            return 1;
        }
    }
    // 打开命名管道以进行写入操作
    int fd = open(FIFO_NAME, O_WRONLY);
    if (fd == -1)
    {
        perror("open");
        return 1;
    }
    // 获取用户输入的消息
    while (1)
    {
        printf("Enter a message to send: ");
        fgets(message, BUFFER_SIZE, stdin);
        message[strcspn(message, "\n")] = 0; // 移除换行符
        // 向命名管道写入消息
        if (write(fd, message, strlen(message)) == -1)
        {
            perror("write");
            close(fd);
            return 1;
        }
        printf("Message sent successfully.\n");
    }
    // 关闭命名管道
    close(fd);
    return 0;
}

testr.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define FIFO_NAME "myfifo"
#define BUFFER_SIZE 256
int main(){
    int fd;
    char buffer[BUFFER_SIZE];
    // 打开命名管道以进行读取操作
    fd = open(FIFO_NAME, O_RDONLY);
    if (fd == -1)
    {
        perror("open");
        return 1;
    }
    while (1)
    {
        // 从命名管道读取消息
        ssize_t bytes_read = read(fd, buffer, BUFFER_SIZE - 1);
        if (bytes_read == -1)
        {
            perror("read");
            close(fd);
            return 1;
        }
        buffer[bytes_read] = '\0'; // 添加字符串结束符
        // 输出接收到的消息
        if(buffer[0] == 0)  break;
        printf("Received message: %s\n", buffer);
    }
    // 关闭命名管道
    close(fd);
    // 删除命名管道
    if (unlink(FIFO_NAME) == -1)
    {
        perror("unlink");
        return 1;
    }
    return 0;
}

二、可变参数列表

我们将利用命名管道编写日志文件,这需要使用可变参数列表的知识,下面详细解释一下。

可变参数列表允许函数接受不确定数量和类型的参数,通常放在参数列表的最后。例如,我们之前在进程中断中的函数:int execl(const char *path, const char *arg, ...);,我们有“表”的概念,只要是一个表,最后一个元素一定是NULL,用来标志表的结束。

与此相关的关键元素包括以下四个(头文件stdarg.h):

va_listva_list是一种自定义类型(通常为指针类型),用于声明一个变量,该变量将指向可变参数列表。

va_start宏:其作用是初始化va_list类型的变量,使其指向可变参数列表的第一个参数。

void va_start(va_list ap, last);
// ap:va_list 类型的变量
// last:可变参数列表之前的最后一个固定参数

va_arg宏:此宏用于从可变参数列表中获取下一个参数,并将va_list指针移动到下一个参数的位置。

type va_arg(va_list ap, type);
// ap:va_list 类型的变量
// type:要获取的参数的类型

va_end宏:该宏用于结束对可变参数列表的访问,进行必要的清理工作。

void va_end(va_list ap);
// ap:之前用 va_start 初始化过的 va_list 变量

今日分享就到这里~


# linux  # ai  # 区别  # c#  # NULL  # const  # 可变参数  # char  # int  # 指针  # 接口  # 指针类型  # 是一个  # 区中  # 是一种  # 放在  # 第一个  # 多个  # 这就是  # 它是  # 并将  # 与此 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何在建站之星网店版论坛获取技术支持?  php结合redis实现高并发下的抢购、秒杀功能的实例  如何在景安云服务器上绑定域名并配置虚拟主机?  iOS验证手机号的正则表达式  Laravel N+1查询问题如何解决_Eloquent预加载(Eager Loading)优化数据库查询  LinuxShell函数封装方法_脚本复用设计思路【教程】  香港服务器租用每月最低只需15元?  青岛网站建设如何选择本地服务器?  Python自然语言搜索引擎项目教程_倒排索引查询优化案例  深入理解Android中的xmlns:tools属性  在线制作视频网站免费,都有哪些好的动漫网站?  如何使用 jQuery 正确渲染 Instagram 风格的标签列表  Laravel如何编写单元测试和功能测试?(PHPUnit示例)  微信小程序 scroll-view组件实现列表页实例代码  详解阿里云nginx服务器多站点的配置  Laravel怎么解决跨域问题_Laravel配置CORS跨域访问  如何正确选择百度移动适配建站域名?  Laravel怎么处理异常_Laravel自定义异常处理与错误页面教程  如何在企业微信快速生成手机电脑官网?  Laravel如何使用Telescope进行调试?(安装和使用教程)  如何在云虚拟主机上快速搭建个人网站?  如何在万网ECS上快速搭建专属网站?  谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复  Laravel如何发送邮件和通知_Laravel邮件与通知系统发送步骤  js代码实现下拉菜单【推荐】  Chrome浏览器标签页分组怎么用_谷歌浏览器整理标签页技巧【效率】  HTML5段落标签p和br怎么选_文本排版常用标签对比【解答】  Claude怎样写结构化提示词_Claude结构化提示词写法【教程】  Laravel如何自定义错误页面(404, 500)?(代码示例)  Laravel Eloquent关联是什么_Laravel模型一对一与一对多关系精讲  rsync同步时出现rsync: failed to set times on “xxxx”: Operation not permitted  Laravel怎么配置自定义表前缀_Laravel数据库迁移与Eloquent表名映射【步骤】  MySQL查询结果复制到新表的方法(更新、插入)  laravel怎么为应用开启和关闭维护模式_laravel应用维护模式开启与关闭方法  nodejs redis 发布订阅机制封装实现方法及实例代码  Java解压缩zip - 解压缩多个文件或文件夹实例  jQuery中的100个技巧汇总  如何用西部建站助手快速创建专业网站?  uc浏览器二维码扫描入口_uc浏览器扫码功能使用地址  Laravel怎么使用artisan命令缓存配置和视图  微信小程序 wx.uploadFile无法上传解决办法  如何在Tomcat中配置并部署网站项目?  英语简历制作免费网站推荐,如何将简历翻译成英文?  Laravel如何使用Blade组件和插槽?(Component代码示例)  Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用  Laravel全局作用域是什么_Laravel Eloquent Global Scopes应用指南  个人网站制作流程图片大全,个人网站如何注销?  Laravel如何实现URL美化Slug功能_Laravel使用eloquent-sluggable生成别名【方法】  HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】  Laravel如何实现多语言支持_Laravel本地化与国际化(i18n)配置教程