在嵌入式产品开发中,有时为了降低产品的硬件成本,会使用内存比较小的芯片。这会导致在设计程序时,需要考虑内存的消耗。在裸机的环境中,程序使用多少内存,基本上比较清楚。在嵌入式linux中,由于接口有多种,处理方式有多种,可能导致程序的内存开销会有不一样的效果。

        一、  选择合适的接口能大幅减小内存开销。实现WIFI连接管理,需要对设备的WIFI状态、网络状态进行一个获取。同时连接时,需要选择合适的接口来进行驱动加载、连接

    (一)程序编写中,获取WIFI状态的方式有好几种:

      1、通过调用system("wpa_cli -i wlan0 status"),这种方式能获取到很多状态,包括连接、断开、密码错误、扫描中。但是非常耗费内存,因为需要启动外部shell、fork开销很大、wpa_cli也得开一个线程

      2、可以通过popen()来获取,比system获取好一点,但还是需要消耗很多内存

      3、直接读取/sys/class/net/wlan0/operstate的值,但是状态比较单一,只有up、down。无法判断其他状态,不适合用来管理连接,适合读取网卡是否存在

      4、通过socket与wpa_supplicant通信。这种方式不需要 fork 任何进程,不需要启动 Shell,不需要启动wpa_cli。又能获取到WIFI连接、是否为假连接,这些已经满足WIFI连接管理的需求,关键省内存

    (二)、程序中获取NET状态的方式,也有几种方式:

      1、通过调用system("ping www.xxx.com"),这种如上所说,非常耗费内存

      2、通过获取TCP连接的方式,来查看是否与公网连接成功,比较省内存。但需要维护一个TCB,需要至少3次握手

      3、通过使用ICMP ping的方式。ICMP的方式,只需要把数据发出去,不需要维护连接状态。理论上比TCP连接更省内存、速度更快

    (三)、操作驱动加载、连接的方式:

      1、使用C语言库。优点就是灵活性高、集成度高。缺点就是上手没那么容易,需要对 Linux 网络子系统有较深的理解

      2、使用system来运行驱动加载和现有的网络管理工具。system已经分析过,是消耗比较大内存的

      3、使用fork+exec的方式来执行shell命令。比system省内存,但开销也很大

      4、使用vfork+exec的方式,或者使用posix_spawn来运行命令。

    这里选择了socket与wpa_supplicant通信来查看WIFI连接状态、直接读取/sys/class/net/wlan0/来判断网卡是否存在,通过ICMP ping的方式判断与网关和公网是否连接,操作命令使用的是vfork+exec的方式

  二、分层管理状态,避免系统峰值开销。

    在嵌入式设备,我们总希望系统开销越少越好,特别是在系统处理任务很繁重的时候,网络检测的步骤很多,同时检测,开销会更大,有风险导致系统被OOM杀掉进程。如何才能保证网络又能及时检测、系统开销又小。可以采用分层级管理的方法。在刚开始启动的时候,所有的检测步骤都得上,只要有一个步骤不通过,就表示不成功。等到网络已经连接成功后,这时,不需要同时检测WIFI是否连接、网络是否连通,可以每10秒检测WIFI连接、每60s检测NET连接。错开检测。同时避免在系统内存消耗峰值时来检测,需要判断空闲内存是否超过可检测阈值,没有超过则等下次检测时间到。具体的流程可见如下:   

image