一、命名管道
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_list:va_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 变量
今日分享就到这里~










