OpenHarmony-3.HDF框架(2)

news2024/12/26 19:39:51
  • OpenHarmony HDF 平台驱动

1.平台驱动概述

  系统平台驱动框架是系统驱动框架的重要组成部分,它基于HDF驱动框架、操作系统适配层(OSAL, operating system abstraction layer)以及驱动配置管理机制,为各类平台设备驱动的实现提供标准模型。

  系统平台驱动(PlatformDriver),即平台设备驱动,它用于驱动平台设备(PlatformDevice),为系统及外设驱动提供访接口。这里的平台设备,泛指I2C/UART等总线、以及GPIO/RTC等SOC片内硬件资源。

  系统平台驱动框架为外设提供了标准的平台设备访问接口,使其不必关注具体硬件及OS平台;同时为平台设备驱动提供统一的适配接口,使其只关注自身硬件的控制。

  为实现这个目标,OpenHarmony系统平台驱动框架满足如下特性:

  • 统一的平台设备访问接口:对平台设备操作接口进行统一封装,屏蔽不同SOC平台硬件差异以及不同OS形态差异。
  • 统一的平台驱动适配接口:为平台设备驱动提供统一的适配接口,使其只关注自身硬件的控制,而不必关注设备管理及公共业务流程。
  • 提供设备注册、管理、访问控制等与SOC无关的公共能力。

2.平台驱动框架介绍

  OpenHarmony系统平台驱动框架主要由平台接口层、平台核心层以及平台适配层三个部分组成。
在这里插入图片描述

  • 平台接口层 以API的形式提供标准的平台设备访问接口。

    平台接口层以设备句柄加配套API的形式对外提供统一的、标准的访问接口。

    设备句柄是DevHandle类型的实例,通过不同设备模块提供的Open/Close方法进行获取、释放。成功获取设备句柄后,即可使用相应的API执行设备操作。例如通过I2cTransfer完成一次I2C数据传输。

    这是一种代理模式,即接口层API不直接引用实际设备对象,而是通过DevHandle作为代理,间接访问设备;而所有来自外设驱动的访问,都建议走接口层,以获得最佳的稳定性。

  • 平台核心层 提供平台设备模型及公共业务框架。
    提供统一适配接口:定义了标准的设备对象模型,驱动程序仅需关注标准对象模型的适配。

    抽取公共业务框架:将不同设备模块的公共流程、算法加以抽取,使得具体设备驱动更加轻薄。

    设备管理:设备注册、注销、设备查找、访问控制。

  • 平台适配层 提供特定平台设备的适配驱动,并遵守核心层约束。

    驱动具体平台设备硬件,并创建对应的设备模型对象,注册到核心层纳入统一管理。

2.1.平台接口层分析

  接口层用DevHandle类型的设备句柄表示一个平台设备对象,然后针对不同类型设备提供一套标准的API方法用于设备访问。那么设备句柄和真实的设备对象如何关联呢?

 drivers_hdf_core/framework/include/platform/platform_if.h:
 39 /**
 40  * @brief Defines the common device handle of the platform driver.
 41  *
 42  * The handle is associated with a specific platform device and is used as the
 43  * first input parameter for all APIs of the platform driver.
 44  *
 45  * @since 1.0
 46  */
 47 typedef void* DevHandle;

  在内核态,这个指针可以直接指向实际设备对象,但是对于某些类型的平台设备,需要在用户态提供同样的DevHandle类型及配套API,而实际设备对象在内核空间,导致无法直接获取和使用内核空间的地址。

  解决办法:将平台设备对象实现为一个HDF设备服务,这样借助HDF DeviceManager的设备服务机制,可以在用户态、内核态同时获取到设备服务,而用户态同内核态通信的问题交由HDF DeviceManager处理。此时,DevHandle只需要关联到这个设备服务即可,而void*类型保证了足够的灵活性。

  根据DevHandle和设备对象关联方式的不同,接口层的设计有三种模式:

2.1.1.独立服务模式

  典型实践是UART模块。
