東莞做網(wǎng)站公司有哪些如何去推廣
目錄
1.原理
2.創(chuàng)建命名管道?
3.使用命名通道實現(xiàn)簡單的通信
4.使用創(chuàng)建的命名管道?
1.原理
????????匿名管道沒有名稱,它們是通過句柄在父進程和子進程之間傳遞的。這意味著匿名管道只能用于具有父子關(guān)系的進程之間。
? ? ? ? 但如果程序之間沒關(guān)系,那么這時候就要用到有名管道了,有名管道通過一個名稱(通常是一個文件系統(tǒng)中的路徑)來標識。這使得任何進程都可以通過該名稱來訪問管道,而不必是創(chuàng)建管道的進程的子進程。有名管道支持不同進程間的通信,甚至支持跨計算機(網(wǎng)絡(luò))的通信。有名管道的生命周期由創(chuàng)建它的進程控制,但即使創(chuàng)建它的進程終止,只要還有進程連接著管道,管道就會繼續(xù)存在。
????????命名管道在操作系統(tǒng)中表現(xiàn)為一種特殊類型的文件,它存在于系統(tǒng)的命名空間中,可以像打開文件那樣被打開和讀寫。一旦創(chuàng)建,命名管道就可以在不同的進程中被打開多次,允許單向或雙向的數(shù)據(jù)流傳輸。
2.創(chuàng)建命名管道?
創(chuàng)建命名管道,直接使用mkfifo命令就可以了
eg:
創(chuàng)建一個命名管道
????????一號機上的
while
循環(huán)持續(xù)地將字符串"hello boy"
寫入到命名管道myfifo
中,每次寫入后暫停一秒。二號機上的cat
命令則從myfifo
中讀取數(shù)據(jù),并將其輸出到標準輸出??匆豢葱Ч?#xff1a;我們發(fā)現(xiàn)在一號機寫到myfifo中的數(shù)據(jù)會被同步到二號機中的myfifo,
????????兩個不相關(guān)的進程(一號機和二號機上的進程)之間建立通信。這兩個進程不需要有任何父子關(guān)系或其他特殊關(guān)系,只需要知道命名管道的文件路徑即可。
? ? ? ? myfifo的文件大小始終都沒有變,因為并沒有被刷新到磁盤中。
3.使用命名通道實現(xiàn)簡單的通信
提供一個關(guān)閉命名管道的函數(shù):unlink
提供一個namepipe的類,它封裝了命名管道的創(chuàng)建、打開、讀寫和刪除的邏輯。以下是代碼(namedPipe.hpp):
#pragma once#include <iostream> #include <cstdio> #include <cerrno> #include <string> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>const std::string comm_path = "./myfifo"; #define DefaultFd -1 #define Creater 1 #define User 2 #define Read O_RDONLY #define Write O_WRONLY #define BaseSize 4096class NamePiped { private:bool OpenNamedPipe(int mode){_fd = open(_fifo_path.c_str(), mode);if (_fd < 0)return false;return true;}public:NamePiped(const std::string &path, int who): _fifo_path(path), _id(who), _fd(DefaultFd){if (_id == Creater){int res = mkfifo(_fifo_path.c_str(), 0666);if (res != 0){perror("mkfifo");}std::cout << "creater create named pipe" << std::endl;}}bool OpenForRead(){return OpenNamedPipe(Read);}bool OpenForWrite(){return OpenNamedPipe(Write);}int ReadNamedPipe(std::string *out){char buffer[BaseSize];int n = read(_fd, buffer, sizeof(buffer));if(n > 0){buffer[n] = 0;*out = buffer;}return n;}int WriteNamedPipe(const std::string &in){return write(_fd, in.c_str(), in.size());}~NamePiped(){if (_id == Creater){int res = unlink(_fifo_path.c_str());if (res != 0){perror("unlink");}std::cout << "creater free named pipe" << std::endl;}if(_fd != DefaultFd) close(_fd);}private:const std::string _fifo_path;int _id;int _fd; };
- 成員變量:
_fifo_path
:存儲命名管道的路徑。_id
:標識該對象是命名管道的創(chuàng)建者(Creater
)還是用戶(User
)。_fd
:文件描述符,用于與命名管道進行通信。初始化為DefaultFd
(定義為-1)。- 構(gòu)造函數(shù):
- 接收命名管道的路徑和創(chuàng)建者/用戶標識。
- 如果
_id
為Creater
,則調(diào)用mkfifo
函數(shù)在指定路徑下創(chuàng)建命名管道。如果創(chuàng)建失敗,會打印錯誤信息。- OpenForRead和OpenForWrite方法:
- 這兩個方法分別用于打開命名管道進行讀取和寫入操作。
- 內(nèi)部調(diào)用
OpenNamedPipe
方法,傳入相應(yīng)的讀取或?qū)懭肽J?#xff08;O_RDONLY
或O_WRONLY
)。OpenNamedPipe
方法使用open
系統(tǒng)調(diào)用來打開命名管道,并保存文件描述符到_fd
成員變量中。- ReadNamedPipe和WriteNamedPipe方法:
ReadNamedPipe
方法從命名管道中讀取數(shù)據(jù)到提供的字符串指針中。WriteNamedPipe
方法將提供的字符串寫入命名管道。- 這兩個方法都使用
read
和write
系統(tǒng)調(diào)用來執(zhí)行實際的讀寫操作。- 析構(gòu)函數(shù):
- 在對象銷毀時,析構(gòu)函數(shù)會被調(diào)用。
- 如果
_id
為Creater
,則調(diào)用unlink
函數(shù)來刪除命名管道。這確保了命名管道在不再需要時從文件系統(tǒng)中被移除。- 無論
_id
的值如何,都會檢查_fd
是否不是DefaultFd
(即文件描述符是否已打開),如果是,則調(diào)用close
函數(shù)來關(guān)閉文件描述符。
接下來創(chuàng)建一個客戶端向命名管道寫入(client.cc):
#include "namedPipe.hpp"// write int main() {NamePiped fifo(comm_path, User);if (fifo.OpenForWrite()){std::cout << "client open namd pipe done" << std::endl;while (true){std::cout << "Please Enter> ";std::string message;std::getline(std::cin, message);fifo.WriteNamedPipe(message);}}return 0; }
循環(huán)的寫入信息。
創(chuàng)建一個客戶端用來讀取命名管道的信息(server.cc):
#include "namedPipe.hpp"int main() {NamePiped fifo(comm_path, Creater);// 對于讀端而言,如果我們打開文件,但是寫還沒來,我會阻塞在open調(diào)用中,直到對方打開// 進程同步if (fifo.OpenForRead()){std::cout << "server open named pipe done" << std::endl;sleep(3);while (true){std::string message;int n = fifo.ReadNamedPipe(&message);if (n > 0){std::cout << "Client Say> " << message << std::endl;}else if(n == 0){std::cout << "Client quit, Server Too!" << std::endl;break;}else{std::cout << "fifo.ReadNamedPipe Error" << std::endl;break;}}}return 0; }
- 如果
ReadNamedPipe
返回的值n
大于0,表示成功讀取了n
個字符到message
中。
- 程序?qū)⑤敵?#34;Client Say> "和讀取到的消息內(nèi)容。
- 如果
n
等于0,通常表示客戶端已經(jīng)關(guān)閉了連接或者發(fā)送了一個EOF(文件結(jié)束符)。
- 程序?qū)⑤敵?#34;Client quit, Server Too!"并退出循環(huán),然后退出程序。
- 如果
n
小于0,表示讀取過程中發(fā)生了錯誤。
- 程序?qū)⑤敵?#34;fifo.ReadNamedPipe Error"并退出循環(huán),然后退出程序。
4.使用創(chuàng)建的命名管道?
?我們先運行了讀端程序,但是并沒有提示我們的讀端創(chuàng)建成功(對于讀端而言,如果我們打開文件,但是寫還沒來,我會阻塞在open調(diào)用中,直到對方打開)
打開寫端,讀端才成功打開。
這就實現(xiàn)進程間的通信了