FreeNOS学习-lib-std-log学习

首先来说明一下FreeNOS的目录:

FreeNOS的一级目录如下

  • bin

bin目录下存放的是freenos各个服务的main.cpp

  • config

config顾名思义存放的就是freenos的配置文件了

  • kernel

kernel存放的是freenos的内核的源码

  • lib

lib下面存放的是freenos自己封装的一些基础类,对于C++初级的学者来说这块相对来说简单,而且能够学到的技巧也多,lib下面作者根据功能分类了很多个目录,在这里我就不一一列举了,

  • server

server存放的也是freenos的服务,至于和bin有什么区别,等待后面的学习更新

  • support

support存放的是文档和python脚本,至于这些脚本是用来干什么的目前还不清楚

  • test

test存放的是对freenos的测试的代码

下面我们步入正题,这次我们要学习的是freeNOS中的模块

下面是freeNOS中日志模块的头文件
/**
 * Logging utilities and definitions.
 *
 * @author Niek Linnenbank
 * @date 5 march 2015
 */

#ifndef _LOG_H
#define _LOG_H

#include "Singleton.h"
#include "Macros.h"
#include "String.h"

/**
 * Output a log line to the system log (syslog).
 *
 * @param type Log level
 * @param typestr Log level string
 * @param msg Message to output
 */
#define MAKE_LOG(type, typestr, msg) \
    {\
     if (Log::instance && type <= Log::instance->getMinimumLogLevel())  \
        (*Log::instance) << "[" typestr "] " << __FILE__ ":" <<  __LINE__ << " " << __FUNCTION__ << " -- " << msg << "\r\n"; \
    }

/**
 * Output a critical message and terminate program immediatly.
 * @param msg The critical message.
 */
#define FATAL(msg)   MAKE_LOG(Log::Emergency, "Emergency", msg)

/**
 * Output an error message.
 * @param msg The error message.
 */
#define ERROR(msg)   MAKE_LOG(Log::Error, "Error", msg)

/**
 * Output a warning message.
 * @param msg The warning message.
 */
#define WARNING(msg) MAKE_LOG(Log::Warning, "Warning", msg)

/**
 * Output a notice message.
 */
#define NOTICE(msg)  MAKE_LOG(Log::Notice, "Notice", msg)

/**
 * Output a regular message to standard output.
 */
#define INFO(msg)    MAKE_LOG(Log::Info, "Info", msg)

/**
 * Output a debug message to standard output.
 *
 * @param msg The message to output
 */
#define DEBUG(msg)   MAKE_LOG(Log::Debug, "Debug", msg)

/**
 * Logging class.
 *
 * @note This class is a singleton
 */
class Log : public Singleton<Log>
{
  public:

    /** Logging level values */
    enum Level
    {
        Emergency,
        Alert,
        Critical,
        Error,
        Warning,
        Notice,
        Info,
        Debug
    };

    /**
     * Constructor.
     */
    Log();

    /**
     * Destructor
     */
    virtual ~Log();

    /**
     * Get the minimum logging level.
     */
    Level getMinimumLogLevel();

    /**
     * Set the minimum logging level.
     */
    void setMinimumLogLevel(Level level);

    /**
     * Append to buffered output.
     */
    void append(const char *str);

    /**
     * Set log identity.
     */
    void setIdent(const char *ident);

    /**
     * Retrieve log identify.
     */
    const char * getIdent();

  protected:

    /**
     * Write to the actual output device.
     */
    virtual void write(const char *str) = 0;

  private:
    
    /** Minimum log level required to log. */
    Level m_minimumLogLevel;

    /** Identity */
    const char *m_ident;

    /** Buffered output */
    String m_outputBuffer;
};

/**
 * @name Operators to output various standard types to the log
 * @{
 */

// TODO: #warning move inside the Log class plz.

Log & operator << (Log &log, const char *str);

Log & operator << (Log &log, int number);

Log & operator << (Log &log, unsigned number);

Log & operator << (Log &log, unsigned long number);

Log & operator << (Log &log, void *ptr);    

/**
 * @}
 */

#endif /* _LOG_H */

通过头文件我们可以学习到的知识点:

1. 单例模式

一般在程序中日志模块都只初始化一次,在freenos中我们可以看到他的日志模块设计是继承自一个单例的模板类,这也是我们值得学习的地方,freenos的作者将单例模式进行抽象,定义为一个模板类,这样在整个工程中,只要需要单例模式的地方继承自这个单例的模板类就可以了,大大的减少了代码的重复性。

template <class T> class Singleton
{
  public:

    /**
     * Constructor
     * @param instance New instance of T.
     */
    Singleton<T>(T *obj)
    {
        instance = obj;
    }

    /** One and only instance. */
    static T *instance;
};

/* Initialize the static member obj. */
template <class T> T* Singleton<T>::instance = 0;
2. 宏函数的替换

一般在打印日志的时候都需要设置日志需要打印的级别,freenos的作者在这块巧妙的利用宏函数替换的策略,针对不同级别的日志对MAKE_LOG函数进行替换,把MAKE_LOG函数的前两个参数谢伟固定的,这样在使用日志的时候我们根据需要记录的日志级别选用对应级别的宏函数就可以,好处是只需要传一个参数,而且根据函数名就可以知道使用处日志的级别。

/**
 * Output an error message.
 * @param msg The error message.
 */
#define ERROR(msg)   MAKE_LOG(Log::Error, "Error", msg)
3.类的设计

在freenos中LOG类是所有日志类的基类,write函数是一个纯虚函数,LOG类的析构函数为虚析构函数,所有继承自LOG类的子类,只需要实线write函数即可

4.<<操作符的重载

在LOG类中,freenos通过重载<<操作符,实线了对不同数据类型的写入操作,在MAKE_LOG函数中就是通过调用重载的这一系列重载<<操作符函数来实现了对日志的写入,虽然最终都是将非String类型的数据调用append函数转换为String,并实现写入

Log & operator << (Log &log, const char *str);

Log & operator << (Log &log, int number);

Log & operator << (Log &log, unsigned number);

Log & operator << (Log &log, unsigned long number);

Log & operator << (Log &log, void *ptr); 

猜你喜欢

转载自blog.csdn.net/len_yue_mo_fu/article/details/82781766