最近笔者在开发一个基于wpa_supplicant库和QT的WIFI连接界面,就像现在智能手机中wifi的连接界面。到现在基本上算是开发完成了,遇到不少问题,发现网上关于wpa_supplicant命令的介绍不少,但是关于怎么应用它做出一个完整的程序的文章却不多。所以笔者决定把这段时间开发的思路包括遇到各种问题拿出来分享。
首先本文介绍的算法是笔者在做扫描功能时候优化想出的小算法,因为它具有通用性,所以就把它单出来。笔者在实现wifi扫描时候,因为每次扫描的结果都不一样,而每个AP都是一个对象,笔者本来想把每次扫描到的AP对象放到list链表中,然后统一显示出来。但是这样带来一个问题,就是每个AP都要申请一个对象,然后链入链表,等到下次扫描时候,上次的AP对象又没用了,需要释放这部分内存重新申请新的对象。也就说需要不断地对同一种类进行申请内存和释放内存。笔者不清楚C++或者C编译器对new和delete这种操作优化到什么程度,但是如果想要提高性能,就必须想点办法了。
笔者想起去年分析的linux内存管理的slab算法,多么相似的应用场景。不过这里实现比起内核来简单多了。
算法思想:一次性申请多个对象,然后以栈或者队列来进行维护(笔者使用栈),需要使用对象时候从栈中取出对象,使用完毕后不进行delete释放内存,而是把对象重新放回到栈中。如果栈中对象使用完了那么就重新申请新的对象放到栈中,这样就实现了一种动态对象内存管理。
笔者在开始实现时候只是针对所用到的AP对象实现了算法,即实现的类只能管理固定对象的内存。后来笔者想怎么能做到像内核那样“通吃”呢。由于内核是C实现的,实现函数传入的是对象所占内存大小,然后需要对象时候再进行强强制类型转换。C++当然也可以做到,但是在C++中再去用内核的办法似乎有点大材小用,而C++为我们这种需求提供了更优雅的实现方式–模板。
下面笔者就把代码贴出来,算法已经说得比较清楚了,唯一一点如果读者对C++模板运用不是很熟,需要再去看下模板的用法。
/** ** @file: rampoll.h ** @date: 2016.3.3 */
#ifndef RAMPOLL_H
#define RAMPOLL_H
#include <QList>
template<typename ObjType>
class RamPoll : public QObject
{
public:
RamPoll(int initNum = 10);
ObjType *getObj();
void putObj(ObjType *obj);
signals:
public slots:
private:
QList<ObjType *> listPoll; //相当于内存池
int freeNum; //剩余空闲的对象数量
};
/** * @brief 初始化一定数量的对象 * @date: 2016.3.10 * @param initNum 初始化内存池中对象块数量 */
template<typename ObjType>
RamPoll<ObjType>::RamPoll(int initNum)
{
freeNum = initNum;
for(int i=0; i<initNum; i++){
ObjType *tmp = new ObjType;
listPoll.append(tmp);
}
}
/** * @brief 从缓存池中取一个对象的内存块 * @date: 2016.3.10 * @return APObj对象的内存块 */
template<typename ObjType>
ObjType *RamPoll<ObjType>::getObj()
{
ObjType *freeTmp;
//如果最后一个没被占用,那么返回它的对象引用并且出栈
if(!listPoll.empty()){
freeTmp = listPoll.last();
listPoll.pop_back();
freeNum--;
}else{ //如果都被占用了,直接再申请一个新的即可
freeTmp = new ObjType();
}
return freeTmp;
}
/** * @brief 回收内存块 * @date: 2016.3.10 * @return 废弃的APObj对象内存块 */
template<typename ObjType>
void RamPoll<ObjType>::putObj(ObjType *obj)
{
listPoll.push_back(obj); //入栈
freeNum++;
}
#endif // APRAMPOLL_H
很简单吧,几个函数就可以完成,这样RamPoll类就可以实现通用的碎片式对象管理。唯一一点是笔者借助了QT的QList类来实现算法中的栈功能,读者不同平台可以自己根据实际情况变化实现。