【嵌入式开源库】timeslice的使用,完全解耦的时间片轮询框架构
完全解耦的时间片轮询框架构
- 简介
- 项目代码
- timeslice.h
- timeslice.c
- list.h
- list.c
- 创建工程
- 移植代码
- 实验
- 函数说明
- timeslice_task_init
- timeslice_task_add
- timeslice_tak_del
- timeslice_get_task_num
- 结尾
简介
timeslice是一个时间片轮询框架,他是一个完全解耦的时间片轮询框架,他的使用非常方便,该项目一共有四个文件分别是tieslice的头文件和源文件以及list的头文件和源文件,tieslice是负责轮询任务,list是一个双向链表负责任务的管理,在Linux内核中使用非常广泛也很经典,该框架是参考rtt实时操作系统的侵入式链表实现的,本章文章是将该框架移植到stm32单片机上实验,使用也非常容易,单片机只需要启用一个定时器作为时钟即可;
本章使用环境:
stm32f407vet6
代码工程使用cubemx创建
项目代码
该项目的代码是我在微信公众号上看到的一个文章,代码并没有上传在github上,这里直接贴上源代码;
timeslice.h
#ifndef _TIMESLICE_H
#define _TIMESLICE_H#include "list.h"typedef enum {TASK_STOP,TASK_RUN
} IsTaskRun;typedef struct timesilce
{unsigned int id;void (*task_hdl)(void);IsTaskRun is_run;unsigned int timer;unsigned int timeslice_len;ListObj timeslice_task_list;
} TimesilceTaskObj;void timeslice_exec(void);
void timeslice_tick(void);
void timeslice_task_init(TimesilceTaskObj* obj, void (*task_hdl)(void), unsigned int id, unsigned int timeslice_len);
void timeslice_task_add(TimesilceTaskObj* obj);
void timeslice_task_del(TimesilceTaskObj* obj);
unsigned int timeslice_get_task_timeslice_len(TimesilceTaskObj* obj);
unsigned int timeslice_get_task_num(void);
unsigned char timeslice_task_isexist(TimesilceTaskObj* obj);#endif
timeslice.c
#include "timeslice.h"static LIST_HEAD(timeslice_task_list);void timeslice_exec()
{ListObj* node;TimesilceTaskObj* task;list_for_each(node, ×lice_task_list){task = list_entry(node, TimesilceTaskObj, timeslice_task_list);if (task->is_run == TASK_RUN){task->task_hdl();task->is_run = TASK_STOP;}}
}void timeslice_tick()
{ListObj* node;TimesilceTaskObj* task;list_for_each(node, ×lice_task_list){task = list_entry(node, TimesilceTaskObj, timeslice_task_list);if (task->timer != 0){task->timer--;if (task->timer == 0){task->is_run = TASK_RUN;task->timer = task->timeslice_len;}}}
}unsigned int timeslice_get_task_num()
{return list_len(×lice_task_list);
}void timeslice_task_init(TimesilceTaskObj* obj, void (*task_hdl)(void), unsigned int id, unsigned int timeslice_len)
{obj->id = id;obj->is_run = TASK_STOP;obj->task_hdl = task_hdl;obj->timer = timeslice_len;obj->timeslice_len = timeslice_len;
}void timeslice_task_add(TimesilceTaskObj* obj)
{list_insert_before(×lice_task_list, &obj->timeslice_task_list);
}void timeslice_task_del(TimesilceTaskObj* obj)
{if (timeslice_task_isexist(obj))list_remove(&obj->timeslice_task_list);elsereturn;
}unsigned char timeslice_task_isexist(TimesilceTaskObj* obj)
{unsigned char isexist = 0;ListObj* node;TimesilceTaskObj* task;list_for_each(node, ×lice_task_list){task = list_entry(node, TimesilceTaskObj, timeslice_task_list);if (obj->id == task->id)isexist = 1;}return isexist;
}unsigned int timeslice_get_task_timeslice_len(TimesilceTaskObj* obj)
{return obj->timeslice_len;
}
list.h
#ifndef _LIST_H
#define _LIST_H#define offset_of(type, member) (unsigned long) &((type*)0)->member
#define container_of(ptr, type, member) ((type *)((char *)(ptr) - offset_of(type, member)))typedef struct list_structure
{struct list_structure* next;struct list_structure* prev;
} ListObj;#define LIST_HEAD_INIT(name) {&(name), &(name)}
#define LIST_HEAD(name) ListObj name = LIST_HEAD_INIT(name)void list_init(ListObj* list);
void list_insert_after(ListObj* list, ListObj* node);
void list_insert_before(ListObj* list, ListObj* node);
void list_remove(ListObj* node);
int list_isempty(const ListObj* list);
unsigned int list_len(const ListObj* list);#define list_entry(node, type, member) \container_of(node, type, member)#define list_for_each(pos, head) \for (pos = (head)->next; pos != (head); pos = pos->next)#define list_for_each_safe(pos, n, head) \for (pos = (head)->next, n = pos->next; pos != (head); \pos = n, n = pos->next)#endif
list.c
#include "list.h"void list_init(ListObj* list)
{list->next = list->prev = list;
}void list_insert_after(ListObj* list, ListObj* node)
{list->next->prev = node;node->next = list->next;list->next = node;node->prev = list;
}void list_insert_before(ListObj* list, ListObj* node)
{list->prev->next = node;node->prev = list->prev;list->prev = node;node->next = list;
}void list_remove(ListObj* node)
{node->next->prev = node->prev;node->prev->next = node->next;node->next = node->prev = node;
}int list_isempty(const ListObj* list)
{return list->next == list;
}unsigned int list_len(const ListObj* list)
{unsigned int len = 0;const ListObj* p = list;while (p->next != list){p = p->next;len++;}return len;
}
创建工程
配置高速时钟和低速时钟为外部晶振提供
配置调试模式为sw调试模式
配置时钟频率
配置led,这里我的板子是这三个io接入的是led
配置一个10ms的定时器(1000000hz / 1000ms == 1ms = 1khz 就得到10ms需要计数10000重载)记得打开中断
配置工程并生成,工程名设置,单独生成.c.h文件拷贝库文件
下面开始代码的移植工作;
移植代码
首先我们需要将该开源项目的代码添加到工程中
在定时器中断服务函数中添加timeslice轮询函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM3){timeslice_tick();}
}
然后我们需要在main函数中启动定时器并在while1中调用exec函数调度时间片
HAL_TIM_Base_Start_IT(&htim3);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */timeslice_exec();}
到这里我们的移植工作就做完了,该项目的解耦效果真的非常好,移植相当简单,然后我们创建几个任务实验一下效果;
实验
/* USER CODE BEGIN Header */
/********************************************************************************* @file : main.c* @brief : Main program body******************************************************************************* @attention** Copyright (c) 2023 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "timeslice.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM3){timeslice_tick();}
}// 创建3个任务对象
TimesilceTaskObj task_1, task_2, task_3;// 具体的任务函数
void task1_hdl()
{HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_13);
}void task2_hdl()
{HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_14 );
}void task3_hdl()
{HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_15);
}// 初始化任务对象,并且将任务添加到时间片轮询调度中
void task_init()
{timeslice_task_init(&task_1, task1_hdl, 1, 1);timeslice_task_init(&task_2, task2_hdl, 2, 1);timeslice_task_init(&task_3, task3_hdl, 3, 1);timeslice_task_add(&task_1);timeslice_task_add(&task_2);timeslice_task_add(&task_3);
}
/* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_TIM3_Init();/* USER CODE BEGIN 2 */HAL_TIM_Base_Start_IT(&htim3);task_init();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */timeslice_exec();}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Configure the main internal regulator output voltage*/__HAL_RCC_PWR_CLK_ENABLE();__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 25;RCC_OscInitStruct.PLL.PLLN = 336;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ = 4;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK){Error_Handler();}
}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** @brief This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef USE_FULL_ASSERT
/*** @brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* @param file: pointer to the source file name* @param line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
核心部分
// 创建3个任务对象
TimesilceTaskObj task_1, task_2, task_3;// 具体的任务函数
void task1_hdl()
{HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_13);
}void task2_hdl()
{HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_14 );
}void task3_hdl()
{HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_15);
}// 初始化任务对象,并且将任务添加到时间片轮询调度中
void task_init()
{timeslice_task_init(&task_1, task1_hdl, 1, 1);timeslice_task_init(&task_2, task2_hdl, 2, 2);timeslice_task_init(&task_3, task3_hdl, 3, 3);timeslice_task_add(&task_1);timeslice_task_add(&task_2);timeslice_task_add(&task_3);
}
需要注意的是必须要有一个任务是需要在exec前创建,这样才能保证运行,其他的任务可以在这个任务中再创建,上面的实验是实现三个任务,三个任务分别为一个中断触发一次,第二个任务是每隔两个中断触发一次,第三个任务是每隔三个中断触发一次任务;
函数说明
timeslice_task_init
初始化任务函数
void timeslice_task_init(TimesilceTaskObj* obj, void (*task_hdl)(void), unsigned int id, unsigned int timeslice_len)
{obj->id = id;obj->is_run = TASK_STOP;obj->task_hdl = task_hdl;obj->timer = timeslice_len;obj->timeslice_len = timeslice_len;
}
在这个函数中将任务结构体参数初始化,id类似于任务名称用于区分任务,is_run是一个标志位用于判断该任务在该次中断是否需要执行,task_hd1表示函数指针也就是我们的任务函数,timer表示每多少次中断触发一次计数,timeslice_len 表示没多少次中断触发一次计数初始值,在timeslice_tick中当timer的值减到0任务将触发并会重新复位timer的值为 timeslice_len ;
timeslice_task_add
添加任务到双向链表中
void timeslice_task_add(TimesilceTaskObj* obj)
{list_insert_before(×lice_task_list, &obj->timeslice_task_list);
}void list_insert_before(ListObj* list, ListObj* node)
{list->prev->next = node;node->prev = list->prev;list->prev = node;node->next = list;
}
该链表(timeslice_task_list)在timeslice_tick中会轮询进行遍历
timeslice_tak_del
删除正在运行的任务链表
void timeslice_task_del(TimesilceTaskObj* obj)
{if (timeslice_task_isexist(obj))list_remove(&obj->timeslice_task_list);elsereturn;
}
在该函数中会通过timeslice_task_isexist函数去判断链表中是否存在该任务的id,如果存在将返回退出允许,这里涉及到一个Linux中的函数list_entry->container_of,该函数是通过结构体的某个变量获取整个结构体的指针位置,有兴趣可以去学习一下该项目代码的实现;
timeslice_get_task_num
获取当前任务数量,也就是链表的长度
unsigned int timeslice_get_task_num()
{return list_len(×lice_task_list);
}unsigned int list_len(const ListObj* list)
{unsigned int len = 0;const ListObj* p = list;while (p->next != list){p = p->next;len++;}return len;
}
结尾
整体的代码不算复杂但是是值得学习的一个项目,我是凉开水白菜祝各位程序员们节日快乐~ 咱们下文见~
相关文章:

【嵌入式开源库】timeslice的使用,完全解耦的时间片轮询框架构
完全解耦的时间片轮询框架构 简介项目代码timeslice.htimeslice.clist.hlist.c 创建工程移植代码实验函数说明timeslice_task_inittimeslice_task_addtimeslice_tak_deltimeslice_get_task_num 结尾 简介 timeslice是一个时间片轮询框架,他是一个完全解耦的时间片轮…...
人工智能期末考试(刷题篇部分题有答案)
参考: 人工智能 经典考试试题及答案 - 百度文库 大学人工智能期末考试题库 - 百度文库 人工智能【期末复习题】 - 百度文库 人工智能期末试题及答案完整版 - 百度文库 一、选择题 AI的缩写是 Artificial Intelligence反演归结(消解)证明…...

手写Vue渲染器render函数
使用js对象来描述UI更加的灵活。“这种对象”在vue框架中被称为虚拟DOM,渲染函数内部可以创建虚拟DOM,然后vue.js可以将其内容进行渲染。 1.渲染器的介绍 渲染器的作用就是把虚拟DOM渲染为真实DOM 思考下,我们有一个虚拟 DOM,如…...

CGAL+QT
先安装CGAL和QT 安装完QT其中MSVC 这两个没配置 1、x32配置选择的是 x64配置选择的是 2、CGAL 5.4.5 - Manual: Using CGAL on Windows (with Visual C) 参数文章配置一些环境变量 3、 测试 新建build 进行cmake QT、Boost、CGAL都自动匹配上了(环境变量已经配…...
GBase8a SSL 配置
GBase8a SSL 配置 GBase8a MPP Cluster 支持 SSL 标准协议, SSL 协议是一种安全性更高的协议标准, 它加入了数字签名和数字证书来实现客户端和服务器的双向身份验证,保证了通信双方更加安全的数据传输。 配置客户端使用 SSL 安全连接的方式连…...

数据结构之队列(源代码➕图解➕习题)
前言 在学过栈之后,会了解到栈的底层是根据顺序表或者链表来构建的,那么我们今天要学习的队列是否也是基于顺序表和链表呢?那我们直接进入正题吧! 1. 队列的概念(图解) 还是跟上节一样,依旧用图…...

社区迭代|ETLCloud社区新增“论坛”啦!
ETLCloud社区是谷云科技RestCloud旗下面向开发工程师、集成研发人员等技术人员提供全方位交流和学习的开放式平台,也是ETLCloud在产品生态赋能上的一大亮点,旨在能够帮助更多的用户更快捷高效的掌握技能,也为企业提供集成人才培养赋能&#x…...

ohos的代码同步以及添加自己的代码
首先我们需要获取到官方的repo工具,命令如下curl -s https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > ./repo,这里我们就拿到repo工具了,这个repo可以放任意地方,也可以放 /usr/local/bin/repo下,这样可以…...
Python的Pandas库(二)进阶使用
Python开发实用教程 DataFrame的运算 DataFrame重载了运算符,支持许多的运算 算术运算 运算方法运算说明df.add(other)对应元素的加,如果是标量,就每个元素加上标量df.radd(other)等效于otherdfdf.sub(other)对应元素相减,如果…...
如何才能从程序员到架构师?
1 引言 小团队一般 10 人左右,其中常常是技术最牛的人做架构师(或TL)。所以,架构师在广大码农中的占比大概平均不到 10%。而架构师也可以分为初级、中级、高级三档,江湖上真正高水平的软件架构师就更少了。 所以&…...

dvadmin-打包发布-nginx-静态服务器配置-防火墙设置
文章目录 1.下载nginx2.nginx常用命令3.dvadmin打包发布4.防火墙设置 1.下载nginx 也从作者下载的网址下载:https://download.csdn.net/download/m0_67316550/88470098 2.nginx常用命令 注意:一定要在dos窗口启动,不要直接双击nginx.exe&a…...

Win10中Pro/E鼠标滚轮不能缩放该怎么办?
Pro/E安装好后,鼠标滚轮不能缩放模型,该怎么办?问题多发生在win8/win10上,新装了PROE,发现滑动鼠标中键不能放大缩小。 彩虹图纸管理软件_图纸管理系统_图纸文档管理软件系统_彩虹EDM【官网】彩虹EDM图纸管理软件系统…...

腾讯云轻量应用服务器性能如何?值得入手吗?
腾讯云轻量应用服务器性能怎么样?轻量服务器的CPU内存计算性能和同规格的标准型云服务器CVM性能处于同一水准,性能很不错,具有100%CPU性能,并且价格很优惠,值得买。腾讯云百科txybk.com分享腾讯云轻量应用服务器性能测…...

主流大语言模型的技术细节
主流大语言模型的技术原理细节从预训练到微调https://mp.weixin.qq.com/s/P1enjLqH-UWNy7uaIviWRA 比较 LLaMA、ChatGLM、Falcon 等大语言模型的细节:tokenizer、位置编码、Layer Normalization、激活函数等。2. 大语言模型的分布式训练技术:数据并行、…...
面试经典150题——Day22
文章目录 一、题目二、题解 一、题目 6. Zigzag Conversion The string “PAYPALISHIRING” is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility) P A H N A P L S I I G …...
for循环三种跳出循环的方法(retrun、continue、break)
1、continue:指的是跳出当前循环,即不执行continue后的语句,直接进入下次循环。 【continue语句和break语句差不多。不同的是,它不是退出一个循环,而是跳出当前循环,进行下一轮循环】 public static void…...

React中的受控组件(controlled component)和非受控组件(uncontrolled component)
聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…...

python 查找波峰和波谷
import numpy as np import matplotlib.pyplot as plt from scipy.signal import find_peaks# 生成示例信号 x np.array([1, 3, 7, 1, 2, 6, 0, 4, 3, 2, 5, 1])# 寻找波峰 peaks, _ find_peaks(x)# 寻找波谷(使用信号的负数形式) valleys, _ find_pe…...
深入理解 Document Load 和 Document Ready 的区别
目录 前言: 一、Document Ready 二、Document Load 三、理解和总结 前言: 在前端开发中,理解页面加载的不同阶段是至关重要的。特别是当我们需要在页面加载到特定阶段时执行某些操作时,我们需要知道应该使用 document ready 还…...
有趣的算法(七) ——快速排序改进算法
有趣的算法(七) ——快速排序改进算法 目录 有趣的算法(七) ——快速排序改进算法 本文章向大家介绍有趣的算法(七) ——快速排序改进算法,主要内容包括其使用实例、应用技巧、基本知识点总结…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...

家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...

群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...

CSS3相关知识点
CSS3相关知识点 CSS3私有前缀私有前缀私有前缀存在的意义常见浏览器的私有前缀 CSS3基本语法CSS3 新增长度单位CSS3 新增颜色设置方式CSS3 新增选择器CSS3 新增盒模型相关属性box-sizing 怪异盒模型resize调整盒子大小box-shadow 盒子阴影opacity 不透明度 CSS3 新增背景属性ba…...

解析“道作为序位生成器”的核心原理
解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制,重点解析"道作为序位生成器"的核心原理与实现框架: 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...
Java中栈的多种实现类详解
Java中栈的多种实现类详解:Stack、LinkedList与ArrayDeque全方位对比 前言一、Stack类——Java最早的栈实现1.1 Stack类简介1.2 常用方法1.3 优缺点分析 二、LinkedList类——灵活的双端链表2.1 LinkedList类简介2.2 常用方法2.3 优缺点分析 三、ArrayDeque类——高…...
Docker环境下安装 Elasticsearch + IK 分词器 + Pinyin插件 + Kibana(适配7.10.1)
做RAG自己打算使用esmilvus自己开发一个,安装时好像网上没有比较新的安装方法,然后找了个旧的方法对应试试: 🚀 本文将手把手教你在 Docker 环境中部署 Elasticsearch 7.10.1 IK分词器 拼音插件 Kibana,适配中文搜索…...
MySQL用户远程访问权限设置
mysql相关指令 一. MySQL给用户添加远程访问权限1. 创建或者修改用户权限方法一:创建用户并授予远程访问权限方法二:修改现有用户的访问限制方法三:授予特定数据库的特定权限 2. 修改 MySQL 配置文件3. 安全最佳实践4. 测试远程连接5. 撤销权…...

成工fpga(知识星球号)——精品来袭
(如需要相关的工程文件请关注知识星球:成工fpga,https://t.zsxq.com/DMeqH,关注即送200GB学习资料,链接已置顶!) 《孩子都能学会的FPGA》系列是成工完成的第一个系列,也有一年多的时…...