当前位置: 首页 > news >正文

openharmony中HDF驱动框架源码梳理-驱动加载流程

要想大概了解一个公司,我们可能只需要知道它的运行逻辑即可,例如我们只需要知道它有财务有研发有运营等,财务报销、研发负责产品等即可,但是如果想深入具体的了解的话我们就要了解都有什么部门(对象)、各部门都包含哪些职责(对象方法)以及各部门都包含哪些关键人员(子对象)以及他们的职责(子对象方法),根据这个逻辑我大概整理了openharmony 5.0的HDF框架中包含的关键对象以及对应的方法,便于更深的理解HDF的实现。

一、源码目录

仓库路径仓库内容
drivers/hdf_core/frameworkHDF框架、平台驱动框架、驱动模型等平台无关化的公共框架。
- framework/core目录:驱动框架
  - 提供驱动框架能力,主要完成驱动加载和启动功能。
  - 通过对象管理器方式可实现驱动框架的弹性化部署和扩展。
- framework/model目录:驱动模型
  提供了模型化驱动能力,如网络设备模型。
- framework/ability目录:驱动能力库
  提供基础驱动能力模型,如IO通信能力模型。
- framework/tools目录:驱动工具
  提供HDI接口转换、驱动配置编译等工具。
- framework/support目录:Support
  提供规范化的平台驱动接口和系统接口抽象能力。
drivers/hdf_core/adapter包含所有LiteOS-M和LiteOS-A内核以及用户态接口库等相关适配代码以及编译脚本。
drivers/hdf_core/adapter/khdf/linux包含所有Linux内核相关适配代码以及编译脚本。
drivers/peripheralDisplay、Input、Sensor、WLAN、Audio、Camera等外设模块硬件抽象层。
drivers/interfaceDisplay、Input、Sensor、WLAN、Audio、Camera等外设模块HDI接口定义。

在这里插入图片描述

二、硬件驱动框架(HDF)

1. 驱动开发流程

驱动加载
驱动服务管理
驱动消息机制
配置管理
驱动模型
HDF驱动开发流程
按需加载,加载策略由配置文件中的preload字段来控制
preload为0:则系统启动过程中默认加载
preload为01:当系统支持快速启动的时候,则在系统完成之后再加载这一类驱动
preload为2:则系统启动过程中默认不加载,支持后续动态加载
按序加载(默认)
配置文件中的priority(整数0到200)是用来表示host(驱动容器)和驱动的优先级的
host和驱动都是priority值越小,加载优先级越高
驱动需要以接口的形式对外提供能力时使用
包含驱动服务的发布和获取
驱动对外发布服务的策略,由配置文件中的policy字段来控制
0:驱动不提供服务
1:驱动对内核态发布服务
2:驱动对内核态和用户态都发布服务
3:驱动服务不对外发布服务,但可以被订阅
4:驱动私有服务不对外发布服务,也不能被订阅
5:错误的服务策略
当用户态应用和内核态驱动需要交互时使用:
1.用户态应用发送消息到驱动
2.用户态应用接收驱动主动上报事件
HCS(HDF Configuration Source)是HDF驱动框架的配置描述源码。
它实现了配置代码与驱动代码解耦,便于开发者进行配置管理
HDF框架将一类设备驱动放在同一个Host(设备容器)里面,用于管理一组设备的启动加载等过程
划分Host时,驱动程序是部署在一个Host还是部署在不同的Host,主要考虑驱动程序之间是否存在耦合性

下面以驱动开发流程为主线,一步一步分析每个节点的代码实现,以求完全剖析实现逻辑。本篇为驱动加载流程的说明

2. 驱动加载

上图整理的驱动开发流程主要是从驱动应用的角度来绘制的,在聊驱动加载之前我们肯定要问谁来加载驱动呢?答案是驱动框架,所以这时就要先看下驱动框架的加载了。

驱动框架在不同的平台上(linux/liteos等)是不同的,在linux中是直接使用late_initcall内核的函数(hdf_core\adapter\khdf\linux\manager\src\devmgr_load.c)来进行实现的,对linux内核比较熟悉的码友应该比较清楚(不清楚的可以自行查阅,网络上内容应该比较多),不论什么平台大家最终的目的是调用函数DeviceManagerStart,下面就从此函数开始分析:

