Skip to main content

 路由器设置 > 新闻资讯 >

关于日志类的总结

2014-05-04 22:58 浏览:

最近写过几个日志类,有一些体会,现在写下来作为笔记,留待以后完善。写一个日志类,目的就是方便将要打印出来的信息,安全的有序的写到指定文件。一般会默认将时间同时写下来,这是在日志写里面处理的。


一个简单地日志,一般一个应用程序只是对应一个log文件。这时出现共享问题,不同的地方使用同一个文件,使用同一个接口写。最开始,我将每一次的日志写都做一次文件的打开,写,关闭。当日志量少的时候,没有涉及到多线程时是可以工作的。但是,有时也会出现问题,毕竟文件是不能共享的,这时,我开始想办法。

1.为了日志的性能,文件的打开关闭只做一次,这是在日志类的构造函数和析构函数中处理。为了有序的写,必须处理同步。这里我想到两个办法,(针对windows环境)。一种是在类中添加静态临界区成员变量,由它来处理同步问题。当然文件句柄也是静态成员变量。这样就可以保证这两个资源在进程中是唯一的,且生命周期足够长。另一种方案是选用系统核心变量,比如事件,互斥体这些。最好是无名的。

 

当我完成上面这些时,在一个多线程环境下是可以很好的运行的。但是当我将这个类应用到一个多进程环境时,也就是说同一时间可能有多个进程在使用日志文件时,上面方法失败。

 

经过几天的学习和思考。想到了新的处理办法。就是把日志类的写交给一个守护进程。并且申请一段内存共享区,用来作为进程间的通信。这时遇到几个问题:

1.日志的写写到哪里?

2.写之间的同步?

3.如何保证写数据的不丢失?

4.资源如何合理分配和释放?

 

解决办法如下:

1.日志的写写到共享区特定区域,

2.同步使用无名事件

3.为了保证数据不丢失,使用写队列

4.资源的分配由日志类完成,释放由守护进程完成

 

接下来仍然有问题

写队列的设计,不能像普通队列一样随意new和delete,且不能使用指针。这是因为内存共享区映射在不同进程中的地址是不同的,由于是进程间的通信,堆是不能使用的。

 

解决办法如下,由于堆不能用,普通队列无法使用,标准队列需要重新改写容器接口,鉴于本队列相对简单,我选择自己完成队列,队列中的地址操作改为偏移量(用相对于首地址的偏移量作为地址)。由于内存的特殊,队列的设计是固定在内存区的固定位置,所有的操作免去了new和delete。数据区是否为脏的由自己定义特殊标记。

 

完成这些以后,将队列作为日志类的成员变量,并将日志类中的其它资源映射到共享类存中的固定位置。这时就完成了日志类在特定内存区的布局。所以日志类的创建需要用 placement new .值得注意的是,在mfc中这种使用new的方法被屏蔽了。解决办法是:屏蔽掉"#define new DEBUG_NEW".完成这些剩下的就很简单了。本文出自 “学习港湾” 博客