飞凌嵌入式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; } |

相关推荐
To_OC19 小时前
LC 1 两数之和:面试第一道必考题,暴力解法直接被面试官 pass
javascript·算法·leetcode
鱼鱼不愚与1 天前
《原来如此 | 第01期:为什么导航软件能预测红绿灯倒计时?》
算法
复杂网络1 天前
论最小 Agent 计算机的形态
算法
Sokach10151 天前
Linux Shell 脚本从零到能用:一个新手的一天学习总结
linux
kisshyshy2 天前
🍦 雪糕、食堂、火车厢:三幅漫画吃透栈、队列与链表
javascript·算法
AlfredZhao2 天前
Docker 容器时区不对,`timedatectl` 不存在怎么办?
linux·timezone
猿人谷2 天前
不只是 CPU 阈值:STAR 如何用 GAT + Transformer 做容器级自动扩缩容?
人工智能·算法
复杂网络2 天前
Stable Diffusion 视觉大模型微调技术深度调研
算法
复杂网络2 天前
基于 Stable Diffusion 架构的视觉大模型代表性工作与原理深度解析
算法