在这里插入图片描述

由于不同系统有不同的差异,所以码友们需要注意甄别了哈,我下面主要针对linux系统来进行说明的:

late_initcall(DeviceManagerInit);
|-> DeviceManagerInit()|-> DeviceManagerStart()| // (1)创建DevMgr单实例对象|-> instance = DevmgrServiceGetInstance();| // (2)发布DevMgr,"/dev/hdf/"+"dev_mgr"|-> ioService = HdfIoServicePublish(DEV_MGR_NODE, DEV_MGR_NODE_PERM);| // (3)启动DevMgr服务|-> instance->StartService(instance);| //(4) 电源管理的初始化|-> HdfPowerManagerInit()
2.1 创建DevMgr单实例对象

通过对代码的梳理可得代码流程如下图所示,由此可知此函数DevmgrServiceGetInstance的作用为创建DevMgr单实例对象,并为此对象设置好了具体的实现方法。

在这里插入图片描述

为了更好的分析DevMgr实例的具体方法我们可以参看IDevmgrService对象的类图,由图中标号①与标号②中我们可以发现实际创建的对象为单实例的DevmgrService类型,而接收的对象为IDevmgrService类型,由下面类图中的结构可知返回IDevmgrService类型相当于返回的单实例对象DevmgrService的super成员,可直接使用对应的接口函数。

在这里插入图片描述

在驱动框架需要使用DevmgrService提供对应的服务时,可通过设备服务管理客户端(DevmgrServiceClnt)的实例,该实例包含一个指向IDevmgrService对象的指针,通过该指针可以使用DevmgrService提供的服务,即设备管理接口。

2.2 发布用户态服务dev_mgr

在HdfIoServicePublish函数中直接调用的HdfIoServiceAdapterPublish()来发布用户态服务dev_mgr,具体的流程可参考下图:

在这里插入图片描述

其中涉及到了OSAL操作系统层,此层主要的功能是能够适配不同的操作系统(linux、liteos_a等),上图是使用linux操作系统举例的。

相关类图关系如下:

在这里插入图片描述

dev_mgr服务的使用

在用户态程序通过标准的文件操作接口open()打开/dev/hdf/dev_mgr设备节点时,会进入内核态驱动框架绑定的HdfVNodeAdapterOpen()中,然后会通过 struct HdfVNodeAdapter *adapter = (struct HdfVNodeAdapter *)OsalGetCdevPriv(cdev)这条语句将cdev中的priv字段强制类型转换,以转换为HdfVNodeAdapter 类型。

2.3 启动DevMgr服务

启动DevMgr服务(instance->StartService(instance))实际调用如下的设备管理服务的启动入口函数(DevmgrServiceStartService)

//初始化设备管理服务,并启动设备主机(Device Hosts)以及设备服务管理器(DevSvcManager)
int DevmgrServiceStartService(struct IDevmgrService *inst)|-->struct DevmgrService *dmService = (struct DevmgrService *)inst;//1.数据类型的强制转换|-->ret = DevmgrServiceStartDeviceHosts(dmService);//启动所有设备主机,加载设备驱动并初始化设备|-->if (!HdfAttributeManagerGetHostList(&hostList)) {//2.3.1初始化主机设备列表|-->while (HdfSListIteratorHasNext(&it)) {//遍历主机设备列表,启动每个主机设备|-->ret = DevmgrServiceStartDeviceHost(inst, hostAttr);//2.3.2启动主机设备|-->HdfSListFlush(&hostList, HdfHostInfoDelete);//清理主机设备列表|-->int startServiceRet = DevSvcManagerStartService();//2.3.3启动设备服务管理器,负责设备服务的管理和发布|-->struct IDevSvcManager *svcmgr = DevSvcManagerGetInstance()//获取设备管理服务的实例|--> ret = svcmgr->StartService(svcmgr)//启动设备管理器服务|-->return ret;

