Porting Layer - 跨平台函数接口封装(RTOS/Windows)- C语言
目录
- 概述
- 具体实现
- 使用说明
概述
在嵌入式开发中,一般会在某个开发板上某个系统上实现某个功能,为了开发模块的移植性更好,因此需要对不同的操作系统有一层封装层。当换一个操作系统时,模块中的code不用修改,只需要根据不同的操作系统将封装层的函数实现即可,起到了模块和操作系统的解耦。同理,类似的还有模块与开发板的库函数(相当于工具模块),如输入输出,Socket,时间日期,内存管理等。如下实现了两个常用操作系统的封装层,以便跑在嵌入式中的功能运行在Window上,以方便调试优化。
具体实现
以下是一个用C语言实现的跨平台函数接口层,可以同时适用于RTOS(如FreeRTOS)和Windows环境。通过宏定义区分不同平台,提供统一的API接口。
/*** @file platform_api.h* @brief 跨平台接口层(RTOS/Windows)*/#ifndef PLATFORM_API_H
#define PLATFORM_API_H#include <stdint.h>
#include <stdbool.h>// 平台检测宏
#if defined(_WIN32) || defined(_WIN64)#define PLATFORM_WINDOWS 1#include <windows.h>
#elif defined(FREERTOS) || defined(RT_THREAD) || defined(UCOSII) || defined(UCOSIII)#define PLATFORM_RTOS 1#include "FreeRTOS.h"#include "task.h"#include "queue.h"#include "semphr.h"
#else#error "Unsupported platform!"
#endif#ifdef __cplusplus
extern "C" {
#endif/*---------------------------------* 线程相关接口*--------------------------------*/
typedef void (*thread_func_t)(void* arg);/*** @brief 创建线程* @param func 线程函数* @param arg 线程参数* @param stack_size 栈大小(字节)* @param priority 优先级(RTOS下具体含义取决于实现)* @return 线程句柄,NULL表示失败*/
void* platform_thread_create(thread_func_t func, void* arg, uint32_t stack_size, int priority);/*** @brief 销毁线程* @param thread 线程句柄*/
void platform_thread_destroy(void* thread);/*** @brief 当前线程休眠(毫秒)* @param ms 休眠时间(毫秒)*/
void platform_sleep(uint32_t ms);/*** @brief 获取当前线程ID* @return 线程ID*/
uint32_t platform_thread_id(void);/*---------------------------------* 互斥锁接口*--------------------------------*/
typedef void* platform_mutex_t;/*** @brief 创建互斥锁* @return 互斥锁句柄*/
platform_mutex_t platform_mutex_create(void);/*** @brief 销毁互斥锁* @param mutex 互斥锁句柄*/
void platform_mutex_destroy(platform_mutex_t mutex);/*** @brief 锁定互斥锁* @param mutex 互斥锁句柄*/
void platform_mutex_lock(platform_mutex_t mutex);/*** @brief 尝试锁定互斥锁* @param mutex 互斥锁句柄* @return true-成功锁定,false-锁定失败*/
bool platform_mutex_trylock(platform_mutex_t mutex);/*** @brief 解锁互斥锁* @param mutex 互斥锁句柄*/
void platform_mutex_unlock(platform_mutex_t mutex);/*---------------------------------* 信号量接口*--------------------------------*/
typedef void* platform_sem_t;/*** @brief 创建信号量* @param max_count 最大计数值* @param init_count 初始计数值* @return 信号量句柄*/
platform_sem_t platform_sem_create(uint32_t max_count, uint32_t init_count);/*** @brief 销毁信号量* @param sem 信号量句柄*/
void platform_sem_destroy(platform_sem_t sem);/*** @brief 等待信号量* @param sem 信号量句柄* @param timeout_ms 超时时间(毫秒),0xFFFFFFFF表示永久等待* @return true-成功获取,false-超时或失败*/
bool platform_sem_wait(platform_sem_t sem, uint32_t timeout_ms);/*** @brief 释放信号量* @param sem 信号量句柄*/
void platform_sem_post(platform_sem_t sem);/*---------------------------------* 消息队列接口*--------------------------------*/
typedef void* platform_queue_t;/*** @brief 创建消息队列* @param item_size 每个消息项的大小(字节)* @param queue_size 队列容量(消息项数量)* @return 消息队列句柄*/
platform_queue_t platform_queue_create(uint32_t item_size, uint32_t queue_size);/*** @brief 销毁消息队列* @param queue 消息队列句柄*/
void platform_queue_destroy(platform_queue_t queue);/*** @brief 发送消息到队列* @param queue 消息队列句柄* @param item 消息数据指针* @param timeout_ms 超时时间(毫秒)* @return true-成功,false-失败*/
bool platform_queue_send(platform_queue_t queue, const void* item, uint32_t timeout_ms);/*** @brief 从队列接收消息* @param queue 消息队列句柄* @param item 接收缓冲区指针* @param timeout_ms 超时时间(毫秒)* @return true-成功,false-失败*/
bool platform_queue_receive(platform_queue_t queue, void* item, uint32_t timeout_ms);/*---------------------------------* 时间相关接口*--------------------------------*/
/*** @brief 获取系统启动后的毫秒数* @return 毫秒数*/
uint32_t platform_get_tick_count(void);/*** @brief 获取当前时间(秒和微秒)* @param sec 存储秒数的指针* @param usec 存储微秒数的指针*/
void platform_get_time(uint32_t* sec, uint32_t* usec);#ifdef __cplusplus
}
#endif#endif /* PLATFORM_API_H */
下面是实现文件 platform_api.c:
/*** @file platform_api.c* @brief 跨平台接口层实现*/#include "platform_api.h"
#include <string.h>/*---------------------------------* 线程相关实现*--------------------------------*/
#if PLATFORM_WINDOWS// Windows实现
struct win_thread_wrapper {HANDLE handle;thread_func_t func;void* arg;
};static DWORD WINAPI win_thread_entry(LPVOID lpParam)
{struct win_thread_wrapper* wrapper = (struct win_thread_wrapper*)lpParam;wrapper->func(wrapper->arg);free(wrapper);return 0;
}void* platform_thread_create(thread_func_t func, void* arg, uint32_t stack_size, int priority)
{struct win_thread_wrapper* wrapper = malloc(sizeof(*wrapper));if (!wrapper) return NULL;wrapper->func = func;wrapper->arg = arg;wrapper->handle = CreateThread(NULL, stack_size, win_thread_entry, wrapper, 0, NULL);if (!wrapper->handle) {free(wrapper);return NULL;}// Windows线程优先级映射int win_priority;if (priority < -2) win_priority = THREAD_PRIORITY_LOWEST;else if (priority < 0) win_priority = THREAD_PRIORITY_BELOW_NORMAL;else if (priority == 0) win_priority = THREAD_PRIORITY_NORMAL;else if (priority <= 2) win_priority = THREAD_PRIORITY_ABOVE_NORMAL;else win_priority = THREAD_PRIORITY_HIGHEST;SetThreadPriority(wrapper->handle, win_priority);return wrapper;
}void platform_thread_destroy(void* thread)
{struct win_thread_wrapper* wrapper = (struct win_thread_wrapper*)thread;if (wrapper) {WaitForSingleObject(wrapper->handle, INFINITE);CloseHandle(wrapper->handle);free(wrapper);}
}void platform_sleep(uint32_t ms)
{Sleep(ms);
}uint32_t platform_thread_id(void)
{return (uint32_t)GetCurrentThreadId();
}#elif PLATFORM_RTOS// RTOS实现
void* platform_thread_create(thread_func_t func, void* arg, uint32_t stack_size, int priority)
{TaskHandle_t task = NULL;// FreeRTOS优先级是数字越大优先级越高,通常配置为0-(configMAX_PRIORITIES-1)if (priority < 0) priority = 0;if (priority > configMAX_PRIORITIES - 1) priority = configMAX_PRIORITIES - 1;xTaskCreate((TaskFunction_t)func, "platform_thread", stack_size/sizeof(StackType_t), arg, (UBaseType_t)priority, &task);return task;
}void platform_thread_destroy(void* thread)
{if (thread) {vTaskDelete(thread);}
}void platform_sleep(uint32_t ms)
{vTaskDelay(pdMS_TO_TICKS(ms));
}uint32_t platform_thread_id(void)
{return (uint32_t)xTaskGetCurrentTaskHandle();
}#endif/*---------------------------------* 互斥锁实现*--------------------------------*/
#if PLATFORM_WINDOWSplatform_mutex_t platform_mutex_create(void)
{CRITICAL_SECTION* cs = malloc(sizeof(CRITICAL_SECTION));if (cs) {InitializeCriticalSection(cs);}return cs;
}void platform_mutex_destroy(platform_mutex_t mutex)
{if (mutex) {DeleteCriticalSection((CRITICAL_SECTION*)mutex);free(mutex);}
}void platform_mutex_lock(platform_mutex_t mutex)
{EnterCriticalSection((CRITICAL_SECTION*)mutex);
}bool platform_mutex_trylock(platform_mutex_t mutex)
{return TryEnterCriticalSection((CRITICAL_SECTION*)mutex) != 0;
}void platform_mutex_unlock(platform_mutex_t mutex)
{LeaveCriticalSection((CRITICAL_SECTION*)mutex);
}#elif PLATFORM_RTOSplatform_mutex_t platform_mutex_create(void)
{return (platform_mutex_t)xSemaphoreCreateMutex();
}void platform_mutex_destroy(platform_mutex_t mutex)
{vSemaphoreDelete((SemaphoreHandle_t)mutex);
}void platform_mutex_lock(platform_mutex_t mutex)
{xSemaphoreTake((SemaphoreHandle_t)mutex, portMAX_DELAY);
}bool platform_mutex_trylock(platform_mutex_t mutex)
{return xSemaphoreTake((SemaphoreHandle_t)mutex, 0) == pdTRUE;
}void platform_mutex_unlock(platform_mutex_t mutex)
{xSemaphoreGive((SemaphoreHandle_t)mutex);
}#endif/*---------------------------------* 信号量实现*--------------------------------*/
#if PLATFORM_WINDOWSplatform_sem_t platform_sem_create(uint32_t max_count, uint32_t init_count)
{HANDLE sem = CreateSemaphore(NULL, init_count, max_count, NULL);return (platform_sem_t)sem;
}void platform_sem_destroy(platform_sem_t sem)
{CloseHandle((HANDLE)sem);
}bool platform_sem_wait(platform_sem_t sem, uint32_t timeout_ms)
{DWORD timeout = (timeout_ms == 0xFFFFFFFF) ? INFINITE : timeout_ms;return WaitForSingleObject((HANDLE)sem, timeout) == WAIT_OBJECT_0;
}void platform_sem_post(platform_sem_t sem)
{ReleaseSemaphore((HANDLE)sem, 1, NULL);
}#elif PLATFORM_RTOSplatform_sem_t platform_sem_create(uint32_t max_count, uint32_t init_count)
{return (platform_sem_t)xSemaphoreCreateCounting(max_count, init_count);
}void platform_sem_destroy(platform_sem_t sem)
{vSemaphoreDelete((SemaphoreHandle_t)sem);
}bool platform_sem_wait(platform_sem_t sem, uint32_t timeout_ms)
{TickType_t timeout = (timeout_ms == 0xFFFFFFFF) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms);return xSemaphoreTake((SemaphoreHandle_t)sem, timeout) == pdTRUE;
}void platform_sem_post(platform_sem_t sem)
{xSemaphoreGive((SemaphoreHandle_t)sem);
}#endif/*---------------------------------* 消息队列实现*--------------------------------*/
#if PLATFORM_WINDOWSstruct win_queue {uint32_t item_size;uint32_t queue_size;uint8_t* buffer;uint32_t head;uint32_t tail;uint32_t count;HANDLE sem_empty;HANDLE sem_full;CRITICAL_SECTION lock;
};platform_queue_t platform_queue_create(uint32_t item_size, uint32_t queue_size)
{struct win_queue* queue = malloc(sizeof(struct win_queue));if (!queue) return NULL;queue->item_size = item_size;queue->queue_size = queue_size;queue->buffer = malloc(item_size * queue_size);if (!queue->buffer) {free(queue);return NULL;}queue->head = 0;queue->tail = 0;queue->count = 0;queue->sem_empty = CreateSemaphore(NULL, queue_size, queue_size, NULL);queue->sem_full = CreateSemaphore(NULL, 0, queue_size, NULL);InitializeCriticalSection(&queue->lock);return (platform_queue_t)queue;
}void platform_queue_destroy(platform_queue_t queue)
{struct win_queue* q = (struct win_queue*)queue;if (q) {DeleteCriticalSection(&q->lock);CloseHandle(q->sem_empty);CloseHandle(q->sem_full);free(q->buffer);free(q);}
}bool platform_queue_send(platform_queue_t queue, const void* item, uint32_t timeout_ms)
{struct win_queue* q = (struct win_queue*)queue;DWORD timeout = (timeout_ms == 0xFFFFFFFF) ? INFINITE : timeout_ms;if (WaitForSingleObject(q->sem_empty, timeout) != WAIT_OBJECT_0) {return false;}EnterCriticalSection(&q->lock);memcpy(q->buffer + q->tail * q->item_size, item, q->item_size);q->tail = (q->tail + 1) % q->queue_size;q->count++;LeaveCriticalSection(&q->lock);ReleaseSemaphore(q->sem_full, 1, NULL);return true;
}bool platform_queue_receive(platform_queue_t queue, void* item, uint32_t timeout_ms)
{struct win_queue* q = (struct win_queue*)queue;DWORD timeout = (timeout_ms == 0xFFFFFFFF) ? INFINITE : timeout_ms;if (WaitForSingleObject(q->sem_full, timeout) != WAIT_OBJECT_0) {return false;}EnterCriticalSection(&q->lock);memcpy(item, q->buffer + q->head * q->item_size, q->item_size);q->head = (q->head + 1) % q->queue_size;q->count--;LeaveCriticalSection(&q->lock);ReleaseSemaphore(q->sem_empty, 1, NULL);return true;
}#elif PLATFORM_RTOSplatform_queue_t platform_queue_create(uint32_t item_size, uint32_t queue_size)
{return (platform_queue_t)xQueueCreate(queue_size, item_size);
}void platform_queue_destroy(platform_queue_t queue)
{vQueueDelete((QueueHandle_t)queue);
}bool platform_queue_send(platform_queue_t queue, const void* item, uint32_t timeout_ms)
{TickType_t timeout = (timeout_ms == 0xFFFFFFFF) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms);return xQueueSend((QueueHandle_t)queue, item, timeout) == pdTRUE;
}bool platform_queue_receive(platform_queue_t queue, void* item, uint32_t timeout_ms)
{TickType_t timeout = (timeout_ms == 0xFFFFFFFF) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms);return xQueueReceive((QueueHandle_t)queue, item, timeout) == pdTRUE;
}#endif/*---------------------------------* 时间相关实现*--------------------------------*/
#if PLATFORM_WINDOWSuint32_t platform_get_tick_count(void)
{return GetTickCount();
}void platform_get_time(uint32_t* sec, uint32_t* usec)
{FILETIME ft;ULARGE_INTEGER li;GetSystemTimeAsFileTime(&ft);li.LowPart = ft.dwLowDateTime;li.HighPart = ft.dwHighDateTime;// 从1601年1月1日到1970年1月1日的100纳秒间隔数li.QuadPart -= 116444736000000000ULL;if (sec) *sec = (uint32_t)(li.QuadPart / 10000000ULL);if (usec) *usec = (uint32_t)((li.QuadPart % 10000000ULL) / 10ULL);
}#elif PLATFORM_RTOSuint32_t platform_get_tick_count(void)
{return xTaskGetTickCount() * portTICK_PERIOD_MS;
}void platform_get_time(uint32_t* sec, uint32_t* usec)
{// RTOS通常没有标准的时间获取函数,这里简单实现uint32_t ticks = xTaskGetTickCount();uint32_t ms = ticks * portTICK_PERIOD_MS;if (sec) *sec = ms / 1000;if (usec) *usec = (ms % 1000) * 1000;
}#endif
使用说明
1.平台选择:
在Windows环境下编译时,会自动使用Windows API实现,在RTOS环境下编译时,会自动使用RTOS API实现,可以通过定义FREERTOS或其他RTOS宏来启用RTOS模式
2.基本功能:
- 线程创建和管理
- 互斥锁
- 信号量
- 消息队列
- 时间相关功能
3.使用示例:
#include "platform_api.h"
#include <stdio.h>void thread_function(void* arg)
{int id = *(int*)arg;for (int i = 0; i < 5; i++) {printf("Thread %d: count %d\n", id, i);platform_sleep(1000);}
}int main()
{// 创建线程int id1 = 1, id2 = 2;void* thread1 = platform_thread_create(thread_function, &id1, 4096, 1);void* thread2 = platform_thread_create(thread_function, &id2, 4096, 1);// 等待线程结束platform_thread_destroy(thread1);platform_thread_destroy(thread2);return 0;
}
相关文章:
Porting Layer - 跨平台函数接口封装(RTOS/Windows)- C语言
目录 概述具体实现使用说明 概述 在嵌入式开发中,一般会在某个开发板上某个系统上实现某个功能,为了开发模块的移植性更好,因此需要对不同的操作系统有一层封装层。当换一个操作系统时,模块中的code不用修改,只需要根…...
Kafka负载均衡挑战解决
本文为 How We Solve Load Balancing Challenges in Apache Kafka 阅读笔记 kafka通过利用分区来在多个队列中分配消息来实现并行性。然而每条消息都有不同的处理负载,也具有不同的消费速率,这样就有可能负载不均衡,从而使得瓶颈、延迟问题和…...
Docker Compose 常用命令 运行 docker-compose.yaml
Docker Compose 中有两个重要的概念 服务 (service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。 项目 (project):由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。 为了更方便…...
Kafka的索引设计有什么亮点
想获取更多高质量的Java技术文章?欢迎访问Java技术小馆官网,持续更新优质内容,助力技术成长 Java技术小馆官网https://www.yuque.com/jtostring Kafka的索引设计有什么亮点? Kafka 之所以能在海量数据的传输和处理过程中保持高…...
基于大模型的病态窦房结综合征预测及治疗方案研究报告
目录 一、引言 1.1 研究背景与目的 1.2 研究意义 二、病态窦房结综合征概述 2.1 定义与病因 2.2 临床表现与分型 2.3 诊断方法 三、大模型在病态窦房结综合征预测中的应用 3.1 大模型介绍 3.2 数据收集与预处理 3.3 模型训练与优化 四、术前预测与准备 4.1 风险预…...
音视频入门基础:RTCP专题(5)——《RFC 3550》的附录A
一、引言 本文对应《RFC 3550》的附录A(Appendix A. Algorithms)。 二、Appendix A. Algorithms 根据《RFC 3550》第62页,《RFC 3550》提供了有关RTP发送方和接收方算法的C代码示例。在特定的运行环境下,可能还有其他更快或更有…...
qemu仿真调试esp32,以及安装版和vscode版配置区别
不得不说,乐鑫在官网的qemu介绍真的藏得很深 首先在首页的sdk的esp-idf页面里找找 然后页面拉倒最下面 入门指南 我这里选择esp32-s3 再点击api指南-》工具 才会看到qemu的介绍 QEMU 模拟器 - ESP32-C3 - — ESP-IDF 编程指南 latest 文档https://docs.espressi…...
协方差相关问题
为什么无偏估计用 ( n − 1 ) (n-1) (n−1) 而不是 n n n,区别是什么? 在统计学中,无偏估计是指估计量的期望值等于总体参数的真实值。当我们用样本数据估计总体方差或协方差时,分母使用 ( n − 1 ) (n-1) (n−1) 而不是 n n…...
Android OpenCV 人脸识别 识别人脸框 识别人脸控件自定义
先看效果 1.下载OpenCV 官网地址:opcv官网 找到Android 4.10.0版本下载 下载完毕 解压zip如图: 2.将OpenCV-android_sdk导入项目 我这里用的最新版的Android studio 如果是java开发 需要添加kotlin的支持。我用的studio比较新可以参考下,如果…...
深入解析Linux软硬链接:原理、区别与应用实践
Linux系列 文章目录 Linux系列前言一、软硬链接的概念引入1.1 硬链接1.2 软链接 二、软硬链接的使用场景2.1 软链接2.2 硬链接 三、总结 前言 上篇文章我们详细的介绍了文件系统的概念及底层实现原理,本篇我们就在此基础上探讨Linux系统中文件的软链接࿰…...
TDengine 与 taosAdapter 的结合(二)
五、开发实战步骤 (一)环境搭建 在开始 TDengine 与 taosAdapter 结合的 RESTful 接口开发之前,需要先完成相关环境的搭建,包括 TDengine 和 taosAdapter 的安装与配置,以及相关依赖的安装。 TDengine 安装…...
OBS 中如何设置固定码率(CBR)与可变码率(VBR)?
在使用 OBS 进行录制或推流时,设置“码率控制模式”(Rate Control)是非常重要的一步。常见的控制模式包括: CBR(固定码率):保持恒定的输出码率,适合直播场景。 VBR(可变码率):在允许的范围内动态调整码率,适合本地录制、追求画质。 一、CBR vs. VBR 的差异 项目CBR…...
优艾智合人形机器人“巡霄”,开启具身多模态新时代
近日,优艾智合-西安交大具身智能机器人研究院公布人形机器人矩阵,其中轮式人形机器人“巡霄”首次亮相。 “巡霄”集成移动导航、操作控制与智能交互技术,具备跨场景泛化能,适用于家庭日常服务、电力设备巡检、半导体精密操作及仓…...
蓝桥杯小白打卡第七天(第十四届真题)
小蓝的金属冶炼转换率问题 小蓝有一个神奇的炉子用于将普通金属 (O) 冶炼成为一种特殊金属 (X) 。 这个炉子有一个称作转换率的属性 (V) ,(V) 是一个正整数,这意味着消耗 (V) 个普通金属 (O) 恰好可以冶炼出一个特殊金属 (X) ,当普通金属 (…...
excel经验
Q:我现在有一个excel,有一列数据,大概两千多行。如何在这一列中 筛选出具有关键字的内容,并输出到另外一列中。 A: 假设数据在A列(A1开始),关键字为“ABC”在相邻空白列(如B1)输入公…...
【Pandas】pandas DataFrame astype
Pandas2.2 DataFrame Conversion 方法描述DataFrame.astype(dtype[, copy, errors])用于将 DataFrame 中的数据转换为指定的数据类型 pandas.DataFrame.astype pandas.DataFrame.astype 是一个方法,用于将 DataFrame 中的数据转换为指定的数据类型。这个方法非常…...
【Netty4核心原理④】【简单实现 Tomcat 和 RPC框架功能】
文章目录 一、前言二、 基于 Netty 实现 Tomcat1. 基于传统 IO 重构 Tomcat1.1 创建 MyRequest 和 MyReponse 对象1.2 构建一个基础的 Servlet1.3 创建用户业务代码1.4 完成web.properties 配置1.5 创建 Tomcat 启动类 2. 基于 Netty 重构 Tomcat2.1 创建 NettyRequest和 Netty…...
4.6学习总结
包装类 包装类:基本数据类型对应的引用数据类型 JDK5以后新增了自动装箱,自动拆箱 以后获取包装类方法,不需要new,直接调用方法,直接赋值即可 //1.把整数转成二进制,十六进制 String str1 Integer.toBin…...
MySQL学习笔记五
第七章数据过滤 7.1组合WHERE子句 7.1.1AND操作符 输入: SELECT first_name, last_name, salary FROM employees WHERE salary < 4800 AND department_id 60; 输出: 说明:MySQL允许使用多个WHERE子句,可以以AND子句或OR…...
成为社交场的导演而非演员
一、情绪的本质:社交信号而非自我牢笼 进化功能:情绪是人类进化出的原始社交工具。愤怒触发群体保护机制,悲伤唤起同情支持,喜悦巩固联盟关系。它们如同可见光谱,快速传递生存需求信号。双刃剑效应:情绪的…...
怎么使用vue3实现一个优雅的不定高虚拟列表
前言 很多同学将虚拟列表当做亮点写在简历上面,但是却不知道如何手写,那么这个就不是加分项而是减分项了。实际项目中更多的是不定高虚拟列表,这篇文章来教你不定高如何实现。 什么是不定高虚拟列表 不定高的意思很简单,就是不…...
LemonSqueezy: 1靶场渗透
LemonSqueezy: 1 来自 <LemonSqueezy: 1 ~ VulnHub> 1,将两台虚拟机网络连接都改为NAT模式 2,攻击机上做namp局域网扫描发现靶机 nmap -sn 192.168.23.0/24 那么攻击机IP为192.168.23.182,靶场IP192.168.23.225 3,对靶机进…...
2025 年山东保安员职业资格考试要点梳理
山东作为人口大省,保安市场规模庞大。2025 年考试报考条件常规。报名通过山东省各市公安机关指定的培训机构或政务服务窗口,提交资料与其他地区类似。 理论考试注重对山东地域文化特色相关安保知识的考查,如在孔庙等文化圣地安保中&#x…...
ARM处理器内核全解析:从Cortex到Neoverse的架构与区别
ARM处理器内核全解析:从Cortex到Neoverse的架构与区别 ARM作为全球领先的处理器架构设计公司,其内核产品线覆盖了从高性能计算到低功耗嵌入式应用的广泛领域。本文将全面解析ARM处理器的内核分类、架构特点、性能差异以及应用场景,帮助读者深…...
网络缓冲区
网络缓冲区分为内核缓冲区和用户态网络缓冲区 我们重点要实现用户态网络缓冲区 1.设计用户态网络缓冲区的原因 ①.生产者和消费者的速度不匹配问题, 需要缓存数据。 ②.粘包处理问题, 不能确保一次系统调用读取或写入完整数据包。 2.代码实现(cha…...
数据仓库的核心架构与关键技术(数据仓库系列二)
目录 一、引言 二、数据仓库的核心架构 三、数据仓库的关键技术 1 数据集成与治理 2 查询优化与性能提升 3 数据共享服务 BI:以Tableau为例 SQL2API:以麦聪QuickAPI为例 4 实时数据处理 四、技术的协同作用 五、总结与展望 六、预告 一、引言…...
基于PyQt5与OpenCV的图像处理系统设计与实现
1. 系统概述 本系统是一个集成了多种经典图像处理算法的图形用户界面(GUI)应用程序,采用Python语言开发,基于PyQt5框架构建用户界面,利用OpenCV库实现核心图像处理功能。 系统支持11种图像处理操作,每种操作都提供参数实时调节功能,并具备原始图像与处理后图像的双视图对…...
如何根据设计稿进行移动端适配:全面详解
如何根据设计稿进行移动端适配:全面详解 文章目录 如何根据设计稿进行移动端适配:全面详解1. **理解设计稿**1.1 设计稿的尺寸1.2 设计稿的单位 2. **移动端适配的核心技术**2.1 使用 viewport 元标签2.1.1 代码示例2.1.2 参数说明 2.2 使用相对单位2.2.…...
什么是大型语言模型(LLM)?哪个大模型更好用?
什么是 LLM? ChatGPT 是一种大型语言模型 (LLM),您可能对此并不陌生。它以非凡的能力而闻名,已证明能够出色地完成各种任务,例如通过考试、生成产品内容、解决问题,甚至在最少的输入提示下编写程序。 他们的实力现已…...
集合学习内容总结
集合简介 1、Scala 的集合有三大类:序列 Seq、集Set、映射 Map,所有的集合都扩展自 Iterable 特质。 2、对于几乎所有的集合类,Scala 都同时提供了可变和不可变的版本,分别位于以下两个包 不可变集合:scala.collect…...
使用typedef和不使用的区别
使用 typedef 定义的函数指针类型 typedef sensor_drv_params_t* (*load_sensor_drv_func)(); 不使用 typedef 的函数指针声明 sensor_drv_params_t* (*load_sensor_drv_func)(); 这两者看似相似,但在语义和用途上有显著区别。下面将详细解释这两种声明的区别、各…...
基于线性回归模型的汽车燃油效率预测
基于线性回归模型的汽车燃油效率预测 1.作者介绍2.线性回归介绍2.1 线性回归简介2.2 线性回归应用场景 3.基于线性回归模型的汽车燃油效率预测实验3.1 Auto MPG Data Set数据集3.2代码调试3.3完整代码3.4结果展示 4.问题分析 基于线性回归模型的汽车燃油效率预测 1.作者介绍 郝…...
Playwright之自定义浏览器目录访问出错:BrowserType.launch: Executable doesn‘t exist
Playwright之自定义浏览器目录访问出错:BrowserType.launch: Executable doesn’t exist 问题描述: 在使用playwright进行浏览器自动化的时候,配置了自定义的浏览器目录,当按照自定义的浏览器目录启动浏览器进行操作时,…...
如何拿到iframe中嵌入的游戏数据
在 iframe 中嵌入的游戏数据是否能被获取,取决于以下几个关键因素: 1. 同源策略 浏览器的同源策略是核心限制。如果父页面和 iframe 中的内容同源(即协议、域名和端口号完全相同),那么可以直接通过 JavaScript 访问 …...
优选算法第七讲:分治
优选算法第七讲:分治 1.分治_快排1.1颜色分类1.2排序数组1.3数组中第k个最大元素1.4库存管理II 2.分治_归并2.1排序数组2.2交易逆序对的总数2.3计算右侧小于当前元素的个数2.4翻转对 1.分治_快排 1.1颜色分类 1.2排序数组 1.3数组中第k个最大元素 1.4库存管理II 2.…...
OpenBMC:BmcWeb 处理http请求4 处理路由对象
OpenBMC:BmcWeb 处理http请求2 查找路由对象-CSDN博客 Router::handle通过findRoute获取了FindRouteResponse对象foundRoute void handle(const std::shared_ptr<Request>& req,const std::shared_ptr<bmcweb::AsyncResp>& asyncResp){FindRouteResponse …...
直流电能表计量解决方案适用于光伏储能充电桩基站等场景
多场景解决方案,准确测量 01 市场规模与增长动力 全球直流表市场预测: 2025年市场规模14亿美元,CAGR超15%。 驱动因素:充电桩、光伏/储能、基站、直流配电 市场增长引擎分析: 充电桩随新能源车迅猛增长ÿ…...
x-cmd install | Slumber - 告别繁琐,拥抱高效的终端 HTTP 客户端
目录 核心优势,一览无遗安装应用场景,无限可能示例告别 GUI,拥抱终端 还在为调试 API 接口,发送 HTTP 请求而苦恼吗?还在各种 GUI 工具之间切换,只为了发送一个简单的请求吗?现在,有…...
git修改已经push的commit的message
1.修改信息 2.修改message 3.强推...
STM32 基础2
STM32中断响应过程 1、中断源发出中断请求。 2、判断处理器是否允许中断,以及该中断源是否被屏蔽。 3、中断优先级排队。 4、处理器暂停当前程序,保护断点地址和处理器的当前状态,根据中断类型号,查找中断向量表,转到…...
【STL 之速通pair vector list stack queue set map 】
考list 的比较少 --双端的啦 pair 想下,程序是什么样的. 我是我们要带着自己的思考去学习DevangLic.. #include <iostream> #include <utility> #include <string>using namespace std;int main() {// 第一部分:创建并输出两个 pair …...
深度学习篇---LSTM+Attention模型
文章目录 前言1. LSTM深入原理剖析1.1 LSTM 架构的进化理解遗忘门简介数学表达式实际作用 输入门简介数学表达式后选候选值实际作用 输出门简介数学表达式最终输出实际作用 1.2 Attention 机制的动态特性内容感知位置无关可解释性数学本质 1.3 LSTM与Attention的协同效应组合优…...
React 多个 HOC 嵌套太深,会带来哪些隐患?
在 React 中,使用多个 高阶组件(HOC,Higher-Order Component) 可能会导致组件层级变深,这可能会带来以下几个影响: 一、带来的影响 1、调试困难 由于组件被多个 HOC 包裹,React 开发者工具&am…...
企业工厂生产线马达保护装置 功能参数介绍
安科瑞刘鸿鹏 摘要 工业生产中,电压暂降(晃电)是导致电动机停机、生产中断的主要原因之一,给企业带来巨大的经济损失。本文以安科瑞晃电再起动控制器为例,探讨抗晃电保护器在生产型企业工厂中的应用,分析…...
Redis 的五种数据类型面试回答
这里简单介绍一下面试回答、我之前有详细的去学习、但是一直都觉得太多内容了、太深入了 然后面试的时候不知道从哪里讲起、于是我写了这篇CSDN帮助大家面试回答、具体的深入解析下次再说 面试官你好 我来介绍一下Redis的五种基本数据类型 有String List Set ZSet Map 五种基…...
多线程代码案例(定时器) - 3
定时器,是我们日常开发所常用的组件工具,类似于闹钟,设定一个时间,当时间到了之后,定时器可以自动的去执行某个逻辑 目录 Timer 的基本使用 实现一个 Timer 通过这个类,来描述一个任务 通过这个类&…...
基于大模型的GCSE预测与治疗优化系统技术方案
目录 技术方案文档:基于大模型的GCSE预测与治疗优化系统1. 数据预处理模块功能:整合多模态数据(EEG、MRI、临床指标等),标准化并生成训练集。伪代码流程图2. 大模型架构(Transformer-GNN混合模型)功能:联合建模时序信号(EEG)与空间结构(脑网络)。伪代码流程图3. 术…...
IntelliJ IDEA 中 Continue 插件使用 DeepSeek-R1 模型指南
IntelliJ IDEA 中 Continue 插件使用 DeepSeek-R1 模型指南 Continue 是一款开源的 AI 编码助手插件,支持 IntelliJ IDEA 等 JetBrains 系列 IDE。它可以通过连接多种语言模型(如 DeepSeek-R1)提供实时代码生成、问题解答和单元测试生成等功…...
Valgrind——内存调试和性能分析工具
文章目录 一、Valgrind 介绍二、Valgrind 功能和使用1. 主要功能2. 基本用法2.1 常用选项2.2 内存泄漏检测2.3 详细报告2.4 性能分析2.5 多线程错误检测 三、在 Ubuntu 上安装 Valgrind四、示例1. 检测内存泄漏2. 使用未初始化的内存3. 内存读写越界4. 综合错误 五、工具集1. M…...
京东API智能风控引擎:基于行为分析识别恶意爬虫与异常调用
京东 API 智能风控引擎基于行为分析识别恶意爬虫与异常调用,主要通过以下几种方式实现: 行为特征分析 请求频率:正常用户对 API 的调用频率相对稳定,受到网络延迟、操作速度等因素限制。若发现某个 IP 地址或用户在短时间内对同一…...