使用Linux命名管道(FIFO)實(shí)現(xiàn)無(wú)血緣關(guān)系進(jìn)程間的通信
1. 引言
在Linux系統(tǒng)中,進(jìn)程間通信(IPC)是編程中常見(jiàn)的需求。傳統(tǒng)上,有血緣關(guān)系的進(jìn)程(如父子進(jìn)程)可以通過(guò)管道進(jìn)行通信,但無(wú)血緣關(guān)系的進(jìn)程則需要其他IPC機(jī)制。本文將介紹如何使用Linux命名管道(FIFO)實(shí)現(xiàn)無(wú)血緣關(guān)系進(jìn)程間的通信,展示其原理、實(shí)現(xiàn)方法和實(shí)際應(yīng)用場(chǎng)景。
2. 命名管道(FIFO)概述
命名管道(FIFO, First In First Out)是一種特殊的文件類型,它允許不相關(guān)的進(jìn)程之間進(jìn)行通信。與匿名管道不同,命名管道不要求通信的進(jìn)程之間有血緣關(guān)系,因此可以用于任意兩個(gè)進(jìn)程之間的通信。
命名管道的主要特點(diǎn)包括:
- 命名管道存在于文件系統(tǒng)中,可以通過(guò)路徑名訪問(wèn)
- 命名管道是單向的,數(shù)據(jù)只能在一個(gè)方向上流動(dòng)
- 命名管道不要求通信的進(jìn)程之間有血緣關(guān)系
- 命名管道在內(nèi)核中維護(hù),不占用磁盤空間
- 當(dāng)所有進(jìn)程關(guān)閉了命名管道的文件描述符時(shí),命名管道的內(nèi)容會(huì)被銷毀
3. 創(chuàng)建和使用命名管道
3.1 使用命令行創(chuàng)建命名管道
可以使用mkfifo命令在命令行中創(chuàng)建命名管道:
mkfifo my_pipe
這將在當(dāng)前目錄下創(chuàng)建一個(gè)名為my_pipe的命名管道文件。
3.2 使用C語(yǔ)言創(chuàng)建命名管道
在C語(yǔ)言中,可以使用mkfifo函數(shù)來(lái)創(chuàng)建命名管道:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
const char *fifo_path = "/tmp/my_fifo";
// 創(chuàng)建命名管道
if (mkfifo(fifo_path, 0666) == -1) {
perror("mkfifo");
exit(EXIT_FAILURE);
}
printf("Named pipe created: %s\n", fifo_path);
return 0;
}
4. 實(shí)現(xiàn)無(wú)血緣關(guān)系進(jìn)程間通信
4.1 寫(xiě)進(jìn)程示例
下面是一個(gè)寫(xiě)進(jìn)程的示例代碼,它向命名管道寫(xiě)入數(shù)據(jù):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main() {
const char *fifo_path = "/tmp/my_fifo";
const char *message = "Hello from writer process!";
// 以只寫(xiě)方式打開(kāi)命名管道
int fd = open(fifo_path, O_WRONLY);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
// 向命名管道寫(xiě)入數(shù)據(jù)
write(fd, message, strlen(message));
printf("Message sent: %s\n", message);
// 關(guān)閉命名管道
close(fd);
return 0;
}
4.2 讀進(jìn)程示例
下面是一個(gè)讀進(jìn)程的示例代碼,它從命名管道讀取數(shù)據(jù):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#define BUFFER_SIZE 256
int main() {
const char *fifo_path = "/tmp/my_fifo";
char buffer[BUFFER_SIZE];
// 以只讀方式打開(kāi)命名管道
int fd = open(fifo_path, O_RDONLY);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
// 從命名管道讀取數(shù)據(jù)
int bytes_read = read(fd, buffer, BUFFER_SIZE - 1);
if (bytes_read == -1) {
perror("read");
exit(EXIT_FAILURE);
}
buffer[bytes_read] = '\0'; // 確保字符串以null結(jié)尾
printf("Message received: %s\n", buffer);
// 關(guān)閉命名管道
close(fd);
return 0;
}
4.3 運(yùn)行示例
要運(yùn)行這個(gè)示例,首先需要?jiǎng)?chuàng)建命名管道,然后分別編譯和運(yùn)行寫(xiě)進(jìn)程和讀進(jìn)程。需要注意的是,讀進(jìn)程應(yīng)該先于寫(xiě)進(jìn)程啟動(dòng),因?yàn)樽x進(jìn)程在打開(kāi)命名管道時(shí)會(huì)阻塞,直到有另一個(gè)進(jìn)程以寫(xiě)方式打開(kāi)同一個(gè)命名管道。
# 創(chuàng)建命名管道 mkfifo /tmp/my_fifo # 編寫(xiě)進(jìn)程 gcc writer.c -o writer ./writer & # 讀進(jìn)程 gcc reader.c -o reader ./reader
5. 命名管道的高級(jí)特性
5.1 非阻塞打開(kāi)命名管道
默認(rèn)情況下,以只讀或只寫(xiě)方式打開(kāi)命名管道會(huì)導(dǎo)致進(jìn)程阻塞,直到有另一個(gè)進(jìn)程以相反的方式打開(kāi)同一個(gè)命名管道。為了避免阻塞,可以在打開(kāi)命名管道時(shí)指定O_NONBLOCK標(biāo)志:
// 非阻塞方式打開(kāi)命名管道 int fd = open(fifo_path, O_RDONLY | O_NONBLOCK);
5.2 使用select或poll監(jiān)控命名管道
可以使用select或poll函數(shù)來(lái)監(jiān)控命名管道的可讀性或可寫(xiě)性,從而避免阻塞:
#include <sys/select.h>
#include <poll.h>
// 使用select監(jiān)控命名管道
fd_set read_fds;
struct timeval timeout;
FD_ZERO(&read_fds);
FD_SET(fd, &read_fds);
timeout.tv_sec = 5; // 5秒超時(shí)
timeout.tv_usec = 0;
int ret = select(fd + 1, &read_fds, NULL, NULL, &timeout);
if (ret > 0) {
if (FD_ISSET(fd, &read_fds)) {
// 命名管道可讀
// 執(zhí)行讀取操作
}
}
// 使用poll監(jiān)控命名管道
struct pollfd fds;
fds.fd = fd;
fds.events = POLLIN; // 監(jiān)控可讀事件
int ret = poll(&fds, 1, 5000); // 5秒超時(shí)
if (ret > 0) {
if (fds.revents & POLLIN) {
// 命名管道可讀
// 執(zhí)行讀取操作
}
}
6. 命名管道的注意事項(xiàng)
- 單向通信:命名管道是單向的,如果需要雙向通信,需要?jiǎng)?chuàng)建兩個(gè)命名管道。
- 阻塞行為:默認(rèn)情況下,打開(kāi)命名管道會(huì)導(dǎo)致進(jìn)程阻塞,直到有另一個(gè)進(jìn)程以相反的方式打開(kāi)同一個(gè)命名管道。
- 數(shù)據(jù)完整性:寫(xiě)入命名管道的數(shù)據(jù)可能會(huì)被截?cái)?,特別是在寫(xiě)入大量數(shù)據(jù)時(shí)。因此,需要確保數(shù)據(jù)的完整性。
- 錯(cuò)誤處理:在使用命名管道時(shí),需要正確處理各種錯(cuò)誤情況,如管道不存在、權(quán)限不足等。
- 資源清理:使用完命名管道后,應(yīng)該關(guān)閉文件描述符,并在不需要時(shí)刪除命名管道文件。
7. 實(shí)際應(yīng)用場(chǎng)景
命名管道在實(shí)際開(kāi)發(fā)中有多種應(yīng)用場(chǎng)景,例如:
- 日志收集系統(tǒng):多個(gè)不同的應(yīng)用程序可以將日志寫(xiě)入同一個(gè)命名管道,而日志收集進(jìn)程則從該管道讀取日志。
- 服務(wù)間通信:在微服務(wù)架構(gòu)中,可以使用命名管道作為輕量級(jí)的進(jìn)程間通信機(jī)制。
- 命令行工具:命令行工具可以使用命名管道接收來(lái)自其他程序的輸入或發(fā)送輸出到其他程序。
- 測(cè)試框架:在測(cè)試過(guò)程中,可以使用命名管道模擬不同組件之間的交互。
8. 總結(jié)
本文介紹了Linux命名管道(FIFO)的基本概念、創(chuàng)建方法以及如何使用它來(lái)實(shí)現(xiàn)無(wú)血緣關(guān)系進(jìn)程間的通信。通過(guò)示例代碼,展示了如何創(chuàng)建命名管道、打開(kāi)和關(guān)閉命名管道,以及如何使用命名管道進(jìn)行進(jìn)程間通信。此外,還介紹了命名管道的高級(jí)特性和注意事項(xiàng)。
命名管道是一種簡(jiǎn)單而有效的進(jìn)程間通信機(jī)制,特別適用于不相關(guān)的進(jìn)程之間的通信。通過(guò)合理使用命名管道,可以實(shí)現(xiàn)進(jìn)程間的數(shù)據(jù)交換和同步,提高程序的靈活性和可擴(kuò)展性。
以上就是使用Linux命名管道(FIFO)實(shí)現(xiàn)無(wú)血緣關(guān)系進(jìn)程間的通信的詳細(xì)內(nèi)容,更多關(guān)于Linux命名管道無(wú)血緣關(guān)系通信的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Linux使用mutt命令行發(fā)送郵件的詳細(xì)流程
本文介紹了如何在 Linux 或類 Unix 系統(tǒng)中使用 mutt 命令行郵件客戶端進(jìn)行郵件發(fā)送,mutt 以其輕量、靈活的特點(diǎn),廣泛應(yīng)用于服務(wù)器自動(dòng)化通知、備份提醒和系統(tǒng)告警等場(chǎng)景,需要的朋友可以參考下2025-11-11
XShell免費(fèi)版的安裝配置教程及使用保姆級(jí)教程
XShell?是一種流行且簡(jiǎn)單的網(wǎng)絡(luò)程序,旨在模擬虛擬終端,這篇文章主要介紹了XShell免費(fèi)版的安裝配置教程以及使用教程,需要的朋友可以參考下2022-08-08
Linux虛擬主機(jī)面板 kloxo安裝及漢化教程分享
Kloxo的前身是lxadmin,是一款免費(fèi)的虛擬主機(jī)管理系統(tǒng),安裝簡(jiǎn)單,功能強(qiáng)大,可以快速地在red hat,centos系列l(wèi)inux系統(tǒng)的主機(jī)上搭建LAMP環(huán)境。新版以完全解除限制無(wú)限域名綁定2012-09-09
Centos服務(wù)器搭建簡(jiǎn)單的ftp服務(wù)實(shí)踐
文章介紹了在Centos服務(wù)器上搭建簡(jiǎn)單的FTP服務(wù),并在私網(wǎng)客戶端通過(guò)wget、curl和lftp三個(gè)工具下載FTP網(wǎng)頁(yè)內(nèi)容的過(guò)程2025-12-12
Linux集群/分布式環(huán)境下session處理的五種策略詳解
這篇文章主要給大家介紹了關(guān)于Linux集群/分布式環(huán)境下session處理的五種策略,文中通過(guò)示例代碼及圖片介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-09-09
在Linux系統(tǒng)中檢查CPU和內(nèi)存使用情況的常用方法
在 Linux 系統(tǒng)中,CPU 和內(nèi)存資源的高負(fù)載可能會(huì)導(dǎo)致系統(tǒng)性能下降,甚至使服務(wù)器無(wú)法正常響應(yīng)請(qǐng)求,因此本文將詳細(xì)介紹如何在 Linux 系統(tǒng)中檢查 CPU 和內(nèi)存的使用情況,并提供針對(duì)性解決方案,需要的朋友可以參考下2026-02-02

