首页 > 编程语言 >OpenHarmony 资源调度之智能感知调度源码分析

OpenHarmony 资源调度之智能感知调度源码分析

时间:2023-05-05 10:32:37浏览次数:48  
标签:OpenHarmony socket AF supplicant 调度 WPA 源码 libwpa wpa

作者:张守忠

1 WPA_supplicant简介

WPA是WiFi Protected Access的缩写,中文含义为“WiFi网络安全存取”。WPA是一种基于标准的可互操作的WLAN安全性增强解决方案,可大大增强现有以及未来无线局域网络的数据保护和访问控制水平。 wpa_supplicant是开源项目源码,支持Linux,Windows以及很多嵌入式系统。它是WPA的应用层认证客户端,负责完成认证相关的登录、加密等工作。wpa_supplicant是一个 独立运行的 守护进程,其核心是一个消息循环,在消息循环中处理WPA状态机、控制命令、驱动事件、配置信息等。 经过编译后 的 wpa_supplicant源程序可以看到两个主要的可执行工具:wpa_supplicant 和 wpa_cli。wpa_supplicant是核心程序,它和wpa_cli的关系就是服务和客户端的关系:后台运行wpa_supplicant,使用 wpa_cli来搜索、设置、和连接网络。wpa_supplicant与上层还是wpa_supplicant与驱动都采用socket通讯, 与驱动交互上报数据给用户,而用户可以通过socket发送命令给wpa_supplicant调动驱动来对WiFi芯片操作,如图1所示: 图 1 wpa_supplicant框架 wpa_supplicant_framework.png

2 AF_INET与AF_UNIX socket

Wpa_supplicant支持AF_INET和AF_UNIX socket两种通信方式:AF_INET socket、AF_UNIX socket。 AF_INET socket通信方式类似于网络socket通信,发送方、接收方依赖IP:Port来标识,即将本地的socket绑定到对应的IP端口上,发送数据时,指定对方的IP端口,经过Internet,可以根据此IP端口最终找到接收方;接收数据时,可以从数据包中获取到发送方的IP端口。发送方通过系统调用send()将原始数据发送到操作系统内核缓冲区中。内核缓冲区从上到下依次经过TCP层、IP层、链路层的编码,分别添加对应的头部信息,经过网卡将一个数据包发送到网络中。经过网络路由到接收方的网卡。网卡通过系统中断将数据包通知到接收方的操作系统,再沿着发送方编码的反方向进行解码,即依次经过链路层、IP层、TCP层去除头部、检查校验等,最终将原始数据上报到接收方进程,通信过程如下图所示: 图 2 AF_INET socket通信过程 AF_INET_communication.png AF_UNIX socket通信是典型的本地IPC,类似于管道,依赖路径名标识发送方和接收方。即发送数据时,指定接收方绑定的路径名,操作系统根据该路径名可以直接找到对应的接收方,并将原始数据直接拷贝到接收方的内核缓冲区中,并上报给接收方进程进行处理。同样的接收方可以从收到的数据包中获取到发送方的路径名,并通过此路径名向其发送数据。 图 3 AF_UNIX socket通信过程 AF_UNIX_socket_communication.png 他们的相同点:操作系统提供的接口socket(),bind(),connect(),accept(),send(),recv(),以及用来对其进行多路复用事件检测的select(),poll(),epoll()都是完全相同的。收发数据的过程中,上层应用感知不到底层的差别。 不同点:

  • 建立socket传递的地址域,及bind()的地址结构稍有区别:socket() 分别传递不同的域AF_INET和AF_UNIX bind()的地址结构分别为sockaddr_in(制定IP端口)和sockaddr_un(指定路径名)
  • AF_INET需经过多个协议层的编解码,消耗系统cpu,并且数据传输需要经过网卡,受到网卡带宽的限制。AF_UNIX数据到达内核缓冲区后,由内核根据指定路径名找到接收方socket对应的内核缓冲区,直接将数据拷贝过去,不经过协议层编解码,节省系统cpu,并且不经过网卡,因此不受网卡带宽的限制。
  • AF_UNIX的传输速率远远大于AF_INET
  • AF_INET不仅可以用作本机的跨进程通信,同样的可以用于不同机器之间的通信,其就是为了在不同机器之间进行网络互联传递数据而生。而AF_UNIX则只能用于本机内进程之间的通信。

3 WPA_supplicant在OpenHarmony中的应用

3.1 WPA_supplicant的位置

OpenHarmony的WIFI子系统使用WPA_supplicant实现调动驱动操作WIFI芯片,驱动数据上报给框架层的功能,WPA_supplicant在WIFI子系统的位置如下图的WIFI架构图所示: 图 4 WIFI子系统架构图 Wifi_framework.png WPA Supplicant包含libwpa、libwpa_client库和wpa_cli、wpa_supplicant、hostapd可执行程序。

  • libwpa是一个包含了wpa_suppliant和hostapd具体实现的库。
  • wpa_supplicant是wpa的认证客户端,负责完成认证相关的登录、加密等工作。
  • hostapd包含了IEEE802.11接入点管理、IEEE802.1X/WPA/WPA2认证、EAP服务器以及Radius鉴权服务器功能。
  • libwpa_client是一个给客户端连接和调用的库,提供创建与wpa_supplicant或hostapd通信控制接口的能力。
  • wpa_cli和wpa_supplicant是客户端和服务器的关系,通过wpa_cli可以向wpa_supplicant发送命令,进行扫描、连接等做操作,可用来进行Wifi功能的验证。

