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

