飞凌嵌入式ElfBoard-进程间的通信之命名管道

命名管道(FIFO)与匿名管道(PIPE)的不同的地方在于,命名管道在文件系统中具有一个名字,可以使得不相关的进程也能通过该名字访问管道。

在Linux中可以使用mkfifo命令和mknod命令创建命名管道;mkfifo专用于创建命名管道(FIFO)。mknod命令用于创建设备文件,字符设备,块设备或FIFO。

mkfifo 命令非常简单,用法如下:

mkfifo <fifo_name>

mknod 命令稍微复杂一些,因为它需要指定设备类型。创建命名管道的命令如下:

mknod <fifo_name> p

例如创建一个命名管道my_fifo

mkfifo my_fifo

可以通过echo和cat命令操作FIFO进行读写,在两个终端中分别执行下面两条命令,执行cat的终端就会收到test!的信息;执行cat my_fifo后命名管道是阻塞的,直到有进程将数据写入my_fifo。

cat my_fifo

echo "test!" > my_fifo

在应用程序中也可以使用mkfifo命令的同名函数mkfifo()来创建FIFO;mknod()是比较老的函数,而使用mkfifo()函数更加简单和规范,所以建议在可能的情况下,尽量使用mkfifo()而不是mknod()。

mkfifo专用于创建命名管道(FIFO)。

1 .头文件

#include <sys/types.h>

#include <sys/stat.h>

2 .函数原型

int mkfifo(const char *pathname, mode_t mode);

3 .参数

pathname:表示要创建的命名管道的路径和名称。是一个字符指针,指定命名管道的路径,可以是相对路径或绝对路径。例如,/tmp/my_fifo 或 my_fifo(在当前目录下)。

mode:指定文件的权限模式。是一个 mode_t 类型的值,用于指定 FIFO 的访问权限,与 open() 或 chmod() 使用的权限模式类似。

权限值一般包括:

S_IRUSR (0400):用户可读

S_IWUSR (0200):用户可写

S_IRGRP (0040):组可读

S_IWGRP (0020):组可写

S_IROTH (0004):其他用户可读

S_IWOTH (0002):其他用户可写

例如,0666 表示用户、组和其他用户都可读写。

4 .返回值

函数成功返回 0,否则返回-1 并设置 errno,与其他文件一样,FIFO文件也可以使用open、read、write、close调用来进行读写。

5 .示例:通过mkfifo()函数创建命名管道通信

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <errno.h> int main() { const char *fifo_path = "/tmp/my_fifo"; char buffer256; pid_t pid; // 创建命名管道 if (mkfifo(fifo_path, 0666) == -1) { if (errno != EEXIST) { perror("mkfifo"); exit(EXIT_FAILURE); } } // 创建子进程 pid = fork(); if (pid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (pid == 0) { // 子进程:写入数据 int fifo_fd = open(fifo_path, O_WRONLY); if (fifo_fd == -1) { perror("open for write"); exit(EXIT_FAILURE); } const char *message = "Hello from child process!"; write(fifo_fd, message, strlen(message) + 1); // +1 to include '\0' close(fifo_fd); printf("Child process: Wrote message to FIFO\n"); } else { // 父进程:读取数据 int fifo_fd = open(fifo_path, O_RDONLY); if (fifo_fd == -1) { perror("open for read"); exit(EXIT_FAILURE); } read(fifo_fd, buffer, sizeof(buffer)); printf("Parent process: Read message from FIFO: %s\n", buffer); close(fifo_fd); // 删除管道文件 unlink(fifo_path); } return 0; } |

6 .运行结果

|--------------------------------------------------------------------------------------------------------|
| Parent process: Read message from FIFO: Hello from child process! Child process: Wrote message to FIFO |

7 .程序解析

使用 mkfifo() 创建命名管道。父进程和子进程通过 fork() 创建,并通过 open()、write()、read() 函数进行通信。父进程在读取完数据后,删除命名管道文件。

将这个程序中的父子进程拆成两个程序,编译之后打开两个终端执行;writer 程序通过 mkfifo() 确保管道存在,然后打开管道写入数据。reader 程序打开管道读取数据,并在读取完数据后删除管道文件。

8 .写入数据的程序(writer.c)

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <errno.h> int main() { const char *fifo_path = "/tmp/my_fifo"; // 创建命名管道 if (mkfifo(fifo_path, 0666) == -1) { if (errno != EEXIST) { perror("mkfifo"); exit(EXIT_FAILURE); } } // 打开管道进行写入 int fifo_fd = open(fifo_path, O_WRONLY); if (fifo_fd == -1) { perror("open for write"); exit(EXIT_FAILURE); } const char *message = "Hello from writer program!"; write(fifo_fd, message, strlen(message) + 1); // +1 to include '\0' printf("Writer: Message written to FIFO\n"); close(fifo_fd); return 0; } |

9 .读取数据的程序(reader.c)

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <errno.h> int main() { const char *fifo_path = "/tmp/my_fifo"; char buffer256; // 打开管道进行读取 int fifo_fd = open(fifo_path, O_RDONLY); if (fifo_fd == -1) { perror("open for read"); exit(EXIT_FAILURE); } read(fifo_fd, buffer, sizeof(buffer)); printf("Reader: Message read from FIFO: %s\n", buffer); close(fifo_fd); // 删除管道文件 unlink(fifo_path); return 0; } |

相关推荐
Web极客码3 分钟前
突破并发瓶颈:云端高性能架构如何赋能海外 AI Agent 矩阵的高效产出
服务器·人工智能·架构
一个有温度的技术博主6 分钟前
【VulnHub 实战】DC-1 靶机渗透测试笔记(一):信息收集与主机发现
服务器·网络·笔记
科技大视界1 小时前
投资AI项目,传统尽调不够用了——李章虎律师拆解算法、数据、算力三大雷区
人工智能·算法·数据挖掘
郝学胜-神的一滴1 小时前
算法实战:最小k个数——大顶堆的优雅解法
开发语言·数据结构·c++·python·程序人生·算法·排序算法
Irissgwe1 小时前
算法滑动窗口
数据结构·算法
bksczm2 小时前
linux之线程概念和控制
linux·开发语言·c++
怪兽学LLM2 小时前
LeetCode 105. 从前序与中序遍历序列构造二叉树:分治递归思路详解
算法·leetcode·职场和发展
可编程芯片开发2 小时前
基于PI控制的三相整流器控制系统的simulink建模与仿真,包含超级电容充电和电机
算法
爱网络爱Linux2 小时前
Linux proc 目录安全加固
linux·运维·rhce·rhca·红帽认证·proc 目录安全加固
hehelm2 小时前
Linux网络编程—TCP字典翻译系统
linux·开发语言·网络·c++·tcp/ip