Linux命名管道方式
一、命名管道
1、與匿名管道的關(guān)系
命名管道由mkfifo創(chuàng)建,是一個文件,打開要用open打開
命名管道與匿名管道之間唯一的區(qū)別就是它們創(chuàng)建和打開的方式不同,其他基本上相同
命名管道也只能和有“血緣”的進程進行通信
2、工作原理
通過mkfifo創(chuàng)建,會生成一個文件,這就是我們的命名管道文件,它的大小為0

可以看到它的第一列為p,說明它是特殊文件
在我們對普通文件進行打開的時候,我們要進行的結(jié)構(gòu)其實是這樣的

其中這個刷盤的過程就是文件緩沖區(qū)中的數(shù)據(jù)刷新到硬盤上的過程,而我們的fifo文件即命名管道文件是沒有刷盤的,所以數(shù)據(jù)只會待在文件緩沖區(qū)里,因為在Linux中,多個進程打開同一個文件所指向的文件緩沖區(qū)只有一個,所以如果此時再有一個進程以讀方式打開fifo文件,它們之間就會以文件緩沖區(qū)作為紐帶連接,形成了一個結(jié)構(gòu),這個結(jié)構(gòu),與我們以前所講的匿名管道形成的管道結(jié)構(gòu)是一摸一樣的
3、系統(tǒng)調(diào)用接口
#include <sys/types.h> #include <sys/stat.h> int mkfifo(const char *filename, mode_t mode); // filename:文件路徑 // mode:文件權(quán)限 // 返回值:如果管道創(chuàng)建成功返回0,如果失敗返回-1并設(shè)置errno
4、實現(xiàn)兩個進程間通信
- tests.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#define FIFO_NAME "myfifo"
#define BUFFER_SIZE 256
int main()
{
char message[BUFFER_SIZE];
// 創(chuàng)建命名管道
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");
}
// 關(guān)閉命名管道
close(fd);
return 0;
}- testr.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#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'; // 添加字符串結(jié)束符
// 輸出接收到的消息
if(buffer[0] == 0) break;
printf("Received message: %s\n", buffer);
}
// 關(guān)閉命名管道
close(fd);
// 刪除命名管道
if (unlink(FIFO_NAME) == -1)
{
perror("unlink");
return 1;
}
return 0;
}二、可變參數(shù)列表
我們后面要借助命名管道來寫一個日志文件,我們需要用到可變參數(shù)列表的知識,在這里詳細解釋一下
可變參數(shù)列表允許函數(shù)接受不定數(shù)量和類型的參數(shù),一般在使用時放到最后面,例如我們前面在進程中斷中的函數(shù):
int execl(const char *path, const char *arg, ...);
我們現(xiàn)在有“表”的概念,只要是一個表,最后一個元素一定是NULL,來標(biāo)志著這個表的結(jié)束
與其相關(guān)的關(guān)鍵元素有以下四個:(頭文件stdarg.h)
va_list:va_list 是一種自定義類型(通常為指針類型),用于聲明一個變量,該變量將指向可變參數(shù)列表va_start宏:其作用是初始化 va_list 類型的變量,讓它指向可變參數(shù)列表的第一個參數(shù)
void va_start(va_list ap, last); //ap:va_list 類型的變量 //last:可變參數(shù)列表之前的最后一個固定參數(shù)
va_arg宏:此宏用于從可變參數(shù)列表中獲取下一個參數(shù),并將 va_list 指針移動到下一個參數(shù)的位置
type va_arg(va_list ap, type); //ap:va_list 類型的變量 //type:要獲取的參數(shù)的類型
va_end宏:該宏用于結(jié)束對可變參數(shù)列表的訪問,進行必要的清理工作
void va_end(va_list ap); //ap:之前用 va_start 初始化過的 va_list 變量
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
crontab執(zhí)行結(jié)果未通過發(fā)送mail通知用戶的方法
這篇文章主要給大家介紹了關(guān)于crontab執(zhí)行結(jié)果未通過發(fā)送mail通知用戶的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用linux系統(tǒng)具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
Linux網(wǎng)絡(luò)配置和監(jiān)控命令總結(jié)
本文介紹了Linux系統(tǒng)中常用的網(wǎng)絡(luò)配置和監(jiān)控命令,包括ifconfig、hostname、route、netstat、ss、lsof、ping、traceroute、nslookup等命令的使用方法和作用,適用于系統(tǒng)管理員在日常管理和故障排查中的網(wǎng)絡(luò)操作2024-09-09
Linux使用 iftop 實時監(jiān)控網(wǎng)卡的流量
iftop可以用來監(jiān)控網(wǎng)卡的實時流量(可以指定網(wǎng)段)、反向解析IP、顯示端口信息等。這篇文章主要介紹了Linux 實時網(wǎng)卡流量監(jiān)控,需要的朋友可以參考下2019-11-11
在Linux中如何查看可用的網(wǎng)絡(luò)接口詳解
這篇文章主要給大家介紹了關(guān)于在Linux中如何查看可用的網(wǎng)絡(luò)接口的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用Linux具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03

