• 首页
  • 关于我们
  • 产品中心
  • 新闻资讯
  • 在线招聘
  • 联系我们
  • 新闻资讯

    你的位置:开云(中国)Kaiyun·官方网站 > 新闻资讯 > 开云(中国)Kaiyun官方网站 OpenHarmony 源码认知之DFX子系统-Hiview(上)

    开云(中国)Kaiyun官方网站 OpenHarmony 源码认知之DFX子系统-Hiview(上)

    发布日期:2023-12-09 13:56    点击次数:171

    开云(中国)Kaiyun官方网站

    念念了解更多内容,请拜访:

    51CTO和华为官方调解共建的鸿蒙时候社区

    https://harmonyos.51cto.com

    1 简介

    DFX(Design for X)子系统是为了进步软件质地野心的用具集,现在包含的内容主要有:DFR(Design for Reliability,可靠性)和DFT(Design for Testability,可测试性)特质。

    已杀青以下功能:

    HiLog:活水日记。 HiSysEvent:系统事件纪录接口。 HiView:插件平台。 FaultLoggerd:诈欺故障订阅和集合。 HiAppEvent: js诈欺事件纪录接口。 1.1 OpenHarmony架构图 OpenHarmony 源码认知之DFX子系统-Hiview(上)-鸿蒙HarmonyOS时候社区 1.2 Hiview简介

    Hiview是一个跨平台的终局建立维测处事集。现在开源部分仅包含插件照应平台和系统事件源。

    Hiview架构图如下:

    OpenHarmony 源码认知之DFX子系统-Hiview(上)-鸿蒙HarmonyOS时候社区

    Hiview由框架和插件构成,分离为:

    操作系统适配层(adapter),对使用的系统处事的接口进行适配。 Hiview基础界说(hiview base),包括插件基类、管说念的界说,事件、事件部队界说以及一些用具类。 Hiview的中枢模块(hiview core),包括插件树立,插件照应以及事件源。 Hiview处事(hiview services),现在仅包括hiview运行信息dump功能。 Hiview插件(plugins),为独建功能的业务模块。 Hiview维测处事是由事件驱动的,其中枢为散播在系统各处的HiSysEvent桩点。

    形态化的事件通过HiSysEvent API上报至hiview进行处理,如下图:

    OpenHarmony 源码认知之DFX子系统-Hiview(上)-鸿蒙HarmonyOS时候社区 诈欺框架、系统处事使用HiSysEvent组件上报系统事件。 Hiview中SysEventSource得到音信,认知并拼装成管说念事件分发给插件处理。 1.3 Hiview代码目次
    /base/hiviewdfx/hiview. 开云(中国)Kaiyun官方网站├── adapter             #平台适配 │   ├── service        #处事适配 │   └── system_service #系统接口适配 ├── base                #模块界说,用具类 │   └── utility ├── build               #编译剧本 ├── core                #插件照应中枢代码 ├── include             #人人界说 ├── plugins             #插件 ├── service             #HiviewService处事 └── utility             #用具类 
    2 源码分析

    本文主要分析hiview插件照应平台的开动化,和事件处理进程。

    hiview是个常驻处事,在开机阶段启动。

    base/hiviewdfx/hiview/service/config/hiview.cfg界说如下

    {     "jobs" : [{             "name" : "post-fs-data",             "cmds" : [                 "mkdir /data/log/ 0770 system log",                 "mkdir /data/log/faultlog/ 0770 system system",                 "mkdir /data/log/faultlog/temp/ 0770 system system",                 "mkdir /data/log/faultlog/faultlogger/ 0770 system system",                 "start hiview"             ]         }     ],     "services" : [{             "name" : "hiview",             "path" : ["/system/bin/hiview"],             "uid" : "system",             "gid" : ["system", "log"],             "writepid" : [                 "/dev/cpuset/system-background/tasks"             ],             "socket" : [                 "hisysevent dgram 0666 root system passcred"             ]         }     ] } 
    2.1 开动化

    hiview的进口函数界说在base/hiviewdfx/hiview/main.cpp中

    int main(int argc __UNUSED, char* argv[] __UNUSED) {     auto& hiview = OHOS::HiviewDFX::HiviewPlatform::GetInstance();     // process cmdline     hiview.ProcessArgsRequest(argc, argv);      // 开动化环境,主要认知树立文献,加载插件     if (!hiview.InitEnvironment()) {         HIVIEW_LOGW("Fail to init plugin environment. exit");         return -1;     }      // 启动HiviewService处事,该处事提供了hiview运行信息dump功能     auto hiviewService = std::make_unique<OHOS::HiviewDFX::HiviewService>();     hiviewService->StartService();     return 0; } 

     HiviewPlatform::InitEnvironment()函数杀青如下:

    bool HiviewPlatform::InitEnvironment(const std::string& defaultDir, const std::string& cloudUpdateDir,                                      const std::string& workDir, const std::string& persistDir) {     // 创建使命目次,现在目次名使用了默许的空字符串,是以并未骨子创建使命目次     ValidateAndCreateDirectories(defaultDir, cloudUpdateDir, workDir, persistDir);      // update beta config     UpdateBetaConfigIfNeed();      // check whether hiview is already started     ExitHiviewIfNeed();      // 认知"/system/etc/hiview/plugin_config"插件树立文献     std::string cfgPath = GetPluginConfigPath();     PluginConfig config(cfgPath);     if (!config.StartParse()) { //...........注[1]         HIVIEW_LOGE("Fail to parse plugin config. exit!");         return false;     }     // 启动插件照应平台音信部队     StartPlatformDispatchQueue();      // init global context helper, remove in the future     HiviewGlobal::CreateInstance(static_cast<HiviewContext&>(*this));     //加载插件     LoadBusinessPlugin(config);      isReady_ = true;     NotifyPluginReady();     return true; } 

    注[1]处PluginConfig::StartParse()函数会按照特定例则去认知插件树立文献:

    if (field == "plugins") {        ParsePlugin(strTmp);    } else if (field == "pipelines") {        ParsePipeline(strTmp);    } else if (field == "pipelinegroups") {        ParsePipelineGroup(strTmp);    } 

     现在使用的插件树立文献/system/etc/hiview/plugin_config内容如下:

    plugins:3 SysEventSource[thread:sysevent_source]:0 static Faultlogger[]:0 static SysEventService[thread:sysevent_service]:0 static pipelines:1 SysEventPipeline:SysEventService Faultlogger pipelinegroups:1 SysEventSource:SysEventPipeline 

     注:base/hiviewdfx/hiview/plugins 下有eventlogger eventservice faultlogger freeze_detector hicollie_collector五个插件目次,而现在插件树立文献里骨子只用到了Faultlogger和SysEventService。

    PluginConfig::StartParse()认知完之后会把关系信息保存到列表中。类图如下:

    OpenHarmony 源码认知之DFX子系统-Hiview(上)-鸿蒙HarmonyOS时候社区

    PluginConfig::ParsePipelineGroup()代码如下

    void PluginConfig::ParsePipelineGroup(const std::string& pipelineGroup) {     std::smatch result;     // EventSourceExample:FromTwo2Three FromThree2Two     if (!regex_search(pipelineGroup, result, std::regex("(\\S+)\\s*:(.+)"))) {         HIVIEW_LOGW("Fail to match pipeline group expression.");         return;     }      const int pipelineGroupNameField = 1;     const int pipelineNameListField = 2;     std::string eventSourceName = StringUtil::TrimStr(result.str(pipelineGroupNameField));     auto ret = std::find_if(pluginInfoList_.begin(), pluginInfoList_.end(), [&](PluginInfo& info) {         if (info.name == eventSourceName) {             info.isEventSource = true;             info.pipelineNameList = StringUtil::SplitStr(result.str(pipelineNameListField));             return true;         }         return false;     });     if (ret != std::end(pluginInfoList_)) {         HIVIEW_LOGD("%s is an event source.", eventSourceName.c_str());     } } 

    阐扬:

    在认知pipelinegroups时,如若发现pipelineGroupName和pluginInfoList中某个插件的name一致,则把该插件PluginInfo.isEventSource置为true况兼把pipelineNameList赋值给PluginInfo.pipelineNameList。 集合/system/etc/hiview/plugin_config树立文献,不错看到SysEventSource插件是带管说念(SysEventPipeline)的,插件SysEventService和Faultlogger附庸于管说念SysEventPipeline,用于处理SysEventSource扔给管说念的事件。

    认知完插件树立信息之后会调用HiviewPlatform::LoadBusinessPlugin(const PluginConfig& config)去装载插件和管说念。

    代码如下

    void HiviewPlatform::LoadBusinessPlugin(const PluginConfig& config) {     // start to load plugin     // 1. 遍历pluginInfoList,字据插件名创建插件。因为现在树立的插件加载延时(loadDelay)为0,是以平直走[2],调用CreatePlugin()创建插件并添加到pluginMap_中。     auto const& pluginInfoList = config.GetPluginInfoList();     for (auto const& pluginInfo : pluginInfoList) {         HIVIEW_LOGI("Start to create plugin %{public}s delay:%{public}d", pluginInfo.name.c_str(),                     pluginInfo.loadDelay);         if (pluginInfo.loadDelay > 0) { //.............[1]             auto task = std::bind(&HiviewPlatform::ScheduleCreateAndInitPlugin, this, pluginInfo);             sharedWorkLoop_->AddTimerEvent(nullptr, nullptr, task, pluginInfo.loadDelay, false);         } else {       //...............[2]             CreatePlugin(pluginInfo);         }     }     // 2. 遍历pipelineInfoList,调用CreatePipeline()创建管说念并添加到pipelines_中。     auto const& pipelineInfoList = config.GetPipelineInfoList();     for (auto const& pipelineInfo : pipelineInfoList) {         HIVIEW_LOGI("Start to create pipeline %{public}s", pipelineInfo.name.c_str());         CreatePipeline(pipelineInfo);     }      // 3. 遍历pluginInfoList,调用InitPlugin()开动化插件     for (auto const& pluginInfo : pluginInfoList) {         HIVIEW_LOGI("Start to Load plugin %{public}s", pluginInfo.name.c_str());         InitPlugin(config, pluginInfo); //............注[1]     }      CleanupUnusedResources(); } 

    阐扬:

    注[1]InitPlugin()这一步中,如若插件的workHandlerType为thread,则绑定使命线程EventLoop。如若插件是EventSource类型,则绑定管说念Pipeline,况兼调用StartEventSource开启音信监听。代码如下:

    void HiviewPlatform::InitPlugin(const PluginConfig& config __UNUSED, const PluginConfig::PluginInfo& pluginInfo) {     auto& plugin = pluginMap_[pluginInfo.name];     if (plugin == nullptr) {         return;     }     // 如若插件的workHandlerType为thread,则绑定使命线程EventLoop。     if (pluginInfo.workHandlerType == "thread") {         auto workLoop = GetAvaliableWorkLoop(pluginInfo.workHandlerName);         plugin->BindWorkLoop(workLoop);     }      auto begin = TimeUtil::GenerateTimestamp();     plugin->OnLoad();     // 如若插件是EventSource类型,则添加管说念Pipeline,况兼调用StartEventSource开启音信监听     if (pluginInfo.isEventSource) {         auto sharedSource = std::static_pointer_cast<EventSource>(plugin);         if (sharedSource == nullptr) {             HIVIEW_LOGE("Fail to cast plugin to event source!");             return;         }         for (auto& pipelineName : pluginInfo.pipelineNameList) {             sharedSource->AddPipeline(pipelines_[pipelineName]);         }         StartEventSource(sharedSource);     }     auto end = TimeUtil::GenerateTimestamp();     HIVIEW_LOGI("Plugin %{public}s loadtime:%{public}" PRIu64 ".", pluginInfo.name.c_str(), end - begin); } 

    至此,插件照应平台开动化使命已完成。

    2.2 事件处理进程

    集合插件树立文献,现在骨子使用的插件类图如下:

    OpenHarmony 源码认知之DFX子系统-Hiview(上)-鸿蒙HarmonyOS时候社区

    阐扬:

    前文终末的代码段提到,如若插件是EventSource类型,则绑定管说念,况兼调用StartEventSource开启音信监听。集合类图,只好SysEventSource是EventSource类型的插件,是以只好SysEventSource捏有管说念。 EventSource类型的插件会监听HiSysEvent接口发来的音信,认知并拼装成管说念事件,分发给管说念中的插件处理。

    SysEventSource::StartEventSource()函数杀青如下。

    void SysEventSource::StartEventSource() {     HIVIEW_LOGI("SysEventSource start");     std::shared_ptr<EventReceiver> sysEventReceiver = std::make_shared<SysEventReceiver>(*this);     eventServer.AddReceiver(sysEventReceiver);      eventServer.Start(); } 

    SysEventSource有个成员变量eventServer,EventServer会开启socketserver端用于接受HiSysEvent接口发来的socket音信。

    类图如下:

    OpenHarmony 源码认知之DFX子系统-Hiview(上)-鸿蒙HarmonyOS时候社区 OpenHarmony 源码认知之DFX子系统-Hiview(上)-鸿蒙HarmonyOS时候社区

    阐扬:

    1.SysEventSource::StartEventSource()中把SysEventReceiver对象加入到EventServer的receivers_容器中。

    2.EventServer收到socket音信之后,调用SysEventReceiver::HandlerEvent(const std::string& rawMsg)形态处理接受到的音信。

    3.SysEventReceiver::HandlerEvent()形态中会调用SysEventParser::Parser(const std::string& rawMsg)形态认知己信并拼装成SysEvent对象,然后调用EventSource::PublishPipelineEvent(std::shared_ptr event)形态把管说念事件发布出去。

    EventSource::PublishPipelineEvent()代码如下:

    bool EventSource::PublishPipelineEvent(std::shared_ptr<PipelineEvent> event) {     HIVIEW_LOGD("EventSource PublishPipelineEvent");     if (event == nullptr) {         return false;     }      if (Audit::IsEnabled()) {         auto digest = GetPluginInfo() + Audit::DOMAIN_DELIMITER + event->GetEventInfo();         Audit::WriteAuditEvent(Audit::StatsEvent::PIPELINE_EVENT_CREATE, event->createTime_, digest);     }      for (auto& pipeline : listeners_) {         if ((pipeline != nullptr) && (pipeline->CanProcessEvent(event))) {             // one event can only be processed by one pipeline             pipeline->ProcessEvent(event);             return true;         }     }     return false; } 

    集合上头的类图,EventSource捏有管说念列表对象listeners_,EventSource::PublishPipelineEvent()函数中会遍历该列表,调用Pipeline::ProcessEvent(std::shared_ptr event)函数行止理管说念事件。(Pipeline对象是在HiviewPlatform::InitPlugin()函数中被加入到EventSource.listeners_中的。)

    Pipeline类型有个成员变量std::list

    在插件平台开动化的时辰,HiviewPlatform::CreatePipeline()函数中也曾把Plugin插件对象加入到了processors_列表中。

    接下来分析Pipeline::ProcessEvent()函数作念了什么。

    void Pipeline::ProcessEvent(std::shared_ptr<PipelineEvent> event) {     event->SetPipelineInfo(name_, processors_);     event->OnContinue(); } 

     把Pipeline的processors_对象赋给了PipelineEvent的processors_对象,然后调用

    PipelineEvent::OnContinue()函数。

    接下来分析PipelineEvent::OnContinue()函数:

    bool PipelineEvent::OnContinue() {     // 判断hasFinish_符号位和processors_列表是否也曾为空,如已为空,截至本次事件传递     if ((!hasFinish_) && processors_.empty()) {         return OnFinish();     }      // once the event start delivering     // the call OnContinue means one has done the processing of the event     // this may be called by upstream event processor or the framework     if (Audit::IsEnabled() && startDeliver_) {         Audit::WriteAuditEvent(Audit::StatsEvent::PIPELINE_EVENT_HANDLE_OUT,             createTime_, std::to_string(Thread::GetTid()));     }      // the framework will call OnContinue when the event is assigned to a pipeline     if (!startDeliver_) {         startDeliver_ = true;     }      // 取出processors_列表中第一个Plugin元素,并从列表弹出     std::weak_ptr<Plugin> plugin = processors_.front();     processors_.pop_front();     if (auto pluginPtr = plugin.lock()) {         if (!pluginPtr->CanProcessMoreEvents()) {             handler_->PauseDispatch(plugin);         }          if (Audit::IsEnabled()) {             Audit::WriteAuditEvent(Audit::StatsEvent::PIPELINE_EVENT_HANDLE_IN, createTime_,                                    pluginPtr->GetHandlerInfo());         }         // 判断刻下Plugin是否开启了事件使命部队,如有则加入事件部队处理,如莫得平直调用OnEventProxy         if (auto workLoop = pluginPtr->GetWorkLoop()) {             workLoop->AddEvent(pluginPtr, shared_from_this()); //............[1]         } else {             pluginPtr->OnEventProxy(shared_from_this()); //..........[2]         }     } else {         return OnContinue();     }     return true; } 

    不论插件是否使用了事件部队,最终皆会调用到Plugin::OnEventProxy()函数来处理管说念事件。

    Plugin::OnEventProxy()函数杀青如下:

    bool Plugin::OnEventProxy(std::shared_ptr<Event> event) {     if (event == nullptr) {          return false;     }      std::shared_ptr<Event> dupEvent = event;     auto processorSize = dupEvent->GetPendingProcessorSize();     dupEvent->ResetPendingStatus();     bool ret = OnEvent(dupEvent); //..............注[1]      if (!dupEvent->IsPipelineEvent()) {         if (Audit::IsEnabled()) {             Audit::WriteAuditEvent(Audit::StatsEvent::QUEUE_EVENT_OUT, dupEvent->createTime_,                 std::to_string(Thread::GetTid()));         }     } else {         if ((!dupEvent->HasFinish() && !dupEvent->HasPending()) &&             (processorSize == dupEvent->GetPendingProcessorSize())) {             dupEvent->OnContinue();//.............注[2]         }     }     return ret; } 

    先调用注[1]OnEvent()函数处理事件,再判断管说念事件传递是否已截至,如未截至则调用注[2]PipelineEvent::OnContinue()函数陆续把管说念事件传递给背面的

    插件处理。

    集合现在的插件树立文献,所有这个词这个词插件照应平台的音信处理进程约莫如下:

    EventServer接受到HiSysEvent组件接口发来的音信 --> SysEventReceiver::HandlerEvent() --> SysEventParser::Parser() --> EventSource::PublishPipelineEvent() --> Pipeline::ProcessEvent() --> PipelineEvent::OnContinue() --> SysEventService::OnEventProxy --> SysEventService::OnEvent --> PipelineEvent::OnContinue() --> Faultlogger::OnEventProxy --> Faultlogger::OnEvent --> 截至

    至此,事件处理进程已分析完。

    3 记忆

    以上内容领先分析了hiview插件照应平台的开动化,然后对事件的处理进程作念了分析。后续会详备栽种base/hiviewdfx/hiview/plugins目次下每个插件的源码。

    念念了解更多内容,请拜访:

    51CTO和华为官方调解共建的鸿蒙时候社区

    https://harmonyos.51cto.com