在这里插入图片描述
  使用范围:在用户态和内核态同时提供API的设备类型,DevHandle同设备对象的关联方式为:

  • 用户态:关联到平台设备对应的设备服务;

  • 内核态:关联到实际平台设备对象或其设备服务(在内核态两者可互相转换)

  每一个设备对象,会独立发布一个设备服务,来处理外部访问,服务收到API的访问请求之后,通过提取请求参数,并调用实际设备对象的相应内部方法。

  优点:管理比较简单,因为它借助了HDF DeviceManager的服务管理能力;
  缺点:需要为每一个设备对象配置设备节点,以便发布设备服务。

2.1.2.统一服务模式

  典型实践是I2C模块。
在这里插入图片描述
  同一类型的设备对象可能会很多,例如I2C模块,可能同时有十几个控制器。如果采用独立服务的模式,每一个控制器,作为一个平台设备,为其创建一个设备服务,那么将会有十几个服务被创建,不光要配置很多设备节点,而且这些服务还会占用内存资源。

  因此为一类设备对象,创建一个平台设备管理器(PlatformManager)对象,并同时对外发布一个管理器服务,由这个管理器服务来统一处理外部访问。当用户需要打开某个设备时,先通过HDF DeviceManager获取到管理器服务,然后管理器服务根据用户指定参数查找到指定设备,并返回一个设备描述符,而这个描述符仍然可以由DevHandle类型表示。

2.1.3.无服务模式
在这里插入图片描述  用于不需要在用户态提供API的设备类型或者没有用户态、内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址。而PlatformManager的实现比较自由,它不需要实现设备服务,只需做好某种类型的设备管理即可,甚至在C语言中,由于无法进行OOP编程,很多模块直接将这个功能面向过程化了,使得没有一个具体的结构体与之对应。

2.2.平台核心层

  平台核心层的作用是承上启下,其主要内容包括:

  • 提供适配接口:为具体的平台设备驱动提供统一的适配接口

    平台驱动框架为不同设备类型,定义了标准的设备对象模型,具体设备驱动只需要关注标准设备对象的适配即可

  • 提供设备管理:提供设备的注册、注销、查找等功能、访问控制等能力

    核心层会提供一系列内部方法,用于设备的注册、注销,设备对象的查找、获取、释放,以及处理多线程访问。例如当向核心层注册一个I2C控制器对象时,使用I2cCntlrAdd;当希望获取一个I2C控制器对象时,通过I2cCntlrGet并指定控制器编号;当不再使用这个对象时,还需要通过I2cCntlrPut释放。这样做的好处是将每一个具体的操作步骤高度抽象化,减小同平台接口层及平台适配层的耦合面,便于业务解耦、演进。由于业务需求需要对I2cCntlr对象进行引用计数,那么只需要修改I2cCntlrGet/Put这对方法的实现即可,并不会影响平台接口层和平台适配层。

  • 公共业务实现:抽取公共的业务流程、算法
    凡是跟特定硬件无关的业务逻辑,都会被抽取到核心层,例如RTC时钟的时间格式转换算法,GPIO模块的线程中断实现等等。

2.3.平台适配层实现

  适配层提供具体平台硬件设备的驱动,按照核心层定义的模型创建设备对象,并完成对象的初始化(包括必要的成员变量初始化以及钩子方法挂接,以及相关的硬件初始化操作),最后使用核心层提供的注册方法将设备对象注册到核心层纳入统一管理。

3.OpenHarmony系统平台驱动适配

3.1.UART模块适配

  UART模块适配的核心环节,是UartHost对象的创建、初始化及注册。UART模块采用的是独立服务模式,要求每一个UartHost对象关联一个HDF设备服务。

1).device_info.hcs: 为每一个UART控制器配置一个HDF设备节点

 vendor/hihope/rk3568/hdf_config/khdf/device_info/device_info.hcs:
 71             device_uart :: device {
 72                 device0 :: deviceNode {
 73                     policy = 2;
 74                     priority = 40;
 75                     permission = 0644;
 76                     moduleName = "HDF_PLATFORM_UART";
 77                     serviceName = "HDF_PLATFORM_UART_0";
 78                     deviceMatchAttr = "rockchip_rk3568_uart_0";
 79                 }
 80                 device1 :: deviceNode {
 81                     policy = 2;
 82                     permission = 0644;
 83                     priority = 40;
 84                     moduleName = "HDF_PLATFORM_UART";
 85                     serviceName = "HDF_PLATFORM_UART_1";
 86                     deviceMatchAttr = "rockchip_rk3568_uart_1";
 87                 }
 88                 device2 :: deviceNode {
 89                     policy = 2;
 90                     permission = 0644;
 91                     priority = 40;
 92                     moduleName = "HDF_PLATFORM_UART";
 93                     serviceName = "HDF_PLATFORM_UART_3";
 94                     deviceMatchAttr = "rockchip_rk3568_uart_3";
 95                 }
 96             }

