【Bluedroid】蓝牙协议栈enable流程深度解析

本文详细剖析 Bluedroid 蓝牙功能启用的核心流程,从enable()函数触发开始,深入解析蓝牙协议栈的异步启动机制、核心协议模块初始化、硬件控制器绑定及状态同步全流程。重点阐述接口就绪性检查、异步线程管理、配置文件回调机制等关键环节,揭示蓝牙栈从软件初始化到硬件交互的完整生命周期管理。

一、概述

1. 接口就绪性与异步启动

  • 接口检查enable()函数首先通过interface_ready()验证蓝牙硬件和软件接口是否就绪

  • 异步启动:通过stack_manager_get_interface()->start_up_stack_async()非阻塞启动蓝牙栈,避免主线程阻塞

2. 协议栈核心初始化流程

  • 状态校验event_start_up_stack首先检查stack_is_running避免重复启动

  • 基础环境初始化:通过ensure_stack_is_initialized确保协议栈基础环境仅初始化一次

  • 核心模块加载:按序初始化 BTM、L2CAP、GATT、SDP 等协议模块,构建协议栈基础架构

  • 配置文件回调通过startProfiles()触发上层业务逻辑,启动 A2DP、HID 等配置文件

3. 硬件交互与状态同步

  • 控制器绑定:初始化 GD_CONTROLLER_MODULE 与物理硬件交互,完成固件加载与射频校准

  • 异步等待机制:通过future_await阻塞等待硬件初始化完成,确保协议栈与硬件状态一致

  • 错误处理:启动失败时通过event_shut_down_stack完成资源清理

  • 状态通知:通过event_signal_stack_up通知 JNI 线程,触发系统状态变更广播

4. 分层架构设计

  • 协议层:BTM、L2CAP 等底层协议模块负责硬件抽象

  • 应用层:BTA 模块封装上层 API,提供设备管理等应用级功能

  • 接口层:BTIF 模块实现与 Android Framework 的接口适配

二、源码解析

enable

packages/modules/Bluetooth/system/btif/src/bluetooth.cc
static int enable() {if (!interface_ready()) return BT_STATUS_NOT_READY;stack_manager_get_interface()->start_up_stack_async(CreateInterfaceToProfiles(), &start_profiles, &stop_profiles);return BT_STATUS_SUCCESS;
}

启动蓝牙栈,并在栈启动完成后异步初始化蓝牙配置文件(如 HID、A2DP、GATT 等)。流程可概括为:

  • 接口就绪性检查:确保蓝牙硬件和软件接口已准备好(如驱动加载、硬件初始化完成)。

  • 异步启动蓝牙栈:通过非阻塞方式启动蓝牙协议栈,避免阻塞调用线程。

  • 配置文件回调注册:在栈启动成功 / 失败时,触发配置文件的启动或停止逻辑。

start_up_stack_async

