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

相关推荐
AOwhisky1 小时前
Ceph系列第六期:Ceph 文件系统(CephFS)精讲
linux·运维·网络·笔记·ceph
啦哈拉哈1 小时前
Leetcode题解记录-hot100(81-100)
算法·leetcode·职场和发展
csdn_aspnet1 小时前
Java 霍尔分区算法(Hoare‘s Partition Algorithm)
java·开发语言·算法
诸葛务农2 小时前
道路行驶条件下电动汽车永磁电机的有效使用寿命及永磁体的失效和回收再利用(下)
java·开发语言·算法
snow@li2 小时前
AI:理解 大数据、算法、算力、电力、生成式AI、token 之间的关系
大数据·人工智能·算法
Starry-sky(jing)2 小时前
# Linux 下 Qt 应用无障碍自动化:记一次wx无人值守系统的架构演进
linux·qt·自动化
荒--2 小时前
apt dpkg 命令详解
linux·服务器
小智老师PMP2 小时前
零基础能不能考PMP?零基础专属学习路径+全套扶持体系
学习·算法·职场和发展·软件工程·求职招聘·敏捷流程
Dillon Dong2 小时前
【风电控制】FPGA采集Vdc的ADC增益系数解析——从数字码到实际电压的桥梁
算法·fpga开发·变流器·风电控制