什么是命名管道
命名管道(Named Pipe),也被稱為FIFO(First In, First Out),是一種在Unix和Unix-like操作系統(tǒng)中用于進(jìn)程間通信的特殊文件類型。它允許不相關(guān)的進(jìn)程通過文件系統(tǒng)中的路徑名進(jìn)行通信。
命名管道的作用有什么
命名管道(Named Pipe)是一種在Unix和Unix-like系統(tǒng)中用于進(jìn)程間通信的特殊文件類型。它的作用主要體現(xiàn)在以下幾個方面:
進(jìn)程間通信: 命名管道提供了一種進(jìn)程間通信的方式。不同的進(jìn)程可以通過共享同一個命名管道文件進(jìn)行通信,其中一個進(jìn)程將數(shù)據(jù)寫入管道,而另一個進(jìn)程從管道中讀取數(shù)據(jù)。這樣,進(jìn)程之間可以實現(xiàn)數(shù)據(jù)的交換和共享。
無關(guān)進(jìn)程通信: 與匿名管道不同,命名管道可以用于無關(guān)的進(jìn)程之間通信。因為命名管道在文件系統(tǒng)中有一個路徑名,進(jìn)程可以通過路徑名來打開和訪問它,而不需要共享相同的地址空間或具有親緣關(guān)系。
獨立于進(jìn)程生命周期: 命名管道是持久的,它存在于文件系統(tǒng)中,不受創(chuàng)建它的進(jìn)程的生命周期限制。這意味著即使創(chuàng)建命名管道的進(jìn)程結(jié)束,其他進(jìn)程仍然可以使用相同的管道進(jìn)行通信。
阻塞式通信: 命名管道是阻塞的,即寫入端會等待讀取端準(zhǔn)備好接收數(shù)據(jù),反之亦然。這樣可以協(xié)調(diào)進(jìn)程之間的通信,確保數(shù)據(jù)的正確傳輸。
常用于Shell編程: 在Shell編程中,命名管道常用于將一個命令的輸出傳遞給另一個命令,實現(xiàn)管道傳輸?shù)耐瑫r也可以用于進(jìn)程間通信。
總體而言,命名管道提供了一種方便、靈活且持久的進(jìn)程間通信機(jī)制,適用于各種需要數(shù)據(jù)交換的場景。
命名管道的特點和用法是什么
文件系統(tǒng)中的路徑名: 命名管道在文件系統(tǒng)中有一個路徑名,類似于普通文件。進(jìn)程可以通過打開這個路徑名的方式來訪問命名管道。
獨立的進(jìn)程通信: 不同進(jìn)程可以通過共享同一個命名管道文件來進(jìn)行通信。這使得命名管道成為不同進(jìn)程之間進(jìn)行進(jìn)程間通信的有效手段。
創(chuàng)建和刪除: 命名管道可以使用 mkfifo 函數(shù)來創(chuàng)建。創(chuàng)建后,它就成為文件系統(tǒng)中的一個特殊文件。當(dāng)通信結(jié)束時,可以使用 unlink 函數(shù)刪除命名管道。
讀寫操作: 進(jìn)程可以像普通文件一樣使用文件描述符對命名管道進(jìn)行讀取和寫入操作,實現(xiàn)進(jìn)程間的數(shù)據(jù)傳輸
命名管道與匿名管道有什么區(qū)別
命名管道(Named Pipe)和匿名管道(Anonymous Pipe)是兩種不同類型的管道,它們在創(chuàng)建、使用和生命周期等方面有一些關(guān)鍵區(qū)別。
命名管道:
創(chuàng)建: 命名管道在文件系統(tǒng)中有一個路徑名,可以通過 mkfifo 函數(shù)創(chuàng)建。它是一個具有持久性的文件,不依賴于創(chuàng)建它的進(jìn)程的生命周期。
路徑名: 命名管道有一個在文件系統(tǒng)中的路徑名,因此可以被不同的進(jìn)程通過路徑名來訪問。
無關(guān)進(jìn)程通信: 不相關(guān)的進(jìn)程可以通過共享同一個路徑名的命名管道進(jìn)行通信。
使用: 通過文件描述符進(jìn)行讀寫操作,可以使用標(biāo)準(zhǔn)的文件I/O函數(shù)。
生命周期: 命名管道存在于文件系統(tǒng)中,直到顯式刪除。
匿名管道:
創(chuàng)建: 匿名管道是由 pipe 系統(tǒng)調(diào)用創(chuàng)建的,沒有在文件系統(tǒng)中的路徑名。它是一種臨時的、僅存在于相關(guān)進(jìn)程之間的通信機(jī)制。
路徑名: 不存在路徑名,只能在創(chuàng)建它的進(jìn)程及其相關(guān)子進(jìn)程之間使用。
有關(guān)進(jìn)程通信: 主要用于有關(guān)系(親緣關(guān)系)的父子進(jìn)程之間通信。
使用: 通過文件描述符進(jìn)行讀寫操作,可以使用標(biāo)準(zhǔn)的文件I/O函數(shù)。
生命周期: 隨著創(chuàng)建它的進(jìn)程或相關(guān)子進(jìn)程的終止而結(jié)束。
綜上所述,主要區(qū)別在于命名管道是具有路徑名的、持久的文件,可以被不相關(guān)的進(jìn)程使用;而匿名管道是臨時的、只存在于相關(guān)進(jìn)程之間的通信機(jī)制,主要用于父子進(jìn)程之間通信。選擇使用哪種管道取決于具體的應(yīng)用場景和需求。
匿名管道相較于命名管道的局限性
首先我們可以先看一下匿名管道的代碼
#include <iostream>
#include <string>
#include <unistd.h>
#include <string.h>
#include <string>
#include <cstdio>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;
#define N 2
const int NUM = 1024;
void Write(int n)
{
string s = "hello,I am chile";
pid_t self = getpid();
char buffer[NUM]; // 緩沖區(qū)
int number = 0;
while (true)
{
buffer[0] = 0; // 字符串清空
snprintf(buffer, sizeof(buffer), "%s-%d-%d", s.c_str(), self, number++);
// cout << buffer << endl;
write(n, buffer, strlen(buffer));
sleep(1);
}
}
void Read(int rfd)
{
char buffer[NUM];
while (true)
{
buffer[0] = 0;
ssize_t n = read(rfd, buffer, sizeof(buffer));
if (n > 0)
{
buffer[n] = 0;
cout << "father get a message[" << getpid() << "]# " << buffer << endl;
}
}
}
int main()
{
int pipefd[N] = {0};
int n = pipe(pipefd);
if (n < 0)
return 1;
pid_t id = fork();
if (id < 0)
return 2;
if (id == 0)
{
close(pipefd[0]);
Write(pipefd[1]);
close(pipefd[1]);
exit(0);
}
close(pipefd[1]);
Read(pipefd[0]);
pid_t rid = waitpid(id, NULL, 0);
if (rid < 0)
{
return 3;
}
close(pipefd[0]);
return 0;
}
從上面代碼我們可以清晰的感知到匿名管道只適用與具有親緣關(guān)系的進(jìn)程之間的通信但是我們在實際開發(fā)環(huán)境中更多的進(jìn)程是不具備親緣關(guān)系的因此匿名管道就非常的局限了。我們看一下匿名管道的最終實現(xiàn)的效果圖
命名管道如何使用
我們來看一下命名管道的使用效果圖
在這張圖我們可以清楚的看到右邊輸入左邊輸出達(dá)到了我們想要的無親緣關(guān)系的進(jìn)程的通信文章來源:http://www.zghlxwxcb.cn/news/detail-805437.html
代碼
1.comm.hpp文件文章來源地址http://www.zghlxwxcb.cn/news/detail-805437.html
#pragma once
#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#define FIFO_FILE "./myfifo"
#define MODE 0664
enum
{
FIFO_CREATE_ERR = 1,
FIFO_DELETE_ERR,
FIFO_OPEN_ERR
};
class Init
{
public:
Init()
{
int n = mkfifo(FIFO_FILE, MODE);
if (n == -1)
{
perror("mkfifo");
exit(FIFO_CREATE_ERR);
}
}
~Init()
{
int m = unlink(FIFO_FILE);
if (m == -1)
{
perror("unlink");
exit(FIFO_DELETE_ERR);
}
}
};
- server.cpp文件代碼
#include "comm.hpp"
#include <iostream>
using namespace std;
int main()
{
Init init;
int fd = open(FIFO_FILE, O_RDONLY);
if (fd < 0)
{
exit(FIFO_OPEN_ERR);
}
while (true)
{
char buffer[1024];
int len = read(fd, buffer, sizeof(buffer));
if (len < 0)
{
break;
}
else if (len > 0)
{
buffer[len] = 0;
cout << "client say#" << buffer << endl;
}
else if (len == 0)
{
break;
}
}
close(fd);
return 0;
}
- client.cpp的代碼
#include "comm.hpp"
#include <iostream>
using namespace std;
int main()
{
int fd = open(FIFO_FILE, O_WRONLY);
if (fd == -1)
{
perror("open");
exit(FIFO_OPEN_ERR);
}
else
{
cout << "client open file done" << endl;
while (1)
{
cout << "Please Enter@ ";
string a;
getline(cin, a);
write(fd, a.c_str(), a.size());
}
}
close(fd);
return 0;
}
到了這里,關(guān)于進(jìn)程間通信之利用命名管道進(jìn)行通信的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!