C++硬实时调度:原理、实践与最佳方案

在工业自动化、航空航天、医疗设备等领域,系统的实时性往往直接关系到生命安全和财产损失。C++作为高性能编程语言,为硬实时系统开发提供了强大支持。本文将深入探讨C++硬实时调度的核心技术,从操作系统原理到代码实现的全方位解析。

一、实时系统概述

1.1 实时系统定义与分类

实时系统是指系统的正确性不仅取决于计算结果的逻辑正确性,还取决于结果产生的时间。根据对时间的严格程度,实时系统可分为:

  • 硬实时系统(Hard Real-Time):任何截止时间的违反都可能导致灾难性后果,如飞控系统、心脏起搏器
  • 软实时系统(Soft Real-Time):偶尔违反截止时间不会导致系统失效,但会降低服务质量,如视频流、音频处理
  • 弱实时系统(Firm Real-Time):介于硬实时和软实时之间,违反截止时间的后果有限,如汽车导航系统

本文主要关注硬实时系统,其对时间的要求最为严格。

1.2 硬实时系统的关键特性

  1. 确定性(Determinism)

    • 系统响应时间可预测
    • 避免不可预测的延迟,如垃圾回收、页交换
  2. 优先级驱动调度

    • 高优先级任务必须能抢占低优先级任务
    • 优先级反转问题需严格控制
  3. 资源有限性

    • 内存、CPU时间等资源必须严格规划
    • 避免动态内存分配和其他不可预测操作
  4. 可靠性与容错性

    • 系统必须能够处理异常情况
    • 故障检测与恢复机制必不可少

1.3 实时系统与普通系统的区别

特性普通系统硬实时系统
响应时间要求平均性能优化最坏情况响应时间保证
调度算法吞吐量优先截止时间保证
内存管理动态分配、垃圾回收静态分配、确定性内存操作
异常处理尽力而为严格的故障处理机制
系统设计功能优先时间约束优先

二、操作系统实时调度基础

2.1 实时操作系统(RTOS)

实时操作系统是专为实时应用设计的操作系统,具有以下特性:

  • 短而确定的中断响应时间:通常在几微秒到几十微秒
  • 抢占式内核:高优先级任务可立即抢占低优先级任务
  • 确定性调度算法:如EDF(最早截止时间优先)、RM(速率单调)
  • 最小化的内核锁定:减少全局锁使用
  • 有限的系统调用延迟:所有系统调用的最坏情况时间可预测

常见的RTOS包括:

  • FreeRTOS:开源、轻量级,广泛应用于嵌入式系统
  • VxWorks:商业RTOS,用于航空航天等高可靠性领域
  • QNX:POSIX兼容,用于汽车电子、医疗设备
  • RTLinux:Linux内核的实时扩展版本

2.2 实时调度算法

实时调度算法主要分为两类:

2.2.1 静态优先级调度
  • 速率单调调度(Rate Monotonic, RM)

    • 任务优先级与其周期成反比(周期越短优先级越高)
    • 适用于周期任务
    • 可调度性条件:Σ(ci/pi) ≤ n(2^(1/n) - 1)
  • 截止时间单调调度(Deadline Monotonic, DM)

    • 任务优先级与其截止时间成反比(截止时间越短优先级越高)
    • 比RM更灵活,适用于截止时间与周期不同的任务
2.2.2 动态优先级调度
  • 最早截止时间优先(Earliest Deadline First, EDF)

    • 任务优先级根据截止时间动态分配,截止时间越早优先级越高
    • 适用于混合周期和非周期任务
    • 理论上可达到100%的CPU利用率
  • 最少松弛时间优先(Least Laxity First, LLF)

    • 松弛时间 = 截止时间 - 剩余执行时间 - 当前时间
    • 松弛时间最少的任务优先执行

2.3 优先级反转与解决方法

优先级反转是实时系统中的一个严重问题,指低优先级任务持有高优先级任务所需资源,导致高优先级任务被阻塞的现象。