说明:

  • policy大于等于1(如需对用户态可见为2,仅内核态可见为1);

  • moduleName需要与驱动Entry中moduleName 保持一致;

  • serviceName必须要按照HDF_PLATFORM_UART_X的格式,X为UART控制器编号;

  • deviceMatchAttr用于配置控制器私有数据,要与uart_config.hcs中对应控制器保持一致,如不需要则忽略。

2). uart_config.hcs:每一个UART控制器配置私有数据

  如果控制器需要配置一些私有数据,例如寄存器基地址,初始化波特率等等,可以在uart_config.hcs中配置,该文件将在产品配置目录的hdf.hcs中导入,具体路径可由产品自由配置。

 vendor/hihope/rk3568/hdf_config/khdf/platform/rk3568_uart_config.hcs:
  1 root {
  2     platform {
  3         uart_config {
  4             template uart_device {
  5                 serviceName = "";
  6                 match_attr = "";
  7                 driver_name = "ttyS";
  8                 num = 0;
  9             }
 10
 11             device_uart_0x0000 :: uart_device {
 12                 match_attr = "rockchip_rk3568_uart_0";
 13             }
 14             device_uart_0x0001 :: uart_device {
 15                 num = 1;
 16                 match_attr = "rockchip_rk3568_uart_1";
 17             }
 18             device_uart_0x0003 :: uart_device {
 19                 num = 3;
 20                 match_attr = "rockchip_rk3568_uart_3";
 21             }
 22         }
 23     }
 24 }
 
  hihope/rk3568/hdf_config/khdf/hdf.hcs:
  1 #include "device_info/device_info.hcs"
  2 #include "platform/adc_config_linux.hcs"
  3 #include "platform/pwm_config.hcs"
  4 #include "platform/rk3568_watchdog_config.hcs"
  5 #include "platform/rk3568_uart_config.hcs"
  6 #include "platform/sdio_config.hcs"
  7 #include "platform/emmc_config.hcs"
  8 #include "platform/rk3568_spi_config.hcs"
  9 #include "input/input_config.hcs"
 10 #include "wifi/wlan_platform.hcs"
 11 #include "wifi/wlan_chip_ap6275s.hcs"
 12 #include "camera/camera_config.hcs"
 13 #include "sensor/sensor_config.hcs"
 14 #include "audio/audio_config.hcs"
 15 #include "audio/codec_config.hcs"
 16 #include "audio/dai_config.hcs"
 17 #include "audio/dma_config.hcs"
 18 #include "audio/dsp_config.hcs"
 19 #include "audio/analog_headset_config.hcs"
 20 #include "light/light_config.hcs"
 21 #include "vibrator/vibrator_config.hcs"
 22 #include "vibrator/linear_vibrator_config.hcs"
 23 #include "vibrator/drv2605l_linear_vibrator_config.hcs"
 24 #include "lcd/lcd_config.hcs"

3).驱动的Entry结构

先执行Bind方法绑定服务,后执行Init 初始化。

drivers_hdf_core\framework\sample\platform\uart\src\uart_sample.c
struct HdfDriverEntry g_sampleUartDriverEntry = {
    .moduleVersion = 1,
    .moduleName = "UART_SAMPLE",
    .Bind = SampleUartDriverBind,
    .Init = SampleUartDriverInit,
    .Release = SampleUartDriverRelease,
};

// Initialize HdfDriverEntry
HDF_INIT(g_sampleUartDriverEntry);
  • Bind方法调用UartHostCreate创建 UartHost 控制器对象并完成服务绑定。
drivers_hdf_coreframework\support\platform\include\uart\uart_core.h:
struct UartHost {
    struct IDeviceIoService service;
    struct HdfDeviceObject *device;
    uint32_t num;
    OsalAtomic atom;
    void *priv;
    struct UartHostMethod *method;
};

