基于FIFO的c++多进程log封装
1 #ifndef PROCESS_LOG_H 2 #define PROCESS_LOG_H 3 4 #include <string> 5 #include <sstream> 6 #include <cstring> 7 8 #include <fcntl.h> 9 #include <sys/stat.h> 10 #include <sys/types.h> 11 #include<sys/time.h> 12 #include<unistd.h> 13 14 using std::string; 15 16 #define LOG_KIND_FILE_NAME 1 17 #define LOG_KIND_FIFO_NAME 2 18 19 #define LOG_ERROR_OPEN_FILE 1 20 #define LOG_ERROR_MKFIFO 2 21 #define LOG_ERROR_OPEN_FIFO 3 22 #define LOG_ERROR_FORK 4 23 #define LOG_ERROR_WRITE 5 24 25 class Log 26 { 27 private: 28 string _log_file_name; 29 string _log_fifo_name; 30 int _log_file_fd; 31 int _log_fifo_fd; 32 public: 33 Log(); 34 Log & bind(int kind, string s); 35 void start(); 36 void stop(); 37 void add(int pid, string s); 38 ~Log(); 39 }; 40 41 inline string getTime(void); 42 43 #endif
log.cpp:
1 #include "log.h" 2 3 //TODO Log构造函数 4 Log::Log(/* args */) : _log_fifo_name(""), 5 _log_file_fd(-1), 6 _log_file_name("") 7 { 8 } 9 10 //TODO Log析构函数 11 Log::~Log() 12 { 13 //释放文件 14 if(_log_file_fd>0){ 15 close(_log_file_fd); 16 } 17 if(_log_fifo_fd > 0){ 18 close(_log_fifo_fd); 19 } 20 } 21 22 //TODO 设置Log的属性(log文件名、FIFO文件名) 23 Log & Log::bind(int kind, string s) 24 { 25 switch (kind) 26 { 27 case LOG_KIND_FILE_NAME: 28 this->_log_file_name = s; 29 break; 30 case LOG_KIND_FIFO_NAME: 31 this->_log_fifo_name = s; 32 break; 33 default: 34 throw -1; 35 break; 36 } 37 return *this; 38 } 39 40 //TODO 添加日志 41 void Log::add(int pid, string s) 42 { 43 //构造日志格式[pid time] info 44 std::stringstream ss; 45 ss << "[" << pid << " " << getTime() << "]" << s; 46 s = ss.str(); 47 //写入fifo 48 write(this->_log_fifo_fd, s.c_str(), s.length()); 49 } 50 51 //TODO 停止Log 52 void Log::stop() 53 { 54 if(write(this->_log_fifo_fd, "STOP", 4) < 0){ 55 throw LOG_ERROR_WRITE; 56 } 57 } 58 59 //TODO 启动Log进程 60 void Log::start() 61 { 62 if(mkfifo(this->_log_fifo_name.c_str(), 0777) != 0){ 63 throw LOG_ERROR_MKFIFO; 64 } 65 66 //打开log文件 67 this->_log_file_fd = open(this->_log_file_name.c_str(), O_WRONLY); 68 if(_log_file_fd < 0){ 69 throw LOG_ERROR_OPEN_FILE; 70 } 71 72 //创建进程 73 int fid = fork(); 74 //原进程 75 if(fid > 0 ){ 76 //只写方式打开fifo 77 this->_log_fifo_fd = open(this->_log_fifo_name.c_str(), O_WRONLY); 78 if(this->_log_fifo_fd <= 0){ 79 throw LOG_ERROR_OPEN_FIFO; 80 } 81 return ; 82 } 83 //log进程 84 else if( fid == 0){ 85 //只读方式打开fifo 86 this->_log_fifo_fd = open(this->_log_fifo_name.c_str(), O_RDONLY); 87 if(this->_log_fifo_fd <= 0){ 88 throw LOG_ERROR_OPEN_FIFO; 89 } 90 91 //Loop 92 bool stop_flag = false; 93 while (!stop_flag) 94 { 95 //读取fifo 96 char buf[1024]; 97 int len = read(this->_log_fifo_fd, buf, 1023); 98 if(len <= 0){ 99 continue; 100 } 101 buf[len] = '\0'; 102 103 //停止 104 if(strcasecmp("STOP", buf) == 0){ 105 stop_flag = true; 106 } 107 //写入log 108 if(write(this->_log_file_fd, buf, len) < 0){ 109 throw LOG_ERROR_WRITE; 110 } 111 112 //刷新文件 113 sync(); 114 } 115 //退出进程 116 exit(0); 117 118 } else { 119 throw LOG_ERROR_FORK; 120 } 121 } 122 123 // TODO: 获取时间 124 inline string getTime(void) 125 { 126 timeval tv; 127 tm * time; 128 std::stringstream ss; 129 130 if(gettimeofday(&tv, nullptr) == -1){ 131 throw errno; 132 } 133 time = localtime(&(tv.tv_sec)); 134 char systime[40]; 135 strftime(systime, 40, "%Y-%m-%d %H:%M:%S.", time); 136 137 ss << systime << (int64_t)(tv.tv_usec / 1000); 138 139 return ss.str(); 140 }