基于wpa_supplicant库的WIFI连接功能实现--应用层碎片式对象内存管理算法

最近笔者在开发一个基于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类来实现算法中的栈功能,读者不同平台可以自己根据实际情况变化实现。

点赞