drivers_hdf_core\framework\sample\platform\uart\src\uart_sample.c
static int32_t SampleUartDriverBind(struct HdfDeviceObject *device)
{
    struct UartHost *uartHost = NULL;
    HDF_LOGD("%s: Enter", __func__);

    uartHost = UartHostCreate(device);
    uartHost->service.Dispatch = SampleDispatch;
    return HDF_SUCCESS;
}

drivers_hdf_core/framework/support/platform/src/uart/uart_core.c
 79 struct UartHost *UartHostCreate(struct HdfDeviceObject *device)
 80 {
 81     struct UartHost *host = NULL;
 82
 88     host = (struct UartHost *)OsalMemCalloc(sizeof(*host));
 93
 94     host->device = device;
 95     device->service = &(host->service);
 96     host->device->service->Dispatch = UartIoDispatch;
 97     OsalAtomicSet(&host->atom, 0);
 98     host->priv = NULL;
 99     host->method = NULL;
100     return host;
101 }

  该方法中将UartHost对象同HdfDeviceObject进行关联:

  • 为HdfDeviceObject的service成员进行赋值,使其指向UartHost的IDeviceIoService类型的成员对象;
  • 同时为service成员的Dispatch方法赋值。
    UartHostCreate函数设置host->device->service->Dispatch = UartIoDispatch; 最后SampleUartDriverBind函数使用uartHost->service.Dispatch = SampleDispatch; 进行覆盖UartIoDispatch。

  这样做的结果:

  • 为HdfDeviceObject对象绑定IDeviceIoService类型的服务对象

  • UartHost和其IDeviceIoService类型的成员对象service可以相互转换

  • 通过UartHost对象即可获取HdfDeviceObject对象

  • 通过HdfDeviceObject对象即可间接获取UartHost对象(先获取service再转为host)

4). Init方法

  完成UartHost对象的初始化。代码调用流程:

SampleUartDriverInit
	->AttachUartDevice
		->AddUartDevice
			->AddRemoveUartDev
				->register_driver
	->host->method = &g_sampleUartHostMethod;

  代码分析:

drivers_hdf_core\framework\sample\platform\uart\src\uart_sample.c
static int32_t SampleUartDriverInit(struct HdfDeviceObject *device)
{
    int32_t ret;
    struct UartHost *host = NULL;
    HDF_LOGD("%s: Enter", __func__);

    host = UartHostFromDevice(device);
    ret = AttachUartDevice(host, device);
    host->method = &g_sampleUartHostMethod;
    return ret;
}

struct UartHostMethod g_sampleUartHostMethod = {
    .Init = SampleUartHostInit,
    .Deinit = SampleUartHostDeinit,
    .Read = NULL,
    .Write = SampleUartHostWrite,
    .SetBaud = SampleUartHostSetBaud,
    .GetBaud = SampleUartHostGetBaud,
    .SetAttribute = NULL,
    .GetAttribute = NULL,
    .SetTransMode = NULL,
};

  通过UartHostFromDevice从HdfDeviceObject对象获取之前关联的UartHost对象,然后调用 AttachUartDevice方法完成host对象的初始化,最后为host对象挂接钩子方法g_sampleUartHostMethod。

  小结:

  UART适配关键是在驱动Entry的Bind方法中创建UartHost对象,而且是使用UartHostCreate创建。这个创建动作同时也是注册的动作,因为它将UartHost以HDF设备服务的形式同HdfDeviceObject进行绑定,这样就完成了服务的发布,HDF Manager对设备服务的管理也就是对UartHost的管理,核心层可以通过HDF提供的服务获取接口来访问UartHost。

  UART适配采用独立服务模式,每一个UartHost对象同时也是一个设备服务,其优点是可以直接利用HDF Manager进行管理;缺点是需要在device_info.hcs为每一个UartHost对象定义设备节点。

3.2.UART模块主要接口

  • drivers/hdf_core/framework/include/platform/uart_if.h
DevHandle UartOpen(uint32_t port)	UART获取设备句柄
void UartClose(DevHandle handle)	UART释放设备句柄
int32_t UartRead(DevHandle handle, uint8_t *data, uint32_t size)	从UART设备中读取指定长度的数据
int32_t UartWrite(DevHandle handle, uint8_t *data, uint32_t size)	向UART设备中写入指定长度的数据
int32_t UartGetBaud(DevHandle handle, uint32_t *baudRate)	UART获取波特率
int32_t UartSetBaud(DevHandle handle, uint32_t baudRate)	UART设置波特率
int32_t UartGetAttribute(DevHandle handle, struct UartAttribute *attribute)	UART获取设备属性
int32_t UartSetAttribute(DevHandle handle, struct UartAttribute *attribute)	UART设置设备属性
int32_t UartSetTransMode(DevHandle handle, enum UartTransMode mode)	UART设置传输模式

