前言
已知条件:存在海量的车辆加速度和车辆定位信息,他们是单独存储成2种bin文件的形式,他们各自的bin文件存放的是不同时间段的数据项,现在需要将这些bin文件解析并且将同一时刻的数据做同步,即合成到一起显式出来。
PS:加速度和GPS的位置信息,每秒数据包的数量不一致,且相对于自身而言,每秒的数据包的数量也不一致。
环境
系统: Ubuntu 16.04
编译器: gcc version 5.4.0
思路
基于Linux 内核的list结构,创建一个链表用于存放数据包。
首先索引所有的bin文件,解析每一个bin文件,将bin文件中的数据包逐条解析出来,加入到链表中。
而后对链表的各个数据包按时间的顺序,从小到大进行排序。
最后,将取出时间相同的加速度和GPS的数据包将其组合到一起。比如,同一时刻,有5包加速度的数据,有7包GPS的数据,则只能同步成5包数据,多余的2包GPS数据丢弃。
Linux内核链表回顾
-
list_head
struct list_head { struct list_head *next, *prev; };
以上为内核链表的索引节点,对链表的增删改查都基于此节点。
-
创建头节点并初始化
#define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) static inline void INIT_LIST_HEAD(struct list_head *list){ list->next = list; list->prev = list; }
-
创建自定义的链表节点
struct list_node{ char *dataptr; struct list_head node; }
-
一些其余的宏
#define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type, member) );}) #define list_entry(ptr, type, member) \ container_of(ptr, type, member) #define list_for_each_entry_safe(pos, n, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member), \ n = list_entry(pos->member.next, typeof(*pos), member); \ &pos->member != (head); \ pos = n, n = list_entry(n->member.next, typeof(*n), member))
此处
list_for_each_entry_safe
的各个参数需要注意,pos
为指向链表的自定义结构体的游标指针;n
即也是一个指向链表自定义结构体的指针,他一只是指向pos
的下一个节点;head
是该链表的头节点;member
指的是链表自定义节点中的list_head
的变量名。
list_entry
一般用于通过head_list
的指针,得到指向他所在自定义节点的指针,所以ptr
是指向head_list
的指针,type
是自定义结构体的类型,member
指的是链表自定义节点中的list_head
的变量名。
排序
此次用到了选择排序,思想较为简单。
list_for_each_entry_safe(iptr, next, &datalisthead, node){
list_for_each_entry_safe(jptr, next, jhead, node){
if(iptr->tv_sec < jptr->tv_sec){
// swap list node value
}
}
jhead = jhead->next;
}
存储
即将链表中的节点遍历取出,将时间相同的元素存到一个数组中(数组元素的结构包含有时间,加速度和GPS数据),同时统计加速度和GPS各自的数量,当此时节点的时间和下一个节点的时间不一致时,则将数组的元素写入到文件中(按照加速度和GPS数量少的规则决定写入的数据的数量),而后清空该数组,直至所有的链表遍历完成,再销毁链表。