Wifi HAL层作为硬件适配层,承上启下,对上层框架屏蔽底层硬件差别,为上层提供一致的接口。对下则负责拉起WPAS,即fork进程wifi_hal_service的子进程,在子进程中加载libwpa库,执行wpa_supplicant或hostapd的入口函数, 作为unix socket通信的服务端. Wifi HAL的wifi_hal_service进程是unix socket通信的客户端,通过命令消息下发给wpa_supplicant或hostapd。

3.2 Wifi HAL与wpa_supplicant的unix socket机制

Wifi HAL拉起wpa_supplicant或hostapd并建立unix socket连接过程如下图所示 图 5 Wifi HAL与wpa_supplicant unix socket建立过程 hal_wpa_supplicant_unix_socket.png 其中HAL拉起wpas的主要实现函数为StartModuleInternal,代码主干如下

int StartModuleInternal(const char *moduleName, const char *startCmd, pid_t *pProcessId)
{
    ...
    pid_t pid = fork();  // fork子进程
    if (pid < 0) {
        LOGE("Create wpa process failed!");
        return HAL_FAILURE;
    }
    if (pid == 0) { /* sub process */
        prctl(PR_SET_PDEATHSIG, SIGKILL);
        pthread_t tid;
        int ret = pthread_create(&tid, NULL, WpaThreadMain, (void *)startCmd); // 子进程中创建主线程,线程入口函数WpaThreadMain 
        ...
    } else {
        ...
    }
    return HAL_SUCCESS;
}

子进程的主线程入口函数WpaThreadMain中,加载libwpa动态库,执行主函数wpa_main或ap_main,参数由创建线程时传入的startcmd解析而来。对于Sta和P2p业务,有两个参数分别是配置文件路径、全局控制路径;对于hostapd业务,传入一个参数,即hostapd配置文件路径。

static void *WpaThreadMain(void *p)
{
   ...
// 加载动态库libwpa
#ifdef OHOS_ARCH_LITE
    void *handleLibWpa = dlopen("libwpa.so", RTLD_NOW | RTLD_LOCAL);
#else
#ifdef __aarch64__
    void *handleLibWpa = dlopen("/system/lib64/libwpa.z.so", RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE);
#else
    void *handleLibWpa = dlopen("/system/lib/libwpa.z.so", RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE);
#endif
#endif
    ...
    if (strcmp(param.argv[0], "wpa_supplicant") == 0) {
        func = (int (*)(int, char **))dlsym(handleLibWpa, "wpa_main");
    } else {
        func = (int (*)(int, char **))dlsym(handleLibWpa, "ap_main");
    }
...
// 执行主函数
    int ret = func(param.argc, tmpArgv);
    LOGD("run wpa_main ret:%{public}d.\n", ret);
    if (dlclose(handleLibWpa) != 0) {
        LOGE("dlclose libwpa failed.");
        return NULL;
    }
    return NULL;
}

Wifi HAL作为客户端建立unix socket连接的主要实现函数WpaCliConnect,通过调用wpa client的函数wpa_ctrl_open建立socket连接,其参数ifname为“/data/service/el1/public/wifi/sockets/wpa/wlan0”。

static int WpaCliConnect(WifiWpaInterface *p)
{
    ...
    int count = WPA_TRY_CONNECT_TIMES;
    while (count-- > 0) {
        int ret = InitWpaCtrl(&p->wpaCtrl, WPA_CTRL_OPEN_IFNAME);
        if (ret == 0) {
            LOGI("Global wpa interface connect successfully!");
            break;
        } else {
            LOGE("Init wpaCtrl failed: %{public}d", ret);
        }
        usleep(WPA_TRY_CONNECT_SLEEP_TIME);
    }
    if (count <= 0) {
        return -1;
    }
    p->threadRunFlag = 1;
    if (pthread_create(&p->tid, NULL, WpaReceiveCallback, p) != 0) {
        p->threadRunFlag = 0;
        ReleaseWpaCtrl(&p->wpaCtrl);
        LOGE("Create monitor thread failed!");
        return -1;
    }
    LOGI("Wpa connect finish.");
    return 0;
}

int InitWpaCtrl(WpaCtrl *pCtrl, const char *ifname)
{
    ...
    do {
#ifdef WPA_CTRL_IFACE_UNIX
        pCtrl->pRecv = wpa_ctrl_open(ifname);
#else
        pCtrl->pRecv = wpa_ctrl_open("global");
#endif
        if (pCtrl->pRecv == NULL) {
            LOGE("open wpa control recv interface failed!");
            break;
        }
        if (wpa_ctrl_attach(pCtrl->pRecv) != 0) {
            LOGE("attach monitor interface failed!");
            break;
        }
#ifdef WPA_CTRL_IFACE_UNIX
        pCtrl->pSend = wpa_ctrl_open(ifname);
#else
        pCtrl->pSend = wpa_ctrl_open("global");
#endif
        if (pCtrl->pSend == NULL) {
            LOGE("open wpa control send interface failed!");
            break;
        }
        flag += 1;
    } while (0);
    ...
    return 0;
}