在进行后续启动流程的了解,建议先看下后续驱动模型章节的内容:

2.3.1初始化主机设备列表

从下图的代码流程图中可看出当前流程主要实现对配置文件hcs的解析,并根据解析的信息创建对应的host,并将host信息存储到hostlist链表中

在这里插入图片描述

  • 配置文件的解析参考配置管理章节

初始化主机设备列表主要是将解析的配置文件信息存储到DeviceResourceNode类型的hdfManagerNode指针中,从 hdfManagerNode 的子节点(child)开始,逐个遍历主机节点,每一个主机节点都会新创建一个新的主机信息实例hostInfo(struct HdfHostInfo),并从当前主机节点(hostNode)中提取主机信息,并填充到 hostInfo 中,最后将新创建的主机信息实例hostInfo添加到链表(hostList)中。参考以下为类图可辅助分析

在这里插入图片描述

2.3.2启动主机设备

启动主机设备即启动host,通过对代码的分析可主要分为三个关键步骤:创建设备主机客户端实例、获取当前主机下的设备列表和启动host进程,下面分别说明。

static int DevmgrServiceStartDeviceHost(struct DevmgrService *devmgr, struct HdfHostInfo *hostAttr)|-->struct DevHostServiceClnt *hostClnt = DevHostServiceClntNewInstance(hostAttr->hostId, hostAttr->hostName);//2.3.2.1.创建设备主机客户端实例|-->if (HdfAttributeManagerGetDeviceList(hostClnt) != HDF_SUCCESS) {return HDF_FAILURE;} //2.3.2.2.获取当前主机下的设备列表|-->DListInsertTail(&hostClnt->node, &devmgr->hosts);//新创建的主机客户端实例(hostClnt)插入到设备管理服务(devmgr)的主机链表(hosts)中|-->if (HdfSListIsEmpty(&hostClnt->unloadDevInfos)) {return HDF_SUCCESS;//检查主机客户端的 unloadDevInfos 链表是否为空|-->if (DevmgrServiceStartHostProcess(hostClnt, false, false) != HDF_SUCCESS) { //2.3.2.3.启动host进程|-->return HDF_SUCCESS;

首先根据从配置文件中获取的host(hostAttr)的id和名称去创建host的客户端实例,然后将此hostClnt实例传入到HdfAttributeManagerGetDeviceList中去获取此host下的设备device(实际也是从配置文件中去获取),然后将新创建的主机客户端实例(hostClnt)插入到设备管理服务(devmgr)的主机链表(hosts)中并判断一下是否包含静态启动的设备,为了节省资源,当没有静态启动的设备便不再启动host。当有静态启动设备时会启动host进程。

  1. 静态设备(Static Devices)

    • 静态设备是指在系统启动时需要立即加载和初始化的设备。
    • 它们的配置通常在 HDF 的配置文件(如 .hcs 文件)中明确指定,并且会在系统启动时自动加载。
    • 静态设备通常与系统的核心功能密切相关,需要在系统启动时就可用。
  2. 动态设备(Dynamic Devices)

    • 动态设备是指在系统运行过程中,根据需要动态加载和初始化的设备。
    • 它们通常由外部事件触发(例如,设备的插入或某个服务的请求)。
    • 动态设备不需要在系统启动时立即加载,因此可以节省资源,并且可以根据实际需求动态分配资源。

    为了便于理解可参考以下相关类图:
    在这里插入图片描述

2.3.2.1.创建设备主机客户端实例

根据上图的类图可知DevHostServiceClnt类型的成员变量都包含哪些,下图的创建设备host客户端实例的主要作用就是分配内存并赋初值

在这里插入图片描述

💙创建时传入的参数只有hostid(在解析配置文件时自动递增添加的唯一标识)和hostname(来自配置文件),即此实例除了具备内存之外便只具备这两个有效属性

2.3.2.2.获取当前主机下的设备列表

HdfAttributeManagerGetDeviceList函数主要实现获取指定主机(Host)下的设备列表,并将设备信息存储到hostClnt结构中,具体的代码流程如下:

在这里插入图片描述

由以上代码流程可看出代码首先从配置文件中根据hostname查找对应的主机(host)(①处),并将找到的主机赋值到hostNode,然后对hostNode的设备列表(device)做遍历操作再对设备实例(device)做遍历设备节点(devicenode)的操作(注意此时是遍历两次),操作时会新建设备节点信息实例(deviceNodeInfo),并将配置文件中的设备信息存储到新建的设备节点deviceNodeInfo中,最后根据配置的加载策略添加到不同的链表(unloadDevInfos(需要预加载)、dynamicDevInfos(动态加载))中(③处)。

在这里插入图片描述

  • 获取配置文件的根节点信息(②处)不属于此节内容所以忽略了。
  • 注意在创建设备节点信息实例(deviceNodeInfo)前遍历了两次,可根据上图的类图分析。
2.3.2.3.启动host进程

启动host进程的过程涉及的过程比较复杂,主要涉及主机服务安装器(DriverInstaller)的创建、启动设备host、关联设备管理服务与主机客户端、安装设备驱动、设备服务发布,下面分别说明

1.主机服务安装器(DriverInstaller)的创建

DriverInstaller 是一个关键组件,主要负责设备主机(Host)的启动和管理,此组件的为单实例创建,调用StartDeviceHost 接口启动设备主机进程。

在这里插入图片描述

由下图的类图可知主机服务安装器DriverInstaller实现了对IDriverInstaller类的继承,即获取了启动host和暂停host这两个方法,传入的参数即为hostid和hostName这两个有效属性。

在这里插入图片描述

2.启动设备host

对于每个主机,调用 DriverInstallerStartDeviceHost 函数启动主机进程

hostClnt->hostPid = installer->StartDeviceHost(hostAttr->hostId, hostAttr->hostName);
  • StartDeviceHost 会创建一个设备主机服务(DevHostService),并启动主机进程
  • 主机服务会调用 DevHostServiceStartService进一步初始化主机服务

在这里插入图片描述

新建非单实例设备每次会新分配内存,并赋值相关的devHostId和hostName。

在这里插入图片描述

  1. 关联设备管理服务与主机客户端

主机服务启动后,会通过 DevmgrServiceClntAttachDeviceHost 函数将设备管理服务(DevmgrServiceClnt)与主机客户端(DevHostServiceClnt)关联。详细如下图:

在这里插入图片描述

设备管理服务为单实例对象,获取后通过调用此对象的AttachDeviceHost接口。注意其中传入的参数包含IDevmgrService的实例,在匹配主机客户端时是通过hostid来查找对应的主机客户端的。

在这里插入图片描述

  1. 安装设备驱动

DevHostServiceClntInstallDriver 函数会遍历主机下的所有设备,调用 AddDevice 方法安装设备驱动。

DevHostServiceClntInstallDriver()
|-> HdfSListIteratorInit(&it, hostClnt->deviceInfos); // 初始化设备信息迭代器
|-> while (HdfSListIteratorHasNext(&it)) {deviceInfo = (struct HdfDeviceInfo *)HdfSListIteratorNext(&it);devHostSvcIf->AddDevice(devHostSvcIf, deviceInfo); // 安装设备驱动
}

具体的安装流程如下:

在这里插入图片描述

DevHostServiceAddDevice函数的核心功能是将设备信息与驱动程序关联起来,并完成设备的初始化和注册,首先会创建驱动加载器实例,然后确认设备主机(HdfDevice)是否已经存在,并根据设备模块名通过调用驱动加载器获取对应的驱动程序,最后创建一个新的设备节点实例(HdfDeviceNode),并调用设备对象(device)的 Attach 方法,将设备节点(HdfDeviceNode)绑定到设备对象。

在这里插入图片描述

  1. 设备服务发布

每个设备驱动安装完成后,会发布为一个设备服务节点,供其他模块使用.

在这里插入图片描述

