zoukankan      html  css  js  c++  java
  • 基于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
    View Code

    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] = '';
    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 }
    View Code
  • 相关阅读:
    MF研究:TinyCLR运行时原理
    不到600美元,即可获取一套MF Porting kit 3.0
    SideShow Gadget开发[1]
    我眼中的WinHEC大会台前幕后
    Visual C++ 2008入门经典 第四章数组 字符串(二) 简单
    PHP的常用函数 简单
    Visual C++ 2008入门经典 第五章程序结构(二) 简单
    用PHP将Unicode 转化为UTF8 简单
    sql GROUP_CONCAT(... SEPARATOR) 简单
    Visual C++ 2008入门经典 第四章数组 字符串(练习题) 简单
  • 原文地址:https://www.cnblogs.com/HadesBlog/p/13173270.html
Copyright © 2011-2022 走看看