packages/modules/Bluetooth/system/btif/src/stack_manager.cc
static void start_up_stack_async(bluetooth::core::CoreInterface* interface, // 蓝牙核心接口指针ProfileStartCallback startProfiles, // 栈启动成功后的回调函数ProfileStopCallback stopProfiles) { // 栈启动失败/停止后的回调函数management_thread.DoInThread(FROM_HERE, base::BindOnce(event_start_up_stack, interface, startProfiles,stopProfiles));}

通过异步线程管理和回调机制,实现了蓝牙栈启动与配置文件初始化的解耦,确保核心流程在独立线程中可靠执行。

event_start_up_stack

packages/modules/Bluetooth/system/btif/src/stack_manager.cc
// Unvetted includes/imports, etc which should be removed or vetted in the
// future
static future_t* hack_future;
// End unvetted section// If running, the stack is fully up and able to bluetooth.
static bool stack_is_running;// Synchronous function to start up the stack
static void event_start_up_stack(bluetooth::core::CoreInterface* interface,ProfileStartCallback startProfiles,ProfileStopCallback stopProfiles) {// 1. 启动前状态校验:避免重复启动if (stack_is_running) {log::info("stack already brought up");return;}// 2. 基础环境初始化:确保运行前提ensure_stack_is_initialized(interface);// 3.  异步等待标记创建:阻塞等待硬件就绪log::info("is bringing up the stack");future_t* local_hack_future = future_new(); // 阻塞当前线程,等待某些异步操作完成(如硬件固件加载、控制器初始化)hack_future = local_hack_future;// 4. 核心协议模块初始化:构建协议栈基础log::info("Gd shim module enabled");get_btm_client_interface().lifecycle.btm_init();       // BTM(蓝牙传输管理层)初始化module_start_up(get_local_module(BTIF_CONFIG_MODULE)); // BTIF配置模块启动(蓝牙接口层)l2c_init(); // L2CAP(逻辑链路控制与适配协议)初始化sdp_init(); // SDP(服务发现协议)初始化gatt_init(); // GATT(通用属性协议)初始化SMP_Init(get_btm_client_interface().security.BTM_GetSecurityMode()); // SMP(安全管理协议)初始化get_btm_client_interface().lifecycle.btm_ble_init();   // BTM BLE子模块初始化RFCOMM_Init(); // RFCOMM(串口仿真协议)初始化GAP_Init();  // GAP(通用访问配置文件)初始化// 5. 配置文件启动回调:触发上层业务逻辑startProfiles();// 6. 蓝牙应用层(BTA)初始化:封装上层 APIbta_sys_init();                                   // BTA系统模块初始化(事件队列、消息机制)module_init(get_local_module(BTE_LOGMSG_MODULE)); // 日志模块初始化(用于协议栈内部日志记录)btif_init_ok();                                   // BTIF层标记初始化完成(通知上层接口就绪)BTA_dm_init();                                   // BTA设备管理模块初始化(设备发现、配对管理)bta_dm_enable(btif_dm_sec_evt, btif_dm_acl_evt); // 启用设备管理(注册安全事件、ACL连接事件回调)// 7. 硬件与控制器绑定:连接物理硬件btm_acl_device_down();  // 关闭所有现有ACL连接(启动前清理)CHECK(module_start_up(get_local_module(GD_CONTROLLER_MODULE))); // 启动GD控制器模块(与硬件控制器交互)BTM_reset_complete(); // 通知BTM控制器重置完成(硬件初始化完成)BTA_dm_on_hw_on(); // 通知BTA设备管理模块硬件已开启// 8. 异步等待与错误处理:确保硬件就绪// 阻塞当前线程,等待local_hack_future被标记为完成// 若超时或失败,进入错误处理流程if (future_await(local_hack_future) != FUTURE_SUCCESS) {log::error("failed to start up the stack");stack_is_running = true;  // So stack shutdown actually happensevent_shut_down_stack(stopProfiles); // 启动失败,触发清理return;}// 9. 最终状态同步与完成module_start_up(get_local_module(RUST_MODULE));  // 启动Rust模块stack_is_running = true; // 标记栈已成功运行log::info("finished");do_in_jni_thread(FROM_HERE, base::BindOnce(event_signal_stack_up, nullptr)); // 通知JNI线程栈已启动
}

同步完成蓝牙栈的完整初始化,包括:

  • 协议模块初始化(如 L2CAP、SDP、GATT 等);

  • 配置文件启动(通过startProfiles回调);

  • 硬件与系统服务绑定(如 BTM、GD 控制器);

  • 错误处理与资源清理(如启动失败时的栈关闭);

  • 状态同步(通知 JNI 线程栈已启动)。

执行流程可概括为:

状态校验 → 基础环境初始化 → 异步等待标记创建 → 核心协议模块初始化 → 配置文件启动 → 应用层初始化 → 硬件绑定 → 异步等待硬件就绪 → 错误处理/状态同步

异步等待的必要性:

future_await用于等待硬件初始化完成(如控制器固件加载、射频校准),这些操作通常由硬件驱动异步执行。通过阻塞管理线程等待,确保协议栈在硬件就绪后再继续初始化,避免因硬件未就绪导致的功能异常。

①启动前状态校验:避免重复启动

stack_is_running:全局布尔变量,标记蓝牙栈是否已处于 “完全运行” 状态(所有模块初始化完成,可正常通信)。

防止多次调用启动函数导致的模块重复初始化、资源竞争(如多个 L2CAP 实例冲突)或硬件状态混乱。

②基础环境初始化:ensure_stack_is_initialized

packages/modules/Bluetooth/system/btif/src/stack_manager.cc
// If initialized, any of the bluetooth API functions can be called.
// (e.g. turning logging on and off, enabling/disabling the stack, etc)
static bool stack_is_initialized;static void ensure_stack_is_initialized(bluetooth::core::CoreInterface* interface) {if (!stack_is_initialized) {log::warn("found the stack was uninitialized. Initializing now.");// No future needed since we are calling it directlyinit_stack_internal(interface);}
}

蓝牙协议栈生命周期管理中的初始化守护函数,通过全局状态标记stack_is_initialized确保蓝牙栈的基础环境仅被初始化一次,避免重复初始化导致的资源竞争或状态混乱。为后续模块启动和功能调用提供可靠的前提条件。

检查stack_is_initialized是否为false(未初始化)。若已初始化(true),函数直接返回。如果没有初始化,调用init_stack_internal(interface)执行实际初始化逻辑。【Bluedroid】蓝牙启动之init_stack_internal 函数全流程源码解析-CSDN博客

③异步等待标记创建:阻塞等待硬件就绪

  • future_t:异步等待对象,用于阻塞当前线程,等待硬件初始化(如固件加载、射频校准)等异步操作完成。

  • hack_future:全局变量,用于其他线程(如硬件驱动线程)设置完成状态。(通过future_ready()设置)

④核心协议模块初始化:构建协议栈基础

模块功能说明(按初始化顺序):

  • BTM(Bluetooth Transport Manager):蓝牙传输管理层,负责 ACL 连接管理、链路控制、功耗模式切换,是协议栈的 “交通警察”。【Bluedriod】蓝牙启动之 btm_init 源码解析-CSDN博客

  • BTIF_CONFIG_MODULE(Bluetooth Interface Layer):蓝牙接口层配置模块,负责与 Android Framework 的接口适配(如 JNI 回调注册)【Bluedriod】蓝牙协议栈GD模块(GD_SHIM_MODULE)启动机制及源码解析_gd协议栈详细介绍-CSDN博客

  • L2CAP(Logical Link Control and Adaptation Protocol):协议栈的核心适配层,负责数据包分段、通道管理(如控制通道、中断通道),是上层协议(GATT、RFCOMM)的基础【Bluedroid】蓝牙启动之 l2c_init 源码解析-CSDN博客

  • SDPService Discovery Protocol:服务发现协议,用于设备间查询支持的服务(如查询耳机支持的 A2DP 服务)。【Bluedroid】蓝牙启动之sdp_init 源码解析-CSDN博客

  • GATT(Generic Attribute Protocol):通用属性协议,是 BLE(低功耗蓝牙)数据通信的核心,定义了服务(Service)、特征(Characteristic)的层级结构。【Bluedroid】蓝牙启动之gatt_init 流程源码解析_bluedroid gatt-CSDN博客

  • SMP(Security Manager Protocol):安全管理协议,负责配对、密钥生成、加密等安全操作,依赖 BTM 提供的安全模式。​​​​​​​【Bluedroid】蓝牙启动之 SMP_Init 源码解析_android p-256曲线-CSDN博客

  • BTM BLE:BTM 对 BLE 的扩展支持(如 LE 连接参数管理)。​​​​​​​【Bluedroid】蓝牙启动之btm_ble_init源码分析-CSDN博客

  • RFCOMM(Radio Frequency Communication):基于 L2CAP 的串口仿真协议,用于传统蓝牙(BR/EDR)的串行数据传输(如 HID 键盘)。​​​​​​​【Bluedroid】蓝牙启动之 RFCOMM_Init 流程源码解析-CSDN博客

  • GAP(Generic Access Profile):通用访问配置文件,定义设备发现、配对、连接等基础流程,是所有蓝牙设备的 “入口”。​​​​​​​【Bluedroid】蓝牙启动之 GAP_Init 流程源码解析-CSDN博客

⑤配置文件启动回调:startProfiles

调用上层传入的startProfiles回调函数,启动蓝牙配置文件(Profiles)的业务逻辑。

典型操作(根据具体 Profile 类型):

  • 音频类(A2DP):注册音频流传输服务;

  • 人机接口类(HID):初始化 HID 主机以支持键盘、鼠标连接;

  • 智能设备类(GATT):注册自定义 GATT 服务(如心率传感器)。

【Bluedroid】蓝牙启动之核心模块(startProfiles )初始化与功能源码解析-CSDN博客

⑥蓝牙应用层(BTA)初始化:封装上层 API

BTA(Bluetooth Application Layer):蓝牙应用层,负责将协议栈功能封装为上层可调用的 API(如 Android 的BluetoothManager),并管理设备发现、配对等应用级逻辑。

关键模块:

  • bta_sys_init:初始化 BTA 的事件队列和消息循环,是 BTA 与协议栈交互的基础;​​​​​​​【Bluedroid】蓝牙启动之 bta_sys_init 源码解析-CSDN博客

  • module_init(get_local_module(BTE_LOGMSG_MODULE)): 日志模块初始化(用于协议栈内部日志记录)​​​​​​​【Bluedroid】蓝牙启动之模块初始化机制(module_init)深度解析 -CSDN博客

  • btif_init_ok:BTIF层标记初始化完成(通知上层接口就绪)​​​​​​​【Bluedroid】蓝牙启动之 btif_init_ok 流程源码解析-CSDN博客

  • BTA_dm_init/bta_dm_enable:设备管理模块初始化,注册安全事件(如配对请求)和 ACL 连接事件(如设备连接 / 断开)的回调,上层通过这些回调感知设备状态变化。

【Bluedroid】蓝牙启动之 BTA_dm_init 流程源码解析-CSDN博客

【Bluedroid】蓝牙启动之 bta_dm_enable 流程梳理 & 源码解析-CSDN博客

⑦ 硬件与控制器绑定:连接物理硬件

GD_CONTROLLER_MODULE:蓝牙硬件控制器的抽象层( “GD” 即 “Generic Driver” 的缩写),负责与具体蓝牙芯片(如高通、博通)交互,完成以下操作:

  • 加载芯片固件(如bt_firmware.bin);

  • 配置控制器参数(如 MTU 大小、功耗模式);

  • 启动射频(RF)模块,完成校准。

btm_acl_device_down:清理历史连接,避免残留的 ACL 连接干扰新启动流程。【Bluedroid】蓝牙启动之 btm_acl_device_down 流程源码解析-CSDN博客

BTM_reset_complete: 通知BTM控制器重置完成(硬件初始化完成)。​​​​​​​【Bluedroid】蓝牙启动之BTM_reset_complete源码解析-CSDN博客

BTA_dm_on_hw_on:通知BTA设备管理模块硬件已开启。​​​​​​​【Bluedroid】蓝牙设备管理器初始化全流程深度解析(BTA_dm_on_hw_on)-CSDN博客

⑧异步等待与错误处理:确保硬件就绪

  • future_await:阻塞当前线程,等待local_hack_future被标记为完成(由硬件驱动线程或其他异步任务通过future_set触发)。若超时或失败(返回非FUTURE_SUCCESS),进入错误处理。

  • 错误处理逻辑

    • 强制标记stack_is_running = true:确保event_shut_down_stack能触发完整的关闭流程(如释放已初始化的模块);

    • 调用event_shut_down_stack(stopProfiles):清理已初始化的模块(如关闭 BTA 服务、释放协议层资源),避免状态不一致。

⑨最终状态同步与完成:通知上层栈已启动

  • RUST_MODULE:用 Rust 语言实现的模块(如安全敏感逻辑或高性能计算),需在核心模块启动后加载。

  • do_in_jni_thread:将event_signal_stack_up任务提交到 JNI 线程( Android 的主线程),通知上层(如BluetoothManagerService)蓝牙栈已启动完成,触发系统广播(如ACTION_BLUETOOTH_STATE_CHANGED)或 UI 更新(如蓝牙开关按钮变蓝)。

event_signal_stack_up

packages/modules/Bluetooth/system/btif/src/stack_manager.cc
static void event_signal_stack_up(void* /* context */) {// Notify BTIF connect queue that we've brought up the stack. It's// now time to dispatch all the pending profile connect requests.// 1. 调度积压的连接请求btif_queue_connect_next();// 2. 通知上层蓝牙状态已变为“开启”GetInterfaceToProfiles()->events->invoke_adapter_state_changed_cb(BT_STATE_ON);
}

在蓝牙栈完全启动后(即event_start_up_stack函数成功执行完毕),由 JNI 线程( Android 主线程)调用,确保上层应用能及时感知蓝牙状态变化。

主要负责触发两个核心操作:

  • 处理蓝牙栈启动前积压的连接请求(如在蓝牙开启过程中已提交的连接任务);

  • 通知所有注册的回调函数:蓝牙适配器状态已变为 “开启”(BT_STATE_ON)。

作为蓝牙栈启动完成的 “回调终点”,将底层启动细节(如协议模块初始化、硬件绑定)与上层业务逻辑(如连接请求处理、状态通知)分离,符合单一职责原则

①btif_queue_connect_next

蓝牙接口层(BTIF)的连接队列调度函数,负责处理启动前积压的连接请求。具体逻辑可能包括:

  • 从连接请求队列(如btif_connect_queue)中取出下一个待处理的连接任务(如连接蓝牙耳机、HID 设备);

  • 调用对应配置文件(Profile)的连接接口(如A2DP_ConnectHID_Connect)执行实际连接操作;

  • 若队列中还有任务,则递归调用自身继续处理,直到队列为空。

在蓝牙栈启动过程中,上层可能已提交了连接请求(如用户在蓝牙开关动画期间点击连接设备)。通过队列机制,确保这些请求在栈启动完成后按序执行,避免丢失或乱序。

  • 队列机制允许用户在蓝牙启动过程中提前发起操作(如点击连接设备),系统会在栈就绪后自动执行,减少用户等待时间。

  • 状态变更通知及时触发 UI 更新,使蓝牙开关动画与实际功能状态同步,提升交互流畅感。

②通知上层蓝牙状态变更:invoke_adapter_state_changed_cb

  • GetInterfaceToProfiles():获取蓝牙配置文件(Profiles)的接口管理器,通常是单例对象,负责管理所有配置文件的生命周期和事件分发。

  • events:配置文件事件处理器,包含一组回调函数指针,用于处理蓝牙状态变更、设备发现等事件。

  • invoke_adapter_state_changed_cb(BT_STATE_ON):遍历并调用所有注册的适配器状态变更回调函数,通知蓝牙适配器已进入 “开启” 状态(BT_STATE_ON)。

packages/modules/Bluetooth/system/btif/src/bluetooth.cc
void invoke_adapter_state_changed_cb(bt_state_t state) {do_in_jni_thread(FROM_HERE, base::BindOnce([](bt_state_t state) {HAL_CBACK(bt_hal_cbacks,adapter_state_changed_cb, state);},state));
}

蓝牙协议栈与 Android 系统框架之间的状态回调桥梁,主要负责将蓝牙适配器的状态变更(如开启、关闭)异步通知到 Java 层。确保 Java 层能及时更新蓝牙状态并通知应用。

  • do_in_jni_thread:将任务提交到 JNI 线程( Android 主线程)执行,确保 Java 层回调在正确的线程上下文执行。这是必要的,因为:

    • Android Java 框架的 UI 操作必须在主线程进行;

    • JNI 回调函数通常要求在创建它们的线程中调用,以避免线程安全问题。

  • base::BindOnce:创建一个一次性执行的回调(lambda 函数),并将当前状态(state)作为参数绑定到该回调中。BindOnce确保回调仅执行一次,执行后自动释放资源。

  • bt_hal_cbacks:蓝牙 HAL 层的回调函数结构体,由 Java 层通过 JNI 注册到 C++ 层。

  • adapter_state_changed_cb:具体的状态变更回调函数指针,指向 Java 层实现的状态处理逻辑。

  • 回调传递的状态值state参数通常是bt_state_t枚举类型,常见值包括:

/** Bluetooth Adapter State */
typedef enum { BT_STATE_OFF, BT_STATE_ON } bt_state_t;

典型接收者与行为

  • Android Framework 层BluetoothManagerService会监听此事件,更新系统蓝牙状态(如设置Settings.Global.BLUETOOTH_ON),并广播ACTION_BLUETOOTH_STATE_CHANGED通知所有应用。

  • 应用层:注册了BluetoothAdapter.ACTION_STATE_CHANGED广播的应用会收到通知,更新 UI(如蓝牙开关按钮状态、已配对设备列表)。

  • 蓝牙配置文件:各配置文件(如 A2DP、HID)可能在此时启动后台扫描或连接任务(如自动连接上次使用的耳机)。

当用户在设置中打开蓝牙开关时,完整的状态通知路径可能为:

1. 用户点击Android设置中的蓝牙开关 →
2. Java层调用JNI接口触发蓝牙开启 →
3. 协议栈启动流程(event_start_up_stack)执行 →
4. 栈启动完成后调用event_signal_stack_up →
5. event_signal_stack_up调用invoke_adapter_state_changed_cb(BT_STATE_ON) →
6. invoke_adapter_state_changed_cb将回调任务提交到JNI线程 →
7. JNI线程执行HAL层回调,触发Java层的adapter_state_changed_cb实现 →
8. Java层更新系统状态(如Settings.Global.BLUETOOTH_ON)并广播ACTION_BLUETOOTH_STATE_CHANGED

三、流程图

Android 蓝牙栈启动流程采用分层架构与异步机制设计,通过严格的状态管理、模块化初始化及错误处理机制,确保蓝牙功能从软件初始化到硬件交互的可靠执行。核心设计亮点包括:

  • 异步线程管理实现协议栈启动与主线程解耦

  • 模块化初始化保证各协议层按依赖顺序加载

  • 双向状态同步机制确保底层与上层状态一致性

  • 完善的错误处理流程避免资源泄漏


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

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

相关文章

各种开发语言主要语法对比

各类主流编程语言的语法有着显著差异,这些差异源于语言设计哲学(简洁性 vs 显式性)、应用领域(系统级、Web、数据科学)、运行方式(编译 vs 解释)以及支持的范式(面向对象、函数式、过…

小鹏汽车6月交付车辆34,611辆,同比增长224%

小鹏汽车-W(09868)发布公告,2025年6月,小鹏汽车共交付智能电动汽车34,611辆,同比增长224%,这标志着小鹏汽车已连续第八个月交付量超过了30,000辆。2025年第二季度,小鹏汽车共交付103,181 辆智能电动车,创下…

深入理解观察者模式:构建松耦合的交互系统

在软件开发中,我们经常遇到这样的场景:一个对象的状态变化需要通知其他多个对象,并且这些对象需要根据变化做出相应的反应。比如,用户界面中的数据变化需要实时反映到多个图表上,或者电商系统中的库存变化需要通知订单…

React强大且灵活hooks库——ahooks入门实践之常用场景hook

什么是 ahooks? ahooks 是一个 React Hooks 库,提供了大量实用的自定义 hooks,帮助开发者更高效地构建 React 应用。其中场景类 hooks 是 ahooks 的一个重要分类,专门针对特定业务场景提供解决方案。 安装 ahooks npm install …

Qt常用控件之QWidget(一)

Qt常用控件之QWidget(一)1.QWidget2.enabled属性2.geometry🌟🌟hello,各位读者大大们你们好呀🌟🌟 🚀🚀系列专栏:【Qt的学习】 📝📝本…

AIOT开发选型:行空板 K10 与 M10 适用场景与选型深度解析

前言 随着人工智能和物联网技术的飞速发展,越来越多的开发者、学生和爱好者投身于创意项目的构建。 在众多的开发板中,行空板 K10 和 M10 以其独特的优势脱颖而出。 本文旨在为读者提供一份详尽的行空板 K10 和 M10 对比分析,从适用场景、…

redis汇总笔记

语雀完整版: https://www.yuque.com/g/mingrun/embiys/calwqx/collaborator/join?tokensLcLnqz5Rv8hOKEB&sourcedoc_collaborator# 《Redis笔记》 Redis 一般问题 Redis内存模型(I/O多路模型)多路复用IO如何解释 为什么Redis要使用单线…

STM32用PWM驱动步进电机

硬件介绍:连线:注意这里stp连的是pwm脉冲,dir连的是方向到时候代码pwm波形就是从这里来的,具体接线根据你的代码来注意要点:步进电机和舵机驱动是不一样的,它是根据步长来移动的,所以要开一个中…

力扣25.7.10每日一题——重新安排会议得到最多空余时间 II

Description 今天这道题和昨天类似,只是允许顺序变化。 Solution 把会议区间视作桌子,空余时间视作空位,我们要把一个桌子移到别的空位中。 初步想法是枚举桌子,找一个长度大于等于桌子长度的空位移过去。看上去,找…

IP报文分片与重组原理及实现分析

IP报文分片与重组原理及实现分析 引用: ppp/net/packet/IPFragment.hppp/net/packet/IPFragment.cpp 1. IP分片原理 当IP数据包大小超过MTU(最大传输单元)时,路由器/主机将其分割为多个片段传输,每个片段包含&…

[python]在drf中使用drf_spectacular

安装drf_spectacular 文档 pypi链接:https://pypi.org/project/drf-spectacular/ 文档链接:https://drf-spectacular.readthedocs.io/en/latest/readme.html 安装步骤 在环境中添加 pip install drf-spectacular在setting的INSTALLED_APPS中添加 INSTALLED_APPS [# ALL…

【Datawhale AI 夏令营】 用AI做带货视频评论分析(二)

5.预训练模型跑分 回顾赛题 回顾赛题任务 挑战与难点: 标注数据少 ——> 半监督学习 or 数据增强 聚类分析噪点影响严重 回顾Baseline 问题: TF-IDF无法捕捉以下语义。聚类分析粗糙,未评估聚类质量。 提升方案: 分类任务…

SPSSPRO:数据分析市场SaaS挑战者的战略分析

目录 第一部分:执行摘要 第二部分:平台解构:产品、架构与用户体验 2.1 SaaS范式转移:架构与起源 2.2 功能能力:分析师的工具箱 2.3 “智能分析”的价值主张 第三部分:市场渗透与受众细分 3.1 目标用户…

低版本hive(1.2.1)UDF实现清除历史分区数据

目标&#xff1a;通过UDF实现对表历史数据清除 入参&#xff1a;表名、保留天数N 一、pom文件 <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.…

C++中顶层const与底层const

在C中&#xff0c;const关键字用于定义常量&#xff0c;但它在指针和引用上下文中会产生两种不同的常量性&#xff1a;顶层const&#xff08;top-level const&#xff09;和底层const&#xff08;low-level const&#xff09;。理解它们的区别是避免编译错误和提高代码质量的关…

“SRP模型+”多技术融合在生态环境脆弱性评价模型构建、时空格局演变分析与RSEI指数生态质量评价

集成云端、桌面端等环境&#xff0c;结合遥感云计算、GIS空间分析&#xff0c;R语言统计分析的优势&#xff0c;以分析生态环境脆弱性的时空演变为主线。通过本课程的学习&#xff0c;您将掌握&#xff1a;第一&#xff0c;收集各类指标数据&#xff0c;构建的“生态压力度-生态…

算法学习笔记:17.蒙特卡洛算法 ——从原理到实战,涵盖 LeetCode 与考研 408 例题

在计算机科学和数学领域&#xff0c;蒙特卡洛算法&#xff08;Monte Carlo Algorithm&#xff09;以其独特的随机抽样思想&#xff0c;成为解决复杂问题的有力工具。从圆周率的计算到金融风险评估&#xff0c;从物理模拟到人工智能&#xff0c;蒙特卡洛算法都发挥着不可替代的作…

Tortoise 设置

如何关闭 Windows 下 TortoiseGit 任务栏里窗口标题的分支显示 一、引言 TortoiseGit 是一个专为团队协作设计的 Git 图形化客户端&#xff0c;旨在解决版本控制中常见的问题&#xff0c;如冲突、回滚、历史查看等。本文档是 TortoiseGit 的使用手册前言部分&#xff0c;旨在向…

[论文阅读] 人工智能 + 软件工程 | AI助力软件可解释性:从用户评论到自动生成需求与解释

AI助力软件可解释性&#xff1a;从用户评论到自动生成需求与解释 Automatic Generation of Explainability Requirements and Software Explanations From User ReviewsarXiv:2507.07344 Automatic Generation of Explainability Requirements and Software Explanations From …

C语言---自定义类型(上)(结构体类型)

结构体结构体的定义与声明结构体其实和数组一样&#xff0c;都是一些值的集合&#xff0c;只不过数组是一系类相同类型的值&#xff0c;而结构体里边的成员可以是不同的数据类型。关于它的声明&#xff0c;所用到的关键字是struct。声明的语法如下&#xff1a;struct 结构体名{…