2.3.1 经典优先级反转示例
  1. 任务H(高优先级)、任务M(中等优先级)、任务L(低优先级)
  2. 任务L获取锁资源R
  3. 任务H就绪,抢占任务L
  4. 任务H尝试获取锁R,被阻塞
  5. 任务M就绪,抢占任务L(此时任务L持有锁R)
  6. 任务M执行,延迟了任务L释放锁的时间
  7. 任务M执行完毕,任务L继续执行并释放锁
  8. 任务H才能获取锁继续执行
2.3.2 解决方案
  • 优先级继承协议(Priority Inheritance Protocol, PIP)

    • 当高优先级任务因等待锁而阻塞时,持有锁的低优先级任务临时提升到高优先级任务的级别
    • 上例中,任务L在持有锁时会被提升到任务H的优先级,避免被任务M抢占
  • 优先级天花板协议(Priority Ceiling Protocol, PCP)

    • 每个资源分配一个优先级天花板(使用该资源的所有任务中的最高优先级)
    • 任务在获取资源时,其优先级临时提升到资源的优先级天花板
    • 可防止优先级反转的级联效应

三、C++硬实时编程技术

3.1 C++实时特性支持

C++11及以后的版本提供了一些对实时编程有用的特性:

  • 原子操作(Atomic Operations)

    #include <atomic>std::atomic<int> shared_counter(0);void increment() {shared_counter.fetch_add(1, std::memory_order_relaxed);
    }
    
  • 线程与同步原语

    #include <thread>
    #include <mutex>std::mutex mtx;
    int shared_data = 0;void worker() {std::lock_guard<std::mutex> lock(mtx);// 临界区shared_data++;
    }
    
  • 时钟与定时器

    #include <chrono>
    #include <thread>void periodic_task() {using namespace std::chrono;auto next_time = steady_clock::now();while (true) {// 执行任务process_data();// 计算下一个周期next_time += milliseconds(10);std::this_thread::sleep_until(next_time);}
    }
    

3.2 避免动态内存分配

动态内存分配(如newmalloc)在硬实时系统中是危险的,因为:

  1. 分配时间不确定
  2. 可能导致内存碎片
  3. 可能失败,需要复杂的错误处理
3.2.1 替代方案
  • 静态内存分配
    // 固定大小数组替代动态分配
    constexpr size_t MAX_SIZE = 1000;
    int static_buffer[MAX_SIZE];// 静态对象池
    template<typename T, size_t N>
    class ObjectPool {
    private:union Node {T data;Node* next;};Node buffer[N];Node* free_list;public:ObjectPool() {free_list = &buffer[0];for (size_t i = 0; i < N - 1; ++i) {buffer[i].next = &buffer[i + 1];}buffer[N - 1].next = nullptr;}T* allocate() {if (!free_list) return nullptr;Node* node = free_list;free_list = node->next;return &node->data;}void deallocate(T* obj) {Node* node = reinterpret_cast<Node*>(obj);node->next = free_list;free_list = node;}
    };
    

3.3 减少中断延迟

在硬实时系统中,中断延迟必须最小化且可预测:

  1. 中断服务程序(ISR)应尽可能短

    // 不好的实践:ISR中执行复杂操作
    void isr_handler() {// 读取传感器数据// 处理数据// 更新显示
    }// 好的实践:ISR只做必要的工作,其余交给后台任务
    std::atomic<bool> data_ready(false);void isr_handler() {// 读取传感器数据read_sensor_data();data_ready = true;
    }void background_task() {while (true) {if (data_ready.exchange(false)) {// 处理数据process_data();// 更新显示update_display();}}
    }
    
  2. 禁用中断嵌套

    // 在关键代码段禁用中断
    void critical_section() {disable_interrupts();// 执行关键操作// ...enable_interrupts();
    }
    

3.4 实时线程调度

在C++中,可以使用POSIX线程API设置线程优先级和调度策略:

#include <pthread.h>
#include <iostream>void* thread_function(void* arg) {// 实时线程执行的代码while (true) {// 周期性任务process_data();pthread_yield();  // 让出CPU}return nullptr;
}int main() {pthread_t thread;pthread_attr_t attr;struct sched_param param;// 初始化线程属性pthread_attr_init(&attr);// 设置线程为FIFO调度策略pthread_attr_setschedpolicy(&attr, SCHED_FIFO);// 设置线程优先级(1-99,99最高)param.sched_priority = 80;pthread_attr_setschedparam(&attr, &param);// 设置线程为实时调度pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);// 创建线程pthread_create(&thread, &attr, thread_function, nullptr);// 清理pthread_attr_destroy(&attr);// 主线程继续执行其他任务// ...// 等待线程结束pthread_join(thread, nullptr);return 0;
}

3.5 内存锁定

为避免页交换带来的不可预测延迟,可锁定内存:

#include <sys/mman.h>
#include <iostream>int main() {// 锁定所有当前和未来的内存分配if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {perror("mlockall failed");return 1;}// 现在可以安全地分配内存,不会发生页交换char* buffer = new char[1024 * 1024];  // 1MB缓冲区// 使用缓冲区// ...// 释放内存delete[] buffer;// 解锁内存munlockall();return 0;
}

