柚子快報激活碼778899分享:c++ 命名管道Linux
柚子快報激活碼778899分享:c++ 命名管道Linux
?管道是
毫不相關的進程進程間通信::命名管道
管道
首先自己要用用戶層緩沖區(qū),還得把用戶層緩沖區(qū)拷貝到管道里,(從鍵盤里輸入數(shù)據(jù)到用戶層緩沖區(qū)里面),然后用戶層緩沖區(qū)通過系統(tǒng)調用(write)寫到管道里,然后再通過read系統(tǒng)調用,被對方(讀端)讀取,就要從管道拷貝到讀端,然后再顯示到顯示器上。
mkfifo命名管道
1號手冊是指令,。2號系統(tǒng)調用接口
創(chuàng)建一個管道,p開頭就是命名管道,并不會直接刷新到磁盤中,實際是個符號
這樣會阻塞
這樣會顯示出來(先輸入左邊的,再輸入右邊的就會顯示),左右兩邊是兩個進程
>>追加寫入的方式,但空間一直是0
所以這就是文件里大小一直是0的原因?????????
你怎么知道打開的是同一個文件
正好符合前提
所以要創(chuàng)建兩個可執(zhí)行程序,各自跑各自的,創(chuàng)建一個common是為了方便使用頭文件????????
client是客戶? ?server是服務者
makefile中一下運行兩個程序
mkfifo,用程序的方式創(chuàng)建管道,第一個參數(shù)是要創(chuàng)建的這個管道在那個路徑下叫什么名字,也就是要保持唯一性的那些點,第二個是創(chuàng)建一個管道
這里是3號手冊是函數(shù)。
返回 -1創(chuàng)建失敗?
創(chuàng)建一個共享文件
./myfifo
server.cc和client.cc想看到同一個文件,包含上頭文件就可以了
這里先用server控制管道文件
創(chuàng)建管道失敗了設置為1?,如果失敗了就exit(1)
誰控制的先運行運行誰就好了
make一下生成兩個可執(zhí)行程序,因為是server控制的,所以要先運行server
運行后就會多一個myfifo命名管道
命名管道的刪除
想刪除這個myfifo用unlink(成功返回0 ,失敗返回-1)?
命令行刪除
代碼也可以刪(成功返回0 ,失敗返回-1),頭文件是unistd.h
創(chuàng)建完文件,5秒后就刪除了
思路
用到了open
打開管道文件,第二個參數(shù)是只進行讀取
enum中
fd<0打開失敗了
服務端讀取數(shù)據(jù)
客戶端,只要用就行
?第二個參數(shù)就是打開文件為了寫入的
用戶輸入完成以后,就要發(fā)送輸入的消息到另一端
打開順序一定
然后打開的順序就一定了,先打開server,然后再打開另一個cc
先打開服務端,會阻塞在這里,然后再打開客戶端,進行輸入
右邊輸入啥,左邊就會有啥
無法輸入空格問題(getline)
但有一個問題就是cin沒法輸入空格,,要用到getline
會發(fā)現(xiàn)一個問題,客戶端退出了,服務端還沒退出
客戶端退出,會read到0,所以服務端(讀端)也要退出
?改正
sever端
等待寫入方式打開后,自己才會打開文件,向后執(zhí)行,open阻塞了!
優(yōu)化一下
寫成進程池的樣子
日志
創(chuàng)建一個新文件
用到了可變參數(shù)(形參實例化是從右到左)
可變參數(shù)必須右至少一個具體的參數(shù)
舉個例子:步驟:s指向可變部分
這里的sum第一個參數(shù)是幾個數(shù)求和的意思,傳不同的類型不可以的,因為上面va_arg里已經寫死了
開始寫日志,level日志等級
先定義時間,time,時間戳
ctime
頭文件
打印具體年月日?
年是從1900年開始的
?年月日時分秒
vsnprint
vsnprint,跟不帶v的區(qū)別就是,去除了...換成了可變參數(shù)部分
把日記等級轉換成字符串風格,所有有可能的地方都需要返回
改進
va_start(s,format),用format修飾s的指向,上面的sum是(s,n),類似
這里要用c_str,因為返回的是string
用完以后再用end
這里是往顯示器打印的,這里要*3,以為%s和%s中間有幾個空格,空間不夠
把這里修改一下,打開失敗的話
這樣就形成日志了
打印最后一行就是正常打開
這里也改一下
測試,先./server,然后會阻塞,然后./client,就會打印出,logmessage里的信息
為啥./client之前不打印
因為等待寫入方式打開后,自己才會打開文件,向后執(zhí)行,open阻塞了!
往文件里打?。ㄉ厦媸峭聊淮蛴。?/p>
先把這些內容全放在Log,日志類
分類
1:向屏幕打印
2:向一個文件打印
3:分類打印
打印格式printMethod
這里構造默認往屏幕去印
析構
打印方式也改一下
打印單個
以0666的權限打開這個文件
打印多個文件(添加一下level)
實現(xiàn)一下
優(yōu)化一下
以后再打印日志就不用這樣打了
這樣就可以了,要記住先創(chuàng)建一個Log對象
這樣以后就寫入一個文件了,寫入log.txt
這樣就把日志分類了
結果
但是日志文件這么多太混亂了
這樣操作后就統(tǒng)一進入一個文件了
makefile也修改一下,先把path定義的log目錄創(chuàng)建一下
日志放入一個文件測試結果:
日志分類測試結果:
log.hpp里頭文件
優(yōu)化一下調用
然后修改一下server.cc
?
client.cc
#include "common.hpp"
#include "log.hpp"
int main()
{
int fd = open(FIFO_FILE,O_WRONLY);
if(fd < 0)
{
perror("open");
exit(FIFO_OPEN_ERR);
}
string line;
while(true)
{
cout<< "Please Enter@ ";
// cin>> line;
getline(cin, line);
write(fd, line.c_str(),line.size());
}
close(fd);
return 0;
}
common.hpp
#pragma noce
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define FIFO_FILE "./myfifo"
#define MODE 0664 //用于設置文件的權限,0664代表著8進制寫法,4是其他用戶可讀不可寫
enum
{
FIFO_CREATE_ERR = 1,
FIFO_DELETE_ERR,
FIFO_OPEN_ERR
};
class Init
{
public:
Init()
{
//創(chuàng)建管道
int n = mkfifo(FIFO_FILE,MODE);
if(n == -1)
{
perror("mkfofi");
exit(FIFO_CREATE_ERR);
}
}
~Init()
{
//刪除命名管道
int m = unlink(FIFO_FILE);
if(m == -1)
{
perror("unlink");
exit(FIFO_DELETE_ERR);
}
}
};
log.hpp
#pragma noce
#include
// #include "common.hpp"
#include
#include
#include
#include
using namespace std;
#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4 // 致命的
//打印方式
#define Screen 1 //屏幕
#define Onefile 2 //一個文件
#define Classfile 3 //多個文件
#define LogFile "log.txt"
class Log
{
public:
Log()
{
printMehod = Screen;
path = "./log/";
}
void Enable(int method)
{
printMehod = method;
}
string levelToString(int level)
{
switch (level)
{
case Info:
return "Info";
case Debug:
return "Debug";
case Warning:
return "Warning";
case Error:
return "Error";
case Fatal:
return "Fatal";
default:
return "";
}
return "";
}
// void logmessage(int level, const char *format, ...)
// {
// time_t t = time(nullptr);
// struct tm *ctime = localtime(&t);
// char leftbuffer[1024];
// snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),
// ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday, ctime->tm_hour, ctime->tm_min, ctime->tm_sec);
// va_list s;
// va_start(s, format);
// char rightbuffer[1024];
// vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
// va_end(s);
// // 格式:默認部分+自定義部分
// char logtxt[1024 * 3];
// snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);
// //cout << logtxt << endl; // 暫時打印
// printLog(level, logtxt);
// }
void operator()(int level, const char* format, ...)
{
time_t t = time(nullptr);
struct tm *ctime = localtime(&t);
char leftbuffer[1024];
snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),
ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday, ctime->tm_hour, ctime->tm_min, ctime->tm_sec);
va_list s;
va_start(s, format);
char rightbuffer[1024];
vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
va_end(s);
// 格式:默認部分+自定義部分
char logtxt[1024 * 3];
snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);
//cout << logtxt << endl; // 暫時打印
printLog(level, logtxt);
}
void printLog(int level, const string &logtxt)
{
switch(printMehod)
{
case Screen:
cout<< logtxt < break; case Onefile: printOneFile(LogFile, logtxt);//"log.txt" break; case Classfile: printClassFile(level, logtxt); break; default: break; } } void printOneFile(const string &logname, const string &logtxt) { // "./log/" "log.txt" string _logname =path + logname; int fd = open(_logname.c_str(), O_WRONLY|O_CREAT|O_APPEND, 0666); if(fd < 0) return; write(fd, logtxt.c_str(), logtxt.size()); close(fd); } void printClassFile(int level, const string &logtxt) { string filename = LogFile;//"log.txt" filename += ".";//"log.txt." filename += levelToString(level); //log.txt.Debug/Waring/Fatal printOneFile(filename, logtxt); } ~Log() {} private: int printMehod; string path; }; makefile .PHONY:all all:client server server:server.cc g++ -o $@ $^ -g -std=c++11 mkdir log client:client.cc g++ -o $@ $^ -g -std=c++11 .PHONY:clean clean: rm -f server client server.cc #include "common.hpp" #include "log.hpp" int main() { //logmessage(Info, "hello"); //創(chuàng)建管道 Init init; Log log; //log.Enable(Onefile); log.Enable(Classfile); // //創(chuàng)建管道 // int n = mkfifo(FIFO_FILE,MODE); // if(n == -1) // { // perror("mkfofi"); // exit(FIFO_CREATE_ERR); // } // sleep(5); //打開管道 int fd = open(FIFO_FILE,O_RDONLY); if(fd < 0) { //log.logmessage(Fatal, "error string:%s,error code:%d",strerror(errno), errno); //優(yōu)化后 log(Fatal, "error string:%s,error code:%d",strerror(errno), errno); exit(FIFO_OPEN_ERR); } // log.logmessage(Info, "server open file done,error string:%s,error code:%d",strerror(errno), errno); // log.logmessage(Warning, "server open file done,error string:%s,error code:%d",strerror(errno), errno); //優(yōu)化后 log(Info, "server open file done,error string:%s,error code:%d",strerror(errno), errno); log(Warning, "server open file done,error string:%s,error code:%d",strerror(errno), errno); //...... //開始通信 while(true) { char buffer[1024] = {0}; int x = read(fd, buffer, sizeof(buffer)); if(x > 0) { buffer[x] = 0; cout<< "client say# " << buffer < } else if(x == 0) { //log.logmessage(Debug, "sclient quit too!,error string:%s,error code:%d",strerror(errno), errno); //優(yōu)化后 log(Debug, "sclient quit too!,error string:%s,error code:%d",strerror(errno), errno); //cout<< "client quit too!\n" < break; } else break; } close(fd); // //刪除命名管道 // int m = unlink(FIFO_FILE); // if(n == -1) // { // perror("unlink"); // exit(FIFO_DELETE_ERR); // } return 0; } 柚子快報激活碼778899分享:c++ 命名管道Linux 推薦文章
本文內容根據(jù)網(wǎng)絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉載請注明,如有侵權,聯(lián)系刪除。