本文涉及的UART所有接口,支持内核态及用户态使用。

3.2.1.UartOpen

UartOpen
	->UartGetObjGetByBusNum(port);
		-> DevSvcManagerClntGetService(name)  
	-> UartHostRequest((struct UartHost *)handle);
  • UartGetObjGetByBusNum 调用DevSvcManagerClntGetService,根据name=“HDF_PLATFORM_UART_port” (framework/sample/config/device_info/device_info.hcs) 获取到handle 即host。
  • UartHostRequest 调用host->method->Init,即UartHostDevInit(uart_asr.c)

3.2.2.UartWrite

int32_t UartWrite(struct DevHandle *handle, uint8_t *data, uint32_t size)
{
    int ret;
    struct HdfIoService *service = NULL;

    struct HdfSBuf *sBuf = HdfSbufObtainDefaultSize();

    if (!HdfSbufWriteBuffer(sBuf, data, size)) {
        HDF_LOGE("Failed to write sbuf");
        HdfSbufRecycle(sBuf);
        return HDF_FAILURE;
    }

    service = (struct HdfIoService *)handle->object;
    ret = service->dispatcher->Dispatch(&service->object, UART_WRITE, sBuf, NULL);

    HdfSbufRecycle(sBuf);
    return ret;
}
  • 调用Dispatch接口进行写操作,即SampleDispatch,通过传输cmd 为UART_WRITE调用SampleDispatchWrite,然后调用UartPl011Write调用底层代码进行传输数据。
drivers_hdf_core\framework\sample\platform\uart\src\uart_dispatch_sample.c
int32_t SampleDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
{
    int32_t result = HDF_FAILURE;
    (void)reply;

    struct UartHost *uartHost = (struct UartHost *)client->device->service;

    struct UartDevice *uartDevice = (struct UartDevice *)uartHost->priv;
 
    switch (cmdId) {
        case UART_WRITE: {
            result = SampleDispatchWrite(uartDevice, data);
            break;
        }
        default:
            break;
    }
    return result;
}

static int32_t SampleDispatchWrite(struct UartDevice *device, struct HdfSBuf *txBuf)
{
    uint32_t idx;
    uint32_t dataSize = 0;
    const uint8_t *data = NULL;
    struct UartRegisterMap *regMap = (struct UartRegisterMap *)device->resource.physBase;

    if (!HdfSbufReadBuffer(txBuf, (const void **)&data, &dataSize)) {
        HDF_LOGE("%s: Failed to read sbuf", __func__);
        return HDF_FAILURE;
    }
    regMap = (struct UartRegisterMap *)device->resource.physBase;
    for (idx = 0; idx < dataSize; idx++) {
        UartPl011Write(regMap, data[idx]);
    }
    return HDF_SUCCESS;
}

drivers_hdf_core\framework\sample\platform\uart\include\uart_pl011_sample.h
static inline void UartPl011Write(struct UartRegisterMap *regMap, uint8_t byte)
{
    while (UartPl011IsBusy(regMap)) {}
    regMap->dr = byte;
}

3.3.用户层测试代码

  • 通过/dev/uartdev-%d 节点访问
drivers_hdf_core\framework\sample\platform\uart\dev\hello_uart_dev.c
int main(void)
{
    int ret;
    int fd;
    const char info[INFO_SIZE] = {" HELLO UART! "};

    fd = open("/dev/uartdev-5", O_RDWR);
    if (fd < 0) {
        HDF_LOGE("uartdev-5 open failed %d", fd);
        return -1;
    }
    ret = write(fd, info, INFO_SIZE);
    if (ret != 0) {
        HDF_LOGE("write uartdev-5 ret is %d", ret);
    }
    ret = close(fd);
    if (ret != 0) {
        HDF_LOGE("uartdev-5 close failed %d", fd);
        return -1;
    }
    return ret;
}
  • 使用UartOpen 接口进行方法