四、实时性能分析与调试

4.1 性能分析工具

  1. Cyclictest:测量系统循环延迟,评估实时性能

    cyclictest -p 80 -n -i 1000 -h 200
    
  2. RT-Tester:专门为实时系统设计的性能测试工具

    rttester -t 10 -p 70 -i 1000
    
  3. LTTng:Linux跟踪工具包,用于分析系统行为

    lttng create my-session
    lttng enable-event --kernel sched_switch
    lttng start
    # 运行测试程序
    lttng stop
    lttng view
    

4.2 调试技术

  1. 确定性日志记录

    // 环形缓冲区日志,避免动态内存分配
    template<typename T, size_t N>
    class CircularBuffer {
    private:T buffer[N];size_t head;size_t tail;size_t count;public:CircularBuffer() : head(0), tail(0), count(0) {}void push(const T& value) {if (count >= N) {// 缓冲区已满,覆盖最早的记录tail = (tail + 1) % N;} else {count++;}buffer[head] = value;head = (head + 1) % N;}// 其他方法...
    };
    
  2. 硬件调试工具

    • 逻辑分析仪:捕获和分析数字信号
    • 示波器:观察电信号波形
    • JTAG/SWD调试器:直接访问CPU内部状态

五、C++硬实时框架与库

5.1 OROCOS Real-Time Toolkit

OROCOS是一个开源的C++实时框架,提供:

  • 组件化架构
  • 实时通信机制
  • 任务调度
  • 与ROS集成
#include <rtt/TaskContext.hpp>
#include <rtt/Port.hpp>
#include <rtt/Component.hpp>class MyTask : public RTT::TaskContext {
public:MyTask(std::string name) : TaskContext(name) {// 初始化输出端口addPort("output", output_port);// 设置任务周期this->setPeriod(0.01);  // 10ms周期}bool configureHook() {// 配置任务return true;}bool startHook() {// 启动任务return true;}void updateHook() {// 周期性执行的代码double value = get_sensor_data();output_port.write(value);}void stopHook() {// 停止任务}void cleanupHook() {// 清理资源}private:RTT::OutputPort<double> output_port;double get_sensor_data() {// 从传感器读取数据return 0.0;}
};// 注册组件
ORO_CREATE_COMPONENT(MyTask)

5.2 Xenomai

Xenomai是一个Linux内核实时扩展,提供:

  • 硬实时性能
  • 多种实时调度算法
  • POSIX兼容API
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <native/task.h>
#include <native/timer.h>RT_TASK demo_task;void demo(void *arg) {RT_TASK_INFO curtaskinfo;RTIME now, previous;// 获取任务信息rt_task_inquire(NULL, &curtaskinfo);// 设置任务为周期模式rt_task_set_periodic(NULL, TM_NOW, 1000000000);  // 1秒周期previous = rt_timer_read();while (1) {rt_task_wait_period(NULL);now = rt_timer_read();printf("Task name: %s - Execution time: %ld ms\n",curtaskinfo.name, (long)(now - previous) / 1000000);previous = now;}
}void catch_signal(int sig) {// 处理信号
}int main(int argc, char* argv[]) {char  str[10];int   ret;// 锁定内存,防止页交换mlockall(MCL_CURRENT|MCL_FUTURE);// 注册信号处理signal(SIGTERM, catch_signal);signal(SIGINT, catch_signal);// 创建任务sprintf(str, "DEMO_TASK");ret = rt_task_create(&demo_task, str, 0, 99, T_JOINABLE);// 启动任务ret = rt_task_start(&demo_task, &demo, NULL);// 等待用户输入getchar();// 删除任务rt_task_delete(&demo_task);return 0;
}

5.3 FreeRTOS C++封装

FreeRTOS是一个轻量级RTOS,可通过C++封装提高开发效率:

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include <iostream>// C++任务基类
class RTOS_Task {
public:RTOS_Task(const char* name, uint16_t stack_size, UBaseType_t priority): task_handle(NULL) {xTaskCreate(taskFunction,name,stack_size,this,priority,&task_handle);}virtual ~RTOS_Task() {if (task_handle != NULL) {vTaskDelete(task_handle);}}virtual void run() = 0;private:static void taskFunction(void* pvParameters) {RTOS_Task* task = static_cast<RTOS_Task*>(pvParameters);task->run();}TaskHandle_t task_handle;
};// 具体任务实现
class MyTask : public RTOS_Task {
public:MyTask() : RTOS_Task("MyTask", 1024, 2) {}void run() override {while (true) {// 任务代码std::cout << "Task running..." << std::endl;vTaskDelay(pdMS_TO_TICKS(1000));  // 延时1秒}}
};// 主函数
int main() {// 创建任务MyTask task;// 启动调度器vTaskStartScheduler();// 如果程序执行到这里,说明发生了错误while (1);return 0;
}

六、硬实时系统设计案例

6.1 工业机器人控制系统

一个典型的工业机器人控制系统包含:

  1. 关节控制任务

    • 周期:1ms
    • 优先级:最高
    • 功能:读取编码器数据,计算控制输出
  2. 路径规划任务

    • 周期:10ms
    • 优先级:中等
    • 功能:根据目标位置计算机器人运动路径
  3. 传感器数据处理任务

    • 周期:5ms
    • 优先级:中等
    • 功能:处理激光雷达、视觉等传感器数据
  4. 通信任务

    • 周期:20ms
    • 优先级:较低
    • 功能:与上位机通信,接收指令和发送状态

以下是一个简化的关节控制任务实现:

#include <pthread.h>
#include <iostream>
#include <atomic>// 全局标志
std::atomic<bool> running(true);// 电机控制接口
class MotorController {
public:void set_position(double position) {// 实际硬件控制代码// ...}double get_position() {// 读取编码器位置// ...return 0.0;}
};// PID控制器
class PIDController {
private:double kp, ki, kd;double error_sum, last_error;public:PIDController(double p, double i, double d): kp(p), ki(i), kd(d), error_sum(0), last_error(0) {}double compute(double setpoint, double current_value, double dt) {double error = setpoint - current_value;error_sum += error * dt;double error_derivative = (error - last_error) / dt;last_error = error;return kp * error + ki * error_sum + kd * error_derivative;}
};// 关节控制任务
void* joint_control_task(void* arg) {MotorController motor;PIDController pid(10.0, 0.5, 2.0);// 设置线程为FIFO调度,优先级90pthread_setschedprio(pthread_self(), 90);// 任务周期1msconst int period_ns = 1000000;  // 1ms = 1,000,000ns// 计算第一个截止时间struct timespec next_time;clock_gettime(CLOCK_MONOTONIC, &next_time);while (running) {// 读取当前位置double current_position = motor.get_position();// 计算目标位置(简化示例)double target_position = 0.5 * sin(2 * M_PI * 0.1 * clock() / CLOCKS_PER_SEC);// 计算控制输出double control_output = pid.compute(target_position, current_position, 0.001);// 设置电机位置motor.set_position(control_output);// 等待下一个周期next_time.tv_nsec += period_ns;while (next_time.tv_nsec >= 1000000000) {next_time.tv_nsec -= 1000000000;next_time.tv_sec++;}clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next_time, NULL);}return nullptr;
}// 主函数
int main() {pthread_t thread;pthread_attr_t attr;// 初始化线程属性pthread_attr_init(&attr);// 设置线程为FIFO调度struct sched_param param;param.sched_priority = 90;pthread_attr_setschedparam(&attr, &param);pthread_attr_setschedpolicy(&attr, SCHED_FIFO);// 创建关节控制线程pthread_create(&thread, &attr, joint_control_task, nullptr);// 主线程可以执行其他任务// ...// 等待用户输入退出std::cout << "Press Enter to exit..." << std::endl;std::cin.get();// 停止任务running = false;// 等待线程结束pthread_join(thread, nullptr);return 0;
}

七、硬实时系统验证与测试

7.1 最坏情况执行时间(WCET)分析

WCET分析是硬实时系统验证的核心,常用方法包括:

  1. 静态分析:通过代码分析确定最坏情况执行时间

    • 工具:aiT、CompCert
  2. 测量分析:通过实际运行测量执行时间

    • 工具:OProfile、gprof
  3. 混合分析:结合静态和测量方法

示例:使用aiT进行WCET分析

# 编译程序并生成分析所需信息
gcc -O2 -finstrument-functions my_program.c -o my_program# 使用aiT进行分析
ait my_program -o wcet_report.txt

7.2 可调度性分析

验证系统中所有任务是否能满足其截止时间:

// 可调度性分析示例(EDF算法)
bool is_schedulable_edf(const std::vector<Task>& tasks) {double utilization = 0.0;for (const auto& task : tasks) {utilization += task.execution_time / task.period;}// EDF算法在理想情况下可调度利用率<=1的任务集return utilization <= 1.0;
}// 可调度性分析示例(RM算法)
bool is_schedulable_rm(const std::vector<Task>& tasks) {double utilization = 0.0;size_t n = tasks.size();for (const auto& task : tasks) {utilization += task.execution_time / task.period;}// RM算法的可调度性充分条件double bound = n * (std::pow(2.0, 1.0/n) - 1);return utilization <= bound;
}

7.3 压力测试与容错测试

  1. 压力测试

    • 在资源极限条件下运行系统
    • 验证系统在过载情况下的行为
  2. 容错测试

    • 注入故障(如硬件故障、通信中断)
    • 验证系统的恢复能力

示例:网络中断测试脚本

#!/bin/bash# 循环测试网络中断恢复能力
for i in {1..100}; doecho "Test iteration $i"# 断开网络ifconfig eth0 downecho "Network disconnected"sleep 2# 检查系统是否仍在运行# ...# 恢复网络ifconfig eth0 upecho "Network reconnected"sleep 10# 验证系统是否恢复正常# ...
done

八、硬实时系统设计最佳实践

  1. 最小化关键路径

    • 减少关键任务的执行时间
    • 避免关键任务中的阻塞操作
  2. 确定性内存管理

    • 避免动态内存分配
    • 使用静态分配和内存池
  3. 优先级分配策略

    • 遵循速率单调或截止时间单调原则
    • 避免优先级反转
  4. 硬件与软件协同设计

    • 选择适合实时需求的硬件平台
    • 优化硬件/软件接口
  5. 严格的编码规范

    • 避免递归和复杂算法
    • 限制函数调用深度
    • 使用确定性数据结构
  6. 防御性编程

    • 对所有外部输入进行验证
    • 实现健壮的错误处理机制
    • 使用断言检查内部状态
  7. 全面测试与验证

    • 执行最坏情况分析
    • 进行长时间稳定性测试
    • 模拟各种故障情况

九、总结与未来趋势

硬实时系统开发是一项极具挑战性的工作,需要从硬件到软件的全方位考虑。C++作为一种高性能语言,为硬实时系统提供了必要的工具和特性,但也要求开发者具备深入的系统知识和编程技能。

未来,随着物联网、自动驾驶、工业4.0等领域的发展,硬实时系统的需求将不断增长。以下趋势值得关注:

  1. 异构计算与实时性:GPU、FPGA等异构计算设备在实时系统中的应用
  2. 机器学习与实时决策:轻量级深度学习模型在实时控制系统中的应用
  3. 实时容器与微服务:在资源受限环境中部署实时微服务
  4. 形式化方法与验证工具:更强大的自动化验证技术

通过合理选择技术栈、遵循最佳实践、利用先进工具,开发者可以构建出既满足严格实时要求,又具有高可靠性和可维护性的C++硬实时系统。

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

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

相关文章

LeetCode 1156.单字符重复子串的最大长度

如果字符串中的所有字符都相同&#xff0c;那么这个字符串是单字符重复的字符串。 给你一个字符串 text&#xff0c;你只能交换其中两个字符一次或者什么都不做&#xff0c;然后得到一些单字符重复的子串。返回其中最长的子串的长度。 示例 1&#xff1a; 输入&#xff1a;text…

K近邻算法的分类与回归应用场景

K近邻算法的分类与回归应用场景 K近邻&#xff08;K-Nearest Neighbors, KNN&#xff09;算法是一种基础但强大的机器学习方法&#xff0c;它既可以用于分类问题&#xff0c;也能解决回归问题。 两者的核心思想都是基于"近朱者赤&#xff0c;近墨者黑"的原理&#xf…

算法精讲--正则表达式(二):分组、引用与高级匹配技术

算法精讲–正则表达式&#xff08;二&#xff09;&#xff1a;分组、引用与高级匹配技术 &#x1f680;正则表达式的真正力量在于组合使用各种语法元素&#xff0c;创造出强大而精确的匹配模式&#xff01; —— 作者&#xff1a;无限大 推荐阅读时间&#xff1a;25 分钟 适用人…

python+requests 接口自动化测试实战

首先介绍一下python的requests模块&#xff1a; requests的使用介绍&#xff1a;requests快速入门 Python结合requests库实现接口自动化测试环境说明&#xff1a; 1.WIN 7, 64位 2.Python3.4.3 &#xff08;pip-8.1.2&#xff09; 3.Requests —>pip install requests 4.U…

NAT 实验

NAT 实验 一.实验拓扑图实验目的 1.按照图示配置 IP 地址 2.私网 A 通过 R1 接入到互联网&#xff0c;私网 B 通过 R3 接入到互联网 3.私网 A 内部存在 Vlan10 和 Vlan20&#xff0c;通过 R1 上单臂路由访问外部网络 4.私网 A 通过 NAPT 使 Vlan10 和 Vlan20 都能够使用 R1 的公…

buuctf——web刷题第三页

第三页 目录 [FBCTF2019]RCEService [0CTF 2016]piapiapia [Zer0pts2020]Can you guess it? [WUSTCTF2020]颜值成绩查询 [SUCTF 2019]Pythonginx [MRCTF2020]套娃 [CSCCTF 2019 Qual]FlaskLight [watevrCTF-2019]Cookie Store [WUSTCTF2020]CV Maker [红明谷CTF 202…

前后端分离项目中的接口设计与调用流程——以高仙机器人集成为例

一、背景介绍在前后端分离项目开发中&#xff0c;前端页面需要频繁调用后端接口获取数据。在高仙机器人对接项目中&#xff0c;我们采用了若依&#xff08;RuoYi&#xff09;框架&#xff0c;前端通过统一的 API 封装与后端进行数据交互&#xff0c;而后端再对接高仙官方的 OPE…

【第五节】部署http接口到ubuntu server上的docker内

描述清楚需求&#xff0c;让deepseek帮我们写一个demo&#xff0c;文件结构如下 FLASK_API_001 ├── app.py └── Dockerfile └── requirements.txtapp.pyfrom flask import Flask, jsonify, requestapp Flask(__name__)# 根路由 app.route(/) def home():return "…

在 IntelliJ IDEA 中添加框架支持的解决方案(没有出现Add Framework Support)

在 IntelliJ IDEA 中添加框架支持的解决方案 问题背景 版本变化&#xff1a;在 IntelliJ IDEA 2023.2 及更高版本中&#xff0c;项目右键菜单中的 “Add Framework Support” 选项已被移除。 常见需求&#xff1a;为 Java 项目添加框架支持&#xff08;如 Maven、Spring 等&am…

北京-4年功能测试2年空窗-报培训班学测开-第五十天

咦&#xff0c;昨天路上写一半就到家了&#xff0c;后来想早点睡就忘了还要发了&#xff0c;现在赶紧补上昨天是最后一节课(我们将一整天的课称为一节&#xff09;&#xff0c;这就结课了昨天讲了简历编写&#xff0c;面试要准备的内容&#xff0c;还有redis和docker也没有什么…

华为鸿蒙HarmonyOpenEye项目:开眼App的鸿蒙实现之旅

华为鸿蒙HarmonyOpenEye项目&#xff1a;开眼App的鸿蒙实现之旅 引言 在当今移动应用开发的浪潮中&#xff0c;鸿蒙系统凭借其独特的分布式能力和高效的开发框架&#xff0c;吸引了众多开发者的目光。今天要给大家介绍的是一个基于华为鸿蒙系统开发的开眼App项目——HarmonyO…

代码随想录day36dp4

文章目录1049.最后一块石头的重量II494.目标和474.一和零1049.最后一块石头的重量II 题目链接 文章讲解 class Solution { public:int lastStoneWeightII(vector<int>& stones) {// 1. 确定 DP 数组及下标的含义&#xff1a;// dp[i][j] 表示考虑前 i 块石头&#…

Python 爬虫实战指南:按关键字搜索商品

在电商领域&#xff0c;按关键字搜索商品并获取其详情信息是一项常见的需求。无论是进行市场调研、竞品分析还是用户体验优化&#xff0c;能够快速准确地获取商品信息都至关重要。1688 作为国内领先的 B2B 电商平台&#xff0c;提供了丰富的商品资源。本文将详细介绍如何使用 P…

【源力觉醒 创作者计划】百度AI的开放新篇章:文心4.5本地化部署指南与未来生态战略展望

百度AI的开放新篇章&#xff1a;文心4.5本地化部署指南与未来生态战略展望 一起来玩转文心大模型吧&#x1f449;文心大模型免费下载地址&#xff1a;https://ai.gitcode.com/theme/1939325484087291906 &#x1f31f; 嗨&#xff0c;我是IRpickstars&#xff01; &#x1f30…

测试工作中的质量门禁管理

一、前言 测试阶段的质量门禁设计要考虑几个维度,首先是研发流程的阶段划分,每个阶段都要有明确的准入准出标准;其次要考虑不同测试类型的特点,比如功能测试和性能测试的验收标准肯定不同;最后还要平衡质量要求和项目进度。 在单元测试阶段,可以设置通过率和覆盖率的阈值…

线上分享:解码eVTOL安全基因,构建安全飞行生态

随着城市空中交通&#xff08;UAM&#xff09;快速发展&#xff0c;电动垂直起降飞行器&#xff08;eVTOL&#xff09;面临严格的安全与可靠性要求&#xff0c;需满足全球适航标准及全生命周期分析。安全与可靠的飞行系统成为行业关注的焦点。在此背景下&#xff0c;本期线上分…

C回调函数基础用法

&#x1f4cc; 定义&#xff1a;回调函数是通过函数指针传递给另一个函数的函数&#xff0c;这个被传进去的函数将在某个时刻被“回调”调用。换句话说&#xff1a;你定义一个函数 A把函数 A 的地址&#xff08;即函数指针&#xff09;作为参数传给函数 B函数 B 在合适的时机调…

手撕设计模式之消息推送系统——桥接模式

手撕设计模式之消息推送系统——桥接模式 1.业务需求 ​ 大家好&#xff0c;我是菠菜啊&#xff0c;好久不见&#xff0c;今天给大家带来的是——桥接模式。老规矩&#xff0c;在介绍这期内容前&#xff0c;我们先来看看这样的需求&#xff1a;我们现在要做一个消息推送系统&…

Java 大厂面试题 -- JVM 垃圾回收机制大揭秘:从原理到实战的全维度优化

最近佳作推荐&#xff1a; Java 大厂面试题 – JVM 面试题全解析&#xff1a;横扫大厂面试&#xff08;New&#xff09; Java 大厂面试题 – 从菜鸟到大神&#xff1a;JVM 实战技巧让你收获满满&#xff08;New&#xff09; Java 大厂面试题 – JVM 与云原生的完美融合&#xf…

图机器学习(9)——图正则化算法

图机器学习&#xff08;9&#xff09;——图正则化算法1. 图正则化方法2. 流形正则化与半监督嵌入3. 神经图学习4. Planetoid1. 图正则化方法 浅层嵌入方法已经证明&#xff0c;通过编码数据点间的拓扑关系可以构建更鲁棒的分类器来处理半监督任务。本质上&#xff0c;网络信息…