一沙一世界 一树一菩提
分类: LINUX
2016-02-23 15:31:49
今天看看px4的log部分,log这部分其实是比较独立的模块,是可以拿出来使用在其它场合的。基本上也就是一般的记录日志的那一套形式。
不过也记录下来吧。这里没有粘贴代码,一行一行说明,但是下面的内容和代码是一一对应的。
首先根据rcS,它启动rc.logging,那咱们就看看这个脚本:
if [ -d /fs/microsd ]
then
if ver hwcmp PX4FMU_V1
then
if sdlog2 start -r 40 -a -b 3 -t
then
fi
else
if sdlog2 start -r 100 -a -b 12 -t
then
fi
fi
fi
可见,只是启动sdlog2这个命令。后面那一堆都是参数。接下来看代码了。
Src/modules/sdlog2/sdlog2.c,找到sdlog2_thread_main函数,这个是入口。前面一段是参数分析,稍微看下这段:
r参数写入日志频率,对于fmuv2来说,频率是100Hz,即每10ms执行一次。
b参数是log buffer大小,对于fmuv2来说,是12kB。
a参数表示当系统armed以后,开始记录日志。
t参数表示日志文件名字中含有时间戳信息。
然后下面初始化了日志模块接收信息的结构体或者联合体。注释里也说了主要是为了节省空间。
#pragam pack(push, 1)
.。。。。。。
#pragram pack(pop)
这个大家可以baidu下看看,其实也是为了节省空间,主要是对齐方面的设置。
然后初始化的了线程锁和线程条件变量。接下来呢,进入while循环。记录日志的周期在一进入循环就体现了:sleep,不用太过精确,日志记录这件事情啊,和其它的高精度定时相比较,时间多一点,少一点,不是很重要,睡一会醒来接着干活即可。
下面的循环的几个check和update,这几个主要是检测是否需要根据特定的系统要求启动日志写线程。并且只是写线程正常启动以后,才继续往下执行。
在往下继续写以前呢,说下记录日志这件事的软件结构。那就是一个循环缓存区+线程锁+条件变量。还得+两个指针:读指针和写指针。根据这几个组成部分大家也应该知道软件流程了。
一个线程向缓冲区写入日志信息,另外的一个线程从这个缓冲区读日志信息写到sd卡上。两个线程的互斥和同步通过线程锁和条件变量来实现。
写sd卡的是子线程是logwriter_thread,这个线程没有什么说的,就是获得线程锁,查看是否有数据可写到sd卡?没有活干就wait,在条件变量上等待有活干。如果有活干了,先释放线程锁,然后把日志信息写到sd卡,然后再次循环,在线程锁锁住前提下修改指针,继续检查是否有日志信息可以继续写到sd卡。好了,没有了,就这么多。这里需要注意下,循环缓冲区的使用。网上找到看看就可以,或者linux内核代码中好像是有个fifo.c的文件,实现原理一样。这是子线程干的活,再回头看看父线程干毛?其实不用看也知道,子线程有活干,其实是父线程提供的活,父线程的活就是向循环队列里写入日志内容。
大体结构如下:
While()
{
Sleep()
All kinds of check and update
log_msg.xxxx = yyyy;
…….
LOGBUFFER_WRITE_AND_COUNT
}
详细不说了,没有其它。