drivers_hdf_core\framework\sample\platform\uart\dispatch\hello_uart_dispatch.c
int main(void)
{
    const char *info = " HELLO UART! ";

    struct DevHandle *handle = UartOpen(UART_PORT);
    int ret = UartWrite(handle, (uint8_t *)info, strlen(info));
    UartClose(handle);
    return ret;
}

refer to

  • git clone https://gitee.com/openharmony/drivers_hdf_core.git
  • https://blog.csdn.net/HarmonyOS_666/article/details/140824175
  • https://blog.csdn.net/maniuT/article/details/141064333
  • https://blog.csdn.net/zxc95279527q/article/details/143062695

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2254538.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Guiding a Diffusion Model with a Bad Version of Itself

Guiding a Diffusion Model with a Bad Version of Itself Abstract1. Introduction2. Background3. Why does CFG improve image quality?Score matching leads to outliers.CFG 消除异常值Discussion 4 Our method Abstract 在图像生成扩散模型中&#xff0c;主要关注的轴心…

Tomcat,javaweb, servlet , springBoot

在server.xml里配置服务器 <scope>provided</scope>打包的时候&#xff0c;这个jar包不会被打进去&#xff0c;因为tomcat已将封装了这个jar包&#xff0c;没必要要这个

D614 PHP+MYSQL +失物招领系统网站的设计与现 源代码 配置 文档

失物招领系统 1.摘要2. 系统开发的背景和意义3.功能结构图4.界面展示5.源码获取 1.摘要 随着互联网的迅速发展&#xff0c;人们的生产生活方式逐渐发生改变&#xff0c;传统的失物招领也可以通过网络处理。本网站是基PHP技术的一款综合性较强的西南民族大学PHP失物招领系统。 …

单总线one-Wire

单总线one-Wire 概述 One-Wire总线是DALLAS公司研制开发的一种协议 特点&#xff1a; 它是由一个总线主节点&#xff0c;一个或多个从节点组成系统&#xff0c;通过一根信号线对从芯片进行数据的读取 每一个符合One-Wire协议的从芯片都有一个唯一的地址&#xff0c;包括48位的…

【llm】——香橙派AIPRO跑qwen2.5-0.5B

qwen2在Ascend310B4上的评测 代码/模型&#xff1a;https://github.com/chenjun2hao/qwen-ascend-llm 依赖 香橙派AIPRO&#xff1a;http://www.orangepi.cn/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-AIpro.htmlCANN8.0&#xff08;自己手动安装的&#…

Android 单元测试断言校验方法 org.junit.Assert

判断布尔值 assertTrue assertFalse 判断对象非空 assertNull(object); 案例&#xff1a; PersistableBundle result Util.getCarrierConfig(mockContext, subId);assertNull(result); 判断是否相等 assertEquals("mocked_string", result.toString()); package or…

Flink 中双流 Join 的深度解析与实战

目录 一、Join 算子 一&#xff09;语义与特性 二&#xff09;通用用法 三&#xff09;不同窗口类型表现 滚动窗口 Join 滑动窗口 Join 二、CoGroup 算子 一&#xff09;功能特点 二&#xff09;通用用法与连接类型实现 内连接&#xff08;InnerJoin&#xff09; 左…

OpenStack-Glance组件

Glance Glance使用磁盘格式和容器格式基础配置镜像转换 Glance 是 OpenStack 的镜像服务&#xff0c;负责存储、发现和管理虚拟机镜像。它允许用户创建和共享镜像&#xff0c;用于启动虚拟机实例。 Glance 的主要功能 &#xff08;1&#xff09;虚拟机镜像的管理 支持镜像的上…

基于神经网络的弹弹堂类游戏弹道快速预测

目录 一、 目的... 1 1.1 输入与输出.... 1 1.2 隐网络架构设计.... 1 1.3 激活函数与损失函数.... 1 二、 训练... 2 2.1 数据加载与预处理.... 2 2.2 训练过程.... 2 2.3 训练参数与设置.... 2 三、 测试与分析... 2 3.1 性能对比.... 2 3.2 训练过程差异.... 3 四、…

Linux入门攻坚——40、Linux集群系统入门-lvs(1)