总结

本文主要介绍了WPA_supplicant基础及其在分布式软总线子系统WIFI模块的应用 ,着重分析了HAL层与WPA_supplicant之间的unix socket通信机制并贴出主要入口代码,为开发人员维护和扩展功能提供参考。

更多原创内容请关注:深开鸿技术团队

入门到精通、技巧到案例,系统化分享OpenHarmony开发技术,欢迎投稿和订阅,让我们一起携手前行共建生态。

想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com/#bkwz​

标签:OpenHarmony,socket,AF,supplicant,调度,WPA,源码,libwpa,wpa
From: https://blog.51cto.com/harmonyos/6244932

相关文章

  • Opal 教程之二 SipIM 例子源码分析
    在互联网上.极少有关于Opal的中文教程.因此敝人决定把学习Opal的过程记录下来勉励自己.抑或给后来者留下一些入门的资料.最近感觉学习Opal已经慢慢摸出了门道.前几个星期.摸索在VS2005编译Opal花了我好多天的时间.把我的耐心都磨得差不多快要放弃研究Opal.作为初学者.学习的难度......
  • java基于springboot+vue的宿舍管理系统、学生宿舍管理系统、高校宿舍管理系统,附源码+
    1、项目介绍java基于springboot+vue的宿舍管理系统、学生宿舍管理系统、高校宿舍管理系统,实现管理员:首页、个人中心、公告信息管理、院系管理、班级管理、学生管理、宿舍信息管理、宿舍安排管理、卫生检查管理、报修信息管理、报修处理管理、缴费信息管理,学生;首页、个人中心、公......
  • Spring源码:Bean生命周期(三)
    前言在之前的文章中,我们已经对bean的准备工作进行了讲解,包括bean定义和FactoryBean判断等。在这个基础上,我们可以更加深入地理解getBean方法的实现逻辑,并在后续的学习中更好地掌握createBean方法的实现细节。getBean用法讲解getBean方法之前,我们先来看看他有几种常见......
  • STL源码分析读书笔记
    主要是关于标准库容器的整理空间配置器主要看SGI的实现,有两个空间配置器_malloc_alloc_template<0>__default_alloc_template<...>用户可以选择单独使用第一个分配器,或者一起使用两个分配器。当用户选择使用两个分配器时,编译器会分别将上述两个分配器typedef成malloc_a......
  • springboot 分析源码欢迎页和图标-> thymeleaf模板引擎常用语法->扩展
    欢迎页: icon: 注意点: thymeleaf模板引擎1.使用thymeleaf模板引擎前要导入对应依赖包2.阅读源码:根据源码说明我们可以将html文件放置在templates目录下,然后通过controller进行跳转即可 controller类://在templates下的东西需要通过controller类来跳转,//需要导入......
  • 从案例中详解go-errgroup-源码
    一、背景某次会议上发表了errorgroup包,一个g失败,其他的g会同时失败的错误言论(看了一下源码中的一句话Thefirstcalltoreturnanon-nilerrorcancelsthegroup,没进一步看其他源码,片面理解了)。//Thefirstcalltoreturnanon-nilerrorcancelsthegroup'scontext......
  • JUC并发编程原理精讲(源码分析)
    1.JUC前言知识JUC即java.util.concurrent涉及三个包:java.util.concurrentjava.util.concurrent.atomicjava.util.concurrent.locks普通的线程代码:ThreadRunnable没有返回值、效率相比入Callable相对较低!Callable有返回值!【工作常用】1.1进程和线程进程:是......
  • 互联网医院系统源码:数据安全与隐私保护问题如何解决?
    当下,互联网医院系统源码已经走进了很多人的视野中,它的作用和好处小编就不用强调了,今天我们来聊另一个话题——隐私与数据安全。在智慧医疗行业,安全问题更是重中之重,这也自然而然成为了老生常谈的一个问题。本文小编将从互联网医院系统源码的数据安全与隐私保护的意义、当前面临的挑......
  • 分布式有状态服务的调度技术预研报告
    1.研究项目背景平台版本建设中,为了充分发挥视频分析引擎性能,需要针对业务特点,现有的分布式调用方式无法满足需求,需要研究分布式服务的有状态调用实现。2.技术现状分析2.1分布式有状态服务调度技术的发展历程固定分配最初的分布式有状态服务调度技术采用固定分配的方式,......
  • 在线直播系统源码,默认倒计时,自定义输入时间倒计时
    在线直播系统源码,默认倒计时,自定义输入时间倒计时html部分代码 <divid="app">  <inputtype="num"v-model="time">  <inputtype="button" @click="click_input(time)"value="点击">  <div>{{get_cod......