Linux命名管道方式
一、命名管道
1、與匿名管道的關(guān)系
命名管道由mkfifo
創(chuàng)建,是一個文件,打開要用open打開
命名管道與匿名管道之間唯一的區(qū)別就是它們創(chuàng)建和打開的方式不同,其他基本上相同
命名管道也只能和有“血緣”的進(jìn)程進(jìn)行通信
2、工作原理
通過mkfifo
創(chuàng)建,會生成一個文件,這就是我們的命名管道文件,它的大小為0
可以看到它的第一列為p,說明它是特殊文件
在我們對普通文件進(jìn)行打開的時候,我們要進(jìn)行的結(jié)構(gòu)其實是這樣的
其中這個刷盤的過程就是文件緩沖區(qū)中的數(shù)據(jù)刷新到硬盤上的過程,而我們的fifo文件即命名管道文件是沒有刷盤的,所以數(shù)據(jù)只會待在文件緩沖區(qū)里,因為在Linux中,多個進(jìn)程打開同一個文件所指向的文件緩沖區(qū)只有一個,所以如果此時再有一個進(jìn)程以讀方式打開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)兩個進(jì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; } } // 打開命名管道以進(jìn)行寫入操作 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]; // 打開命名管道以進(jìn)行讀取操作 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ù)列表的知識,在這里詳細(xì)解釋一下
可變參數(shù)列表允許函數(shù)接受不定數(shù)量和類型的參數(shù),一般在使用時放到最后面,例如我們前面在進(jìn)程中斷中的函數(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ù)列表的訪問,進(jìn)行必要的清理工作
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)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用linux系統(tǒng)具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06Linux網(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-09Linux使用 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)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Linux具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03