Cluster&#xff0c;集群&#xff0c;为了解决某个特定问题将多台计算机组合起来形成的单个系统。 这个单个集群系统可以扩展&#xff0c;系统扩展的方式&#xff1a;scale up&#xff0c;向上扩展&#xff0c;更换更好的主机&#xff1b;scale out&#xff0c;向外扩展&…

威联通-001 手机相册备份

文章目录 前言1.Qfile Pro2.Qsync Pro总结 前言 威联通有两种数据备份手段&#xff1a;1.Qfile Pro和2.Qsync Pro&#xff0c;实践使用中存在一些区别&#xff0c;针对不同备份环境选择是不同。 1.Qfile Pro 用来备份制定目录内容的。 2.Qsync Pro 主要用来查看和操作文…

Docker单机网络:解锁本地开发环境的无限潜能

作者简介&#xff1a;我是团团儿&#xff0c;是一名专注于云计算领域的专业创作者&#xff0c;感谢大家的关注 座右铭&#xff1a; 云端筑梦&#xff0c;数据为翼&#xff0c;探索无限可能&#xff0c;引领云计算新纪元 个人主页&#xff1a;团儿.-CSDN博客 目录 前言&#…

【Linux操作系统】多线程控制(创建,等待,终止、分离)

目录 一、线程与轻量级进程的关系二、进程创建1.线程创建线程创建函数&#xff08;pthread&#xff09;查看和理解线程id主线程与其他线程之间的关系 三、线程等待&#xff08;回收&#xff09;四、线程退出线程退出情况线程退出方法 五、线程分离线程的优点线程的缺点 一、线程…

解决IDEA的easycode插件生成的mapper.xml文件字段之间逗号丢失

问题 easycode插件生成的mapper.xml文件字段之间逗号丢失&#xff0c;如图 解决办法 将easycode(在settings里面的othersettings)设置里面的Template的mapper.xml.vm和Global Config的mybatisSupport.vm的所有$velocityHasNext换成$foreach.hasNext Template的mapper.xml.vm(…

Android 实现中英文切换

在开发海外项目的时候&#xff0c;需要实现app内部的中英文切换功能&#xff0c;所有的英文都是内置的&#xff0c;整体思路为&#xff1a; 创建一个sp对象&#xff0c;存储当前系统的语言类型&#xff0c;然后在BaseActivity中对语言进行判断&#xff1b; //公共Activitypubl…

11月 | Apache DolphinScheduler月度进展总结

各位热爱 Apache DolphinScheduler 的小伙伴们&#xff0c;社区10月份月报更新啦&#xff01;这里将记录 DolphinScheduler 社区每月的重要更新&#xff0c;欢迎关注&#xff01; 月度Merge之星 感谢以下小伙伴11月份为 Apache DolphinScheduler 所做的精彩贡献&#xff08;排…

[软件开发幼稚指数评比]《软件方法》自测题解析010

第1章自测题 Part2 **9 [**单选题] 以下说法和其他三个最不类似的是: A)如果允许一次走两步&#xff0c;新手也能击败象棋大师 B)百米短跑比赛才10秒钟&#xff0c;不可能为每一秒做周密计划&#xff0c;凭感觉跑就是 C)即使是最好的足球队&#xff0c;也不能保证每…

【JavaWeb后端学习笔记】使用IDEA连接MySQL数据库

IDEA连接MySQL IDEA中集成了DataGrip&#xff0c;因此可以直接使用IDEA操作MySQL数据库。 1.创建一个新的空工程。点击右侧的数据库标志。 2.选择要连接的数据库。第一步&#xff1a;点击“”&#xff1b;第二步&#xff1a;点击 Data Source&#xff1b;第三步&#xff1a;选…

大模型分类2—按训练方式

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl根据训练方式,大模型可分为监督学习、无监督学习、自监督学习和强化学习大模型。 1. 监督学习大模型 1.1 定义与原理 监督学习大模型是一种机器学习范式,它依赖于标记数据集进行训练。这些数据…

鸿蒙特色实战2

服务卡片开发 创建服务卡片 创建一个新的工程后&#xff0c;可以通过如下方法进行创建服务卡片&#xff1a; 创建服务卡片包括如下两种方式&#xff1a; 选择模块&#xff08;如entry模块&#xff09;下的任意文件&#xff0c;单击菜单栏File > New > Service Widget创…