设备服务发布主要实现启动设备节点(HdfDeviceNode)并完成设备驱动加载、初始化和服务发布。它的作用是将设备节点与驱动程序绑定,并确保设备服务能够被系统识别和使用。此过程会首先调用驱动中设置的bind函数实现将设备节点与驱动程序绑定,然后调用驱动程序的初始化函数(driverEntry->Init),最后将设备节点的服务发布到设备服务管理器并将节点的令牌挂载到设备管理服务。

2.3.3启动设备服务管理器

设备服务管理器(DevSvcManager)扩展模块的启动函数,其主要作用是初始化和启动设备服务管理器。主要实现初始化设备服务管理器的设备对象和服务接口、发布设备服务管理器的 I/O 服务以及初始化服务状态监听器。

在这里插入图片描述

2.4 电源管理的初始化

电源管理的初始化,主要作用是注意一个电源管理的回调函数,当有电源状态变化时进行回调。
在这里插入图片描述

2.5 驱动加载总结

1)在系统启动时,DeviceManagerInit通过late_initcall先启动

  1. Device Manager 根据 Device Information (deviceInfo.hcs)信息,解析配置文件中的 Host 列表,根据 Host表中的信息来实例化对应的 Host 对象

3)Host遍历设备列表去获取与之匹配的驱动程序名称,然后基于驱动程序名称遍历.hdf.driver secon 获得驱动程序地址。

4)设备与驱动匹配成功之后,获取指定驱动的入口地址,加载对应的设备驱动程序

5)调用指定驱动的 Bind 接口,用于关联设备和服务实例。

6)调用指定驱动的 Init 接口,用于完成驱动的相关初始化工作。

7)如果驱动被卸载或者因为硬件等原因 Init 接口返回失败,Release 将被调用,用于释放驱动申谈的各类资源。

相关文章:

openharmony中HDF驱动框架源码梳理-驱动加载流程

要想大概了解一个公司,我们可能只需要知道它的运行逻辑即可,例如我们只需要知道它有财务有研发有运营等,财务报销、研发负责产品等即可,但是如果想深入具体的了解的话我们就要了解都有什么部门(对象)、各部门都包含哪些职责(对象方…...

golang 高性能的 MySQL 数据导出

需求导出方式对比方案1:快照导出(耗时:1.5s)方案2: 偏移分页(耗时:4s)方案 3:普通分页(耗时:4min40s) 需求 导出 MySQL 数据 分析: 一次性 select 大量数据带来的问题 性能问题: 数据库负载:大量数据查询会增加数据库的CPU、内存和I/O负担&#xff…...

31-判断子序列

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列&#x…...

leetcode日记(95)将有序数组转换为二叉搜索树

很简单,感觉自己越来越适应数据结构题目了…… /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : va…...

使用SSH密钥连接本地git 和 github

目录 配置本地SSH,添加到github首先查看本地是否有SSH密钥生成SSH密钥,和邮箱绑定将 SSH 密钥添加到 ssh-agent:显示本地公钥*把下面这一串生成的公钥存到github上* 验证SSH配置是否成功终端跳转到本地仓库把http协议改为SSH(如果…...

C语言基础之【内存管理】

C语言基础之【内存管理】 存储类型作用域普通局部变量静态局部变量普通全局变量静态全局变量全局函数和静态函数 内存布局内存分区存储类型与内存四区内存操作函数memset()memcpy()memmove()memcmp() 堆区内存分配和释放malloc()free() 内存分区代码分析返回栈区地址返回data区…...

C盘清理技巧分享:释放空间,提升电脑性能

目录 1. 引言 2. C盘空间不足的影响 3. C盘清理的必要性 4. C盘清理的具体技巧 4.1 删除临时文件 4.2 清理系统还原点 4.3 卸载不必要的程序 4.4 清理下载文件夹 4.5 移动大文件到其他盘 4.6 清理系统缓存 4.7 使用磁盘清理工具 4.8 清理Windows更新文件 4.9 禁用…...

每天一道算法题【蓝桥杯】【两两交换链表中的节点】

思路 本质问题可以分成若干个子问题 即把前两个链表交换,并与后面的链表相连 故实现函数功能调用自身递归即可 #define _CRT_SECURE_NO_WARNINGS 1 struct ListNode {int val;ListNode *next;ListNode() : val(0), next(nullptr) {}ListNode(int x) : val(x), nex…...

mIoU Class与mIoU Category的区别

mIoU(mean Intersection over Union)是语义分割任务中常用的评估指标,用于衡量模型预测的分割结果与真实标签之间的重叠程度。mIoU Class 和 mIoU Category 的区别主要体现在计算方式和应用场景上: 1. mIoU Class 定义&#xff…...

深入解析 C 语言中含数组和指针的构造体与共同体内存计算

在 C 语言中,构造体(struct)和共同体(union)允许我们将多种数据类型组合到一起。除了常见的基本数据类型之外,经常还会在它们中嵌入数组和指针。由于数组的内存是连续分配的,而指针的大小与平台…...

【C++模板】:开启泛型编程之门(函数模版,类模板)

📝前言: 在上一篇文章C内存管理中我们介绍了C的内存管理,重点介绍了与C语言的区别,以及new和delete。这篇文章我们将介绍C的利器——模板。 在C编程世界里,模板是一项强大的特性,它为泛型编程奠定了坚实基础…...

HEC-HMS水文建模全解析:气候变化与极端水文、离散化流域单元‌精准刻画地表径流、基流与河道演进过程‌

一、技术革新:数字流域的精密算法革命 在全球气候变化与极端水文事件频发的双重压力下,HEC-HMS模型凭借其‌半分布式建模架构‌与‌多尺度仿真能力‌,已成为现代流域管理的核心工具。该模型通过‌离散化流域单元‌精准刻画地表径流、基流与河…...

具备多种功能的PDF文件处理工具

软件介绍 在日常办公和学习场景中,PDF文件使用极为频繁,而一款功能强大的PDF编辑软件能大幅提升处理效率。 今天要介绍的Adobe Acrobat Pro DC 2024.005.20414,就具备像编辑Word文档一样便捷编辑PDF的能力。 PDF文档在学习和工作中广泛应用…...

【SpringMVC】SpringMVC的启动过程与原理分析:从源码到实战

SpringMVC的启动过程与原理分析:从源码到实战 SpringMVC是Spring框架中用于构建Web应用的核心模块,它基于MVC(Model-View-Controller)设计模式,提供了灵活且强大的Web开发能力。本文将深入分析SpringMVC的启动过程、核…...

转自南京日报:天洑软件创新AI+仿真技术变制造为“智造

以下文章来源:南京日报 进入3月,南京天洑软件有限公司(以下简称天洑软件)董事长张明更加忙碌。“公司强调工业软件在数字经济与先进制造业融合中的关键作用,并已广泛应用在能源、电力和航空等领域。”他说,…...

golang dlv调试工具

golang dlv调试工具 在goland2022.2版本 中调试go程序报错 WARNING: undefined behavior - version of Delve is too old for Go version 1.20.7 (maximum supported version 1.19) 即使你go install了新的dlv也无济于事 分析得出Goland实际使用的是 Goland安装目录下dlv 例…...

LSTM方法实践——基于LSTM的汽车销量时序建模与预测分析

Hi,大家好,我是半亩花海。本实验基于汽车销量时序数据,使用LSTM网络(长短期记忆网络)构建时间序列预测模型。通过数据预处理、模型训练与评估等完整流程,验证LSTM在短期时序预测中的有效性。 目录 一、实验…...

微服务——网关、网关登录校验、OpenFeign传递共享信息、Nacos共享配置以及热更新、动态路由

之前学习了Nacos,用于发现并注册、管理项目里所有的微服务,而OpenFeign简化微服务之间的通信,而为了使得前端可以使用微服务项目里的每一个微服务的接口,就应该将所有微服务的接口管理起来方便前端调用,所以有了网关。…...

【数据结构】二叉搜索树、平衡搜索树、红黑树

二叉搜索树(Binary Search Tree) 二叉搜索树是一种特殊的二叉树,它用来快速搜索某个值,对于每个节点都应该满足以下条件: 若该节点有左子树,那么左子树中所有节点的值都应该小于该节点的值。若该节点有右…...

Spring Boot 解析 LocalDateTime 失败?Uniapp 传输时间变 1970 的原因与解决方案

目录 前言1. 问题分析2. 时间戳(推荐,可尝试)3. 使用 JsonDeserialize & JsonSerialize(中立)4. 前端传 ISO-8601 格式(不推荐,可尝试)5. 用 String(中立&#xff09…...

Xilinx ZYNQ FSBL解读:LoadBootImage()

篇首 最近突发奇想,Xilinx 的集成开发环境已经很好了,很多必要的代码都直接生成了,这给开发者带来了巨大便利的同时,也让人错过了很多代码的精彩,可能有很多人用了很多年了,都还无法清楚的理解其中过程。博…...

mysql中in和exists的区别?

大家好,我是锋哥。今天分享关于【mysql中in和exists的区别?】面试题。希望对大家有帮助; mysql中in和exists的区别? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 MySQL 中,IN 和 EXISTS 都用于进行子查询,但它…...

oracle 数据导出方案

工作中有遇到需要将oracle 数据库表全部导出,还需要去除表数据中的换行符。 方案 shell 设计 封装函数 1 function con_oracle() 用于连接oracle 2 function send_file() 用于发送文件 3 主程序 使用循环将所有表导出并发送到数据服务器 主程序 程序代码 #!…...

Apache Commons Lang3 和 Commons Net 详解

目录 1. Apache Commons Lang3 1.1 什么是 Apache Commons Lang3? 1.2 主要功能 1.3 示例代码 2. Commons Net 2.1 什么是 Commons Net? 2.2 主要功能 2.3 示例代码 3. 总结 3.1 Apache Commons Lang3 3.2 Commons Net 3.3 使用建议 4. 参考…...

从0开始的操作系统手搓教程33:挂载我们的文件系统

目录 代码实现 添加到初始化上 上电看现象 挂载分区可能是一些朋友不理解的——实际上挂载就是将我们的文件系统封装好了的设备(硬盘啊,SD卡啊,U盘啊等等),挂到我们的默认分区路径下。这样我们就能访问到了&#xff…...

【Linux】36.简单的TCP网络程序

文章目录 1. TCP socket API 详解1.1 socket():打开一个网络通讯端口1.2 bind():绑定一个固定的网络地址和端口号1.3 listen():声明sockfd处于监听状态1.4 accept():接受连接1.5 connect():连接服务器 2. 实现一个TCP网络服务器2.1 Log.hpp - "多级日志系统"2.2 Daem…...

时序分析

1、基本概念介绍 1.1、 建立时间 T(su) 建立时间:setup time,它是指有效的边沿信号到来之前,输入端口数据保持稳定的时间。 1.1.1、 建立时间要求: 建立时间要求指的是 想要寄存器如期的工作,在有效时…...

doris:ClickHouse

Doris JDBC Catalog 支持通过标准 JDBC 接口连接 ClickHouse 数据库。本文档介绍如何配置 ClickHouse 数据库连接。 使用须知​ 要连接到 ClickHouse 数据库,您需要 ClickHouse 23.x 或更高版本 (低于此版本未经充分测试)。 ClickHouse 数据库的 JDBC 驱动程序&a…...

NLP常见任务专题介绍(1)-关系抽取(Relation Extraction, RE)任务训练模板

📌 关系抽取(Relation Extraction, RE)任务训练示例 本示例展示如何训练一个关系抽取模型,以识别两个实体之间的关系。 1️⃣ 任务描述 目标:从文本中提取两个实体之间的语义关系,例如 “人物 - 组织”、“药物 - 疾病”、“公司 - 创始人” 等。输入:句子 + 标注的实…...

大模型Transformer的MOE架构介绍及方案整理

前言:DeepSeek模型最近引起了NLP领域的极大关注,也让大家进一步对MOE(混合专家网络)架构提起了信心,借此机会整理下MOE的简单知识和对应的大模型。本文的思路是MOE的起源介绍、原理解释、再到现有MOE大模型的整理。 一…...