day03(单片机高级)RTOS

news2024/11/24 18:00:28

目录

RTOS(实时操作系统)

裸机开发模式

轮询方式

前后台(中断方式)

改进(前后台(中断))定时器

 裸机进一步优化

裸机的其他问题

RTOS的概念

什么是RTOS

为什么要使用 RTOS

RTOS的应用场景

RTOS的选择

RTOS的工作原理

FreeRTOS特点

创建第一个FreeRTOS程序

搭建方法

1、官网源码下载

2、处理工程目录

3、打开编译工程

4、去掉无关代码

5、删除未定义报错内容

6、验证

串口打印实验

如何找串口仿真

命名规范

动态任务的创建

任务实验

实现

函数原型

实验

优先级

延时函数

查看延时时间验证

调度原理

抢占式调度

时间片调度

任务状态

挂起任务、恢复任务

挂起任务函数原型

恢复任务函数原型

任务删除

函数原型

空闲任务

空闲任务钩子函数用途

空闲任务钩子函数的实现限制

钩子函数的使用

使用CUBE配置FreeRTOS编写程序

1、更新安装freertos插件

2.配置FreeRTOS

3.配置基础硬件

4.最后生成工程MDK内编写程序


 

RTOS(实时操作系统)

裸机开发模式

轮询方式

对于简单的应用程序,轮询(无限循环)的实现比较简单,在硬件完成初始化后,顺序的完成各种 任务。在外设的基础实验中,常采用这种方式。

int main()
{ 
 while(1)
 {
     DHT11数据采集;
     读取WIFI数据;
     判断数据;
 }
}

在实际的嵌入式系统中,存在周期性与触发型任务,每个任务的执行时间与实时响应要求不同,在采用轮询系统进行程序设计时,很难应对这些场景。

前后台(中断方式)

前后台系统是在轮询的基础上加入了中断。外部事件的记录在中断中操作,对事件的响应在轮询中 完成,中断处理过程称之为前台,main 函数中的轮询称为后台。

后台的程序顺序执行,如果产生中断,那么中断会打断后台程序的正常执行,转而去执行中断服务 程序。如果事件的处理过程比较简单,可以直接在中断服务程序中进行处理;如果事件的处理过程比较 复杂,可以在中断中对事件响应进行标记,进而返回后台程序进行处理。

int main()
{ 
 while(1)
 {
    if(DHT11==1)
    {
     DHT11数据处理;
     DHT11=0;
    }
    if(wifi==1)
    {
     处理WIFI数据;
     wifi=0;
     }
 }
}
void DHT11_irq()
{
    DHT11=1;
}
void WIFI_irq()
{
    wifi=1;
}
//中断处理的速度高了
//触发之后又成为了轮询操作
//假如DHT11优先级高,且处理时间过长 wifi的处理就不及时了

采用前后台系统进行程序时,对后台的任务需要进行设计,避免单个任务长时间占有处理器资源。 当任务的逻辑比较复杂,任务的拆分难度增加,同时,随着中断事件的增加,整个程序的设计与响应的 实时性将会降低。

改进(前后台(中断))定时器

设置3S定时器中断(DHT11采集)

设置5s定时器中断(Wifi数据处理)

 裸机进一步优化

void wifi(void)
{
  static int key=0;
  switch(key)
  {
    case 0:
      发送AT指令();
      key=1
      return;
    case 1:
      接收数据();
       key=2
      return;
    case 2:
      判断数据();
      key=0
      return;
  } 
}
void DHT11(void)
{
  static int DHT11=0;
  switch(DHT11)
  {
    case 0:
      握手();
      DHT11=1
      return;
    case 1:
      接收数据();
       DHT11=2
      return;
    case 2:
      判断数据完整性();
      DHT11=3;
      return;
    case 3:
      数据处理();
      DHT11=0;
      return;
  } 
}
//问题解决了,但是程序的复杂度上来了
//基于裸机架构无法完美解决复杂耗时的多个函数

裸机的其他问题

while(1)
{ 
  DHT11;
  if(key)
  {
    delay(100);//程序在这停止了,效率被影响了
      if(key)
      {
        wifi();
     }
  }
}

按键消抖优化:

在按键中断服务程序开启定时器

在定时器中断服务程序执行按键操作,并关掉定时器

RTOS的概念

什么是RTOS

为什么要使用 RTOS

主要是为了满足系统在时间和资源管理上的特殊需求

使用实时内核的理由可以从多个方面来描述,包括可维护性、可扩展性、模块化、团队开发、测试、代码复用、效率、空闲时间、电源管理、中断处理以及混合处理需求。以下是对这些方面的详细解释:

  • 可维护性:实时内核通常具有抽象化的时间细节,这减少了模块间的依赖关系,使软件更易于维护和演化。由于内核负责计时,应用程序的执行受底层硬件变化的影响较小,进一步提高了可维护性。
  • 模块化:实时内核的每个任务通常被设计为独立的模块,具有明确的设计目的。这种模块化设计有助于团队开发,因为每个团队成员可以独立地负责一个模块的开发和维护,提高开发效率和系统稳定性。
  • 可扩展性:实时内核的设计通常允许添加新的功能或模块,而不需要对现有系统进行大规模修改。这使得系统能够随着需求的变化而扩展,保持长久的生命力。
  • 代码复用:实时内核的模块化设计使得代码更容易被复用。通过低耦合设计,代码可以在不同的模块之间共享和重用,提高了开发效率并降低了维护成本。
  • 提升效率:实时内核通常设计为事件驱动,这意味着它仅在事件发生时才进行处理。这种设计有助于提高系统的响应速度和运行效率。

RTOS的应用场景

物联网(IoT):RTOS是专门为物联网设备设计的操作系统,它提供了实时性、高效性和可靠性,以满足物联网应用的特殊需求。RTOS通过任务调度算法管理任务的执行顺序,确保高优先级任务能够及时响应,满足物联网设备对实时性的要求。

智能家居:RTOS在智能家居系统中用于控制各种智能设备,如智能灯泡、智能插座、智能门锁等。RTOS提供了设备之间的实时通信和协同工作,使用户能够方便地通过智能手机或其他设备控制家居环境。

医疗设备:RTOS在医疗设备中发挥着重要作用,如心脏起搏器、监护仪等设备需要实时处理生理参数,确保患者的生命安全。RTOS的高可靠性和实时性使得这些设备能够在关键时刻发挥关键作用。SAFERTOS等RTOS产品特别针对医疗设备的需求,提供响应迅速、稳健、确定性的嵌入式实时操作系统,降低项目风险、开发成本,并缩短上市时间。

汽车电子:在汽车领域,RTOS的应用越来越广泛。例如,高级驾驶辅助系统(ADAS)需要实时处理大量的传感器数据,以实现自动驾驶、车辆导航等功能。RTOS能够确保这些系统的实时性和稳定性,提高驾驶安全性。

工业自动化和机器人技术:RTOS在工业自动化系统中扮演关键角色,通过精确定时和控制能力,确保生产线的稳定运行,提高生产效率和质量。在机器人技术中,RTOS能够确保机器人实时响应指令,执行复杂任务,如无人机和机器人的飞行轨迹控制、任务执行等。

航空航天:在航空航天领域,RTOS的应用至关重要。由于航空电子系统的复杂性和对实时性的极高要求,RTOS能够提供高度可靠的中断处理和任务调度机制,确保飞行控制系统、导航系统和传感器数据处理的实时性和准确性。

RTOS的选择

安全性:RTOS 是否有助于设备的安全性或损害设备的安全性?容易出现用户错误吗?

性能:RTOS 能否促进应用程序代码的开发?代码是否在所需参数内执行?

可靠性:RTOS 是否会影响设备的可靠性?

功能:RTOS 是否具备完成这项工作所需的设施?

学习RTOS的3个步骤

学会使用API

了解API实现原理

可以优化改进API

RTOS的工作原理

① RTOS相当于实现了后台的主循环,并能够处理ISR主循环的交互

使得用户可以只考虑任务的设计

③ RTOS还提供了各种组件用于实现任务间交互及其他控制管理功能(e.g. 存储管理)

提供多个执行流,虽然实际只有一颗CPU,但通过"虚拟化",每个Task好像独占CPU

提供资源管理和通信组件

提供一些组件用于简化任务对资源的访问,事件的处理,以及任务之间的通信,有效降低任务之间的代码耦合

FreeRTOS特点

创建第一个FreeRTOS程序

搭建方法

  1. 移植文件(FreeRTOS相关文件)+时钟配置
  2. 官网源码下的DEMO(需要精简 去掉无关文件)+标准库
  3. CUBEMX直接生成就可以了
1、官网源码下载

(1)进入FreeRTOS官网

(2)点击下载FreeRTOS

2、处理工程目录

(1)下载后解压FreeRTOS文件

(2)删除多余文件(红框里的)

(3)删除"FreeRTOSv202212.01\FreeRTOS\Demo"目录下用不到的示例工程,留下common这里放了一些公共文件

(4)"FreeRTOSv202212.01\FreeRTOS\Source\portable"目录下只保留如下两个文件夹,其他全部删掉。

(5)"FreeRTOSv202212.01\FreeRTOS\Source\portable\RVDS"目录下只保留如下一个文件夹,其他全部删掉

3、打开编译工程

(1删除后文件后,进入如下图打开工程

(2)弹出如下对话框,说明该工程是用KeilMDK4创建的。点击“Migrate to Device Pack”更新为KeilMDK5。

(3弹出对话框,点击“确定”。

  1. 更新后,关闭工程再重新打开,编译。
  2. 工程目录介绍(System里还有一个lcd也删掉)

4、去掉无关代码

(1Demo Files文件下只保留“serial.c和main.c”文件,其他都删掉(删完之后main里去掉一些头文件)

(2)编译

5、删除未定义报错内容

(1)在文件STM32F10x.s中,删除如下内容。

(2)删除其他未定义的相关内容,再次编译。报错的内容均删除或者注释,直到没错为止。

6、验证

在原有任务的基础上加个i++验证

串口打印实验

1、重定向

这个fputc在main中:

int fputc( int ch, FILE *f )//重定向  修改数据传输方向
{
  while(!(USART1->SR & (1<<7))){}
	USART1->DR =ch;
	return ch;
}

2、配置串口

初始化删除多余的东西,自己写一个串口一的初始化。

 void Uart_Init(void)
 {
     GPIO_InitTypeDef GPIO_InitStructure;
	 USART_InitTypeDef USART_InitStructure;
	 RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE );
	 //tx
		 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
		 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
		 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
		 GPIO_Init(GPIOA,&GPIO_InitStructure);
    //rx
		 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
		 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
		 GPIO_Init(GPIOA,&GPIO_InitStructure);
		 

	  USART_InitStructure.USART_BaudRate = 115200;
		USART_InitStructure.USART_WordLength = USART_WordLength_8b;
		USART_InitStructure.USART_StopBits = USART_StopBits_1;
		USART_InitStructure.USART_Parity = USART_Parity_No ;
		USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
		USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
		USART_InitStructure.USART_Clock = USART_Clock_Disable;
		USART_InitStructure.USART_CPOL = USART_CPOL_Low;
		USART_InitStructure.USART_CPHA = USART_CPHA_2Edge;
		USART_InitStructure.USART_LastBit = USART_LastBit_Disable;
        USART_Init( USART1, &USART_InitStructure );	  
        USART_Cmd( USART1, ENABLE ); 
 }

如何找串口仿真

命名规范

数据类型

命名规范

动态任务的创建

任务是什么

任务是由 C 语言函数实现的。唯一特别的地方是其函数原型,必须返回 void,并带有一个 void 指针参数。

 任务的外观:一个永远不返回的函数

任务实验

实现

创建任务函数xTaskCreate:任务也不是很复杂的东西,任务也就是一个函数

xTaskCreate。简单得说,创建一个任务,你得提供它的执行函数,你得提供它的栈的大小,函数的执行空间,函数的优先级等重要的条件。因为任务在运行中,任务函数有调用关系,有局部变量,这些都保存在任务的栈里面;任务有可能被切换,有可能被暂停,这时候CPU寄存器中断现场数据都保存在栈里面。

函数原型

BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName, const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
                            UBaseType_t uxPriority,
                            TaskHandle_t * const pxCreatedTask )

参数说明

pvTaskCode:指向任务函数的指针。该函数表示任务要执行的代码。

pcName:任务名称字符串。用于调试和跟踪,不影响任务功能。也可用于获取任务句柄

usStackDepth:任务栈大小(以单词为单位)。根据任务需求设定,过小可能导致栈溢出。

pvParameters:传递给任务函数的参数。可以是任意类型的指针。

uxPriority:任务优先级。数值越大,优先级越高。

pxCreatedTask:任务句柄指针。用于存储创建任务后的任务句柄,可选参数。可为NULL

返回值

如果任务创建成功,返回pdPASS。如果任务创建失败(例如内存不足),返回错误码。

任务创建成功后,系统会自动将其加入到调度队列。调度器会根据任务优先级选择合适的任务执行。

实验

优先级

结论

FreeRTOS中,优先级数越大优先级越高,两个任务同优先级时通过时间片轮转执行,如果有高优先级时,高优先级执行,一直到高优先级停止执行低优先级才能执行。

延时函数

void vTaskDelay( const TickType_t xTicksToDelay );

查看延时时间验证

声明个变量a只有任务一执行时才为1,其他时候为0,然后进入仿真使用虚拟逻辑分析仪查看变量a状态

查看方法(进入仿真使用):

调度原理

调度器是内核中负责决定在任何特定时间应执行哪些任务的部分。内核可以在任务生命周期内多次挂起并且稍后恢复一个任务。调度策略是调度器用来决定在任何时间点执行哪个任务的算法。非实时多用户系统的策略极有可能使每个任务具有"公平"比例的处理时间。

FreeRTOS 共支持三种任务调度方式,分别为抢占式调度、时间片调度和协程式调度。需要注意的是,FreeRTOS 官方对协程式调度做了特殊说明,协程式调度用于一些资源非常少的设备上,但是现在已经很少用到。虽然协程式调度的相关代码还没有被删除,FreeRTOS 官方并未计划继续开发协程式调度。因此不推荐在开发中继续使用协程式调度,我们接着理解一下抢占式调度与时间片调度的概念。

抢占式调度

抢占式调度主要时针对优先级不同的任务,每个任务都有一个优先级,优先级高的任务可以抢占优先级低的任务,只有当优先级高的任务发生阻塞或者被挂起,低优先级的任务才可以运行。

时间片调度

时间片调度主要针对优先级相同的任务,当多个任务的优先级相同时, 任务调度器会在每一次系统时钟节拍到的时候切换任务,也就是说 CPU 轮流运行优先级相同的任务,每个任务运行的时间就是一个系统时钟节拍。

在 FreeRTOS 中的任务存在四种状态,分别为运行态、就绪态、阻塞态和挂起态。在 FreeRTOS 运行时,任务的状态一定是这四种状态中的一种,下面是四种任务状态的介绍。

任务状态

同优先级的任务正在运行,所以需要等待。

运行态(Running):如果一个任务得到 CPU 的使用权,即任务被实际执行时,那么这个任务处于运行态。如果运行 FreeRTOS 的 MCU 只有一个处理器核心,那么在任务时刻,都只能有一个任务处理运行态。

就绪态:如果一个任务已经能够被执行(不处于阻塞态或挂起态),但当前还未被执行(具有相同优先级或更高优先级的任务正持有 CPU 使用权),那么这个任务就处于就绪态。

阻塞态(Blocked):如果一个任务因延时一段时间或等待外部事件发生,那么这个任务就处理阻塞态。例如任务调用了函数 vTaskDelay(),进行一段时间的延时,那么在延时超时之前,这个任务就处理阻塞态。任务也可以处于阻塞态以等待队列、信号量、事件组、通知或信号量等外部事件。通常情况下,处于阻塞态的任务都 有一个阻塞的超时时间,在任务阻塞达到或超过这个超时时间后,即使任务等待的外部事件还没有发生, 任务的阻塞态也会被解除。要注意的是,处于阻塞态的任务是无法被运行的。

挂起态(Suspended):任务一般通过函数 vTaskSuspend()和函数 vTaskResums()进入和退出挂起态与阻塞态一样,处于挂起态的任务也无法被运行。

挂起任务、恢复任务

挂起任务函数原型
vTaskSuspend( TaskHandle_t xTaskToSuspend )

参数

xTaskToSuspend:需要挂起任务的句柄

创建任务时加上句柄

句柄声明

恢复任务函数原型

 void vTaskResume( TaskHandle_t xTaskToResume )

参数

TaskToResumex:需要恢复任务的句柄

任务删除

vTaskDelete()函数用于删除任务。在使用这个函数时,需要提供一个任务句柄作为参数,以便通知内核删除哪个任务。

函数原型
void vTaskDelete( TaskHandle_t xTaskToDelete )

参数:

xTaskToDelete:需要删除任务的句柄

如果写的是NULL,则自杀

空闲任务

当创建的任务大部分时间都处于阻塞状态。当任务处于阻塞状态时,它们无法运行,因此调度器无法选择它们。必须始终至少有一个任务可以进入运行状态(即使在使用 FreeRTOS 的特殊低功耗功能时也是如此,在这种情况下,如果应用程序创建的任务都无法执行,那么执行 FreeRTOS 的微控制器将被置于低功耗模式)。为了确保这种情况,当调用 vTaskStartScheduler()时,调度器会自动创建一个空闲任务。空闲任务除了在一个循环中等待之外几乎不执行其他任何操作,因此,就像第一个示例中的任务一样,它始终能够运行。

空闲任务具有尽可能低的优先级(优先级为 0),以确保它永远不会阻止更高优先级的应用程序任务进入运行状态。然而,这并不妨碍应用程序设计者根据需要创建与空闲任务共享优先级的任务。可以使用 FreeRTOSConfig.h 中的 configIDLE_SHOULD_YIELD 编译时配置常量阻止空闲任务消耗处理时间,可以更有效地分配给具有同样优先级的应用程序任务处理时间。运行在最低优先级确保了当更高优先级的任务进入就绪状态时,空闲任务会立即从运行状态转换出来。

注意:如果一个任务使用 vTaskDelete() API 函数来删除自己,那么必须确保空闲任务不会因处理时间不足而受到影响。这是因为空闲任务负责清理由已删除自身的任务所使用的内核资源。

空闲任务钩子函数用途

可以通过使用空闲钩子(或空闲回调)函数直接在空闲任务中添加应用程序的相关功能。处理一些不紧急的任务。空闲钩子函数是一种函数,它在空闲任务循环的每次迭代中自动由空闲任务调用。空闲任务钩子的常见用途包括:

  • 执行低优先级、后台或连续处理功能,而无需为此目的创建应用程序任务,所带来额外的 RAM开销。
  • 测量空闲处理能力(空闲任务仅在所有更高优先级的应用程序任务没有工作要执行时,空闲任务才会运行;因此,测量分配给空闲任务的处理时间,可以清楚地表明有多少处理时间是空闲的)。
  • 将处理器置于低功耗模式,提供了一种简单且自动的方法,在没有应用程序处理要执行时,节省功耗。

空闲任务钩子函数的实现限制

  1. 空闲任务钩子函数绝对不能阻塞或挂起自己。(以任何方式阻塞空闲任务都可能导致没有任务能够进入运行态!)
  2. 如果一个应用程序任务使用 vTaskDelete() API 函数删除自己,那么必须在合理的时间段内将闲任务钩子返回给调用者。这是因为任务被删除后,空闲任务负责清理内核资源。如果空闲任务永久保持在空闲钩子函数中,则无法进行这种清理。

钩子函数的使用

  • main函数中找到vTaskStartScheduler()并跳转

  • vTaskStartScheduler()内可以找到如图的函数

  • 跳转空闲任务函数找到了vApplicationIdleHook()函数就是钩子函数,但是需要configUSE_IDLE_HOOK==1

  • 右键跳转configUSE_IDLE_HOOK并将configUSE_IDLE_HOOK等于1

  • 编译发现报错,内容为vApplicationIdleHook未定义

  • 接下来我们声明写一个vApplicationIdleHook函数并在里面写自己的任务程序就可以了
TaskHandle_t xTask1ToSuspend;
void vApplicationIdleHook( void )
{
	while(1)
	{
		printf("我是钩子,我的优先级为0\n");
	}
}
void task1( void *pvParameters )
{
	for(;;)
	{
		printf("我是任务1,我的优先级高\n");
		vTaskDelay(10);
		
	}
}
void task2( void *pvParameters )
{
	for(;;)
	{
		printf("我是任务2,我的优先级低\n");
		vTaskDelete(xTask1ToSuspend);
	}
}

使用CUBE配置FreeRTOS编写程序

1、更新安装freertos插件

2.配置FreeRTOS

创建一个新的工程

3.配置基础硬件

4.最后生成工程MDK内编写程序

void StartTask02(void *argument)
{
  /* USER CODE BEGIN myTask02 */
  /* Infinite loop */
  for(;;)
  {
		HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
    osDelay(100);
  }
  /* USER CODE END myTask02 */
}

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

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

相关文章

cookie反爬----普通服务器,阿里系

目录 一.常见COOKIE反爬 普通&#xff1a; 1. 简介 2. 加密原理 二.实战案例 1. 服务器响应cookie信息 1. 逆向目标 2. 逆向分析 2. 阿里系cookie逆向 1. 逆向目标 2. 逆向分析 实战&#xff1a; 无限debugger原理 1. Function("debugger").call() 2. …

C++中的erase()函数用法总结

在 C 中&#xff0c;erase() 是 std::string 和 std::vector 等容器中的成员函数&#xff0c;用于删除容器中的元素。erase可以删去容器中指定位置的元素&#xff0c;容器的size&#xff08;大小&#xff09;会改变&#xff0c;但是容器的容量不变。 常用用法&#xff1a; 1.…

全面解析:HTML页面的加载全过程(四)--浏览器渲染之样式计算

主线程遍历得到的 DOM 树&#xff0c;依次为树中的每个节点计算出它最终的样式&#xff0c;称之为 Computed Style。 通过前面生成的DOM 树和 CSSOM 树&#xff0c;遍历 DOM 树&#xff0c;为每一个 DOM 节点&#xff0c;计算它的所有 CSS 属性&#xff0c;最后会得到一棵带有…

Linux|内存级文件原理

目录 进程与文件 Linux下的文件系统 文件操作&#xff0c;及文件流 C语言函数 文件流 文件描述符 系统调用操作 系统调用参数 重定向与文件描述符 输出重定向 输入重定向 文件内容属性 Linux下一切皆文件 进程与文件 当我们对文件进行操作时&#xff0c;文件必须…

40分钟学 Go 语言高并发:Context包与并发控制

Context包与并发控制 学习目标 知识点掌握程度应用场景context原理深入理解实现机制并发控制和请求链路追踪超时控制掌握超时设置和处理API请求超时、任务限时控制取消信号传播理解取消机制和传播链优雅退出、资源释放context最佳实践掌握使用规范和技巧工程实践中的常见场景…

【SpringMVC - 1】基本介绍+快速入门+图文解析SpringMVC执行流程

目录 1.Spring MVC的基本介绍 2.大致分析SpringMVC工作流程 3.SpringMVC的快速入门 首先大家先自行配置一个Tomcat 文件的配置 配置 WEB-INF/web.xml 创建web/login.jsp 创建com.ygd.web.UserServlet控制类 创建src下的applicationContext.xml文件 重点的注意事项和说明…

neo4j图数据库community-5.50创建多个数据库————————————————

1.找到neo4J中的conf文件&#xff0c;我的路径是&#xff1a;D:\Program Files\neo4j-community-5.5.0-windows\neo4j-community-5.5.0\conf 这里找自己的安装路径&#xff0c; 2.用管理员模式打开conf文件&#xff0c;右键管理员&#xff0c;记事本或者not 3.选中的一行新建一…

如何最简单、通俗地理解Python的迭代器?

我们知道迭代器&#xff08;iterator&#xff09;可以用for循环去取数&#xff0c;这和列表取数有什么区别呢&#xff1f; 想理解Python迭起器的差异&#xff0c;有个很简单的例子 打个比方&#xff0c;你去玩街头投篮机&#xff0c;可以投5个球&#xff0c;这里有两种方式&a…

JavaEE 【知识改变命运】02 多线程(1)

文章目录 线程是什么&#xff1f;1.1概念1.1.1 线程是什么&#xff1f;1.1.2 为什么要有线程1.1.3 进程和线程的区别1.1.4 思考&#xff1a;执行一个任务&#xff0c;是不是创建的线程或者越多是不是越好&#xff1f;&#xff08;比如吃包子比赛&#xff09;1.1.5 ) Java 的线程…

Linux内核USB2.0驱动框架分析--USB包

一&#xff0c; 包的组成 每个包都由SOP&#xff08;包起始域&#xff09;、SYNC&#xff08;同步域&#xff09;、Packet Content&#xff08;包内容&#xff09;、EOP&#xff08;包结束域&#xff09;四部分组成&#xff0c;其中SOP、SYNC、EOP为所有包共有的域&#xff0c…

云轴科技ZStack亮相2024 IDC中国生态峰会,共塑AI时代IT生态新格局

11月21日&#xff0c;2024 IDC中国生态峰会在北京举办&#xff0c;吸引了超过300位生态伙伴齐聚一堂&#xff0c;聚焦行业内最前沿的热点话题。本届峰会以“创见先机&#xff0c;智领风云”为主题&#xff0c;深入探讨宏观经济趋势、技术革新以及如何融合AI与数据技术&#xff…

C0029.在Clion中解决Debug时,提示Process finished with exit code -1的错误

1.错误提示 Process finished with exit code -12.解决办法 如上在使用Debug进行代码调试时&#xff0c;直接出现如上报错&#xff0c;解决办法就是直接点击运行程序&#xff0c;即可查出报错编号&#xff0c;然后根据报错编号来查找问题&#xff1b; 然后在网上就可以根据该…

07-Making a Bar Chart with D3.js and SVG

课程链接 Curran的课程&#xff0c;通过 D3.js 的 scaleLinear, max, scaleBand, axisLeft, axisBottom&#xff0c;根据 .csv 文件生成一个横向柱状图。 【注】如果想造csv数据&#xff0c;可以使用通义千问&#xff0c;关于LinearScale与BandScale不懂的地方也可以在通义千…

读取各种来源格式单细胞数据集构建seurat分析对象,代做生信分析

参考资料和分析注意事项 全流程的分析指导视频 演示数据集网盘文件 分析参数文件路径格式的特别提示 大家给要分析用到的文件路径或目录路径的时候&#xff0c;以D:/omics_tools/demo_data/scrnaseq/GSE189125/GSE189125_5prime_scRNAseq_seqbatchA_counts.txt.gz 这个文件为…

SQL-多表操作

前文所介绍的sql操作都是基于单表进行的&#xff0c;接下来我们来学习多表操作。 多表设计 在实际的项目开发中&#xff0c;会根据业务需求和业务模块之间的关系进行数据库表结构设计&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在着各种联系&#xf…

c++ STL线程安全使用

c STL不是线程安全的&#xff0c;因此在多线程中使用的时候&#xff0c;操作同一个容器&#xff0c;会崩溃&#xff0c;因此需要解决线程安全的问题&#xff1a; 使用实例类似于以下&#xff1a; #include <thread> #include <vector> #include "thread_safe…

Swift 实现判断链表是否存在环:快慢指针法

文章目录 前言摘要描述题解答案题解代码题解代码分析示例测试及结果时间复杂度空间复杂度总结关于我们 前言 本题由于没有合适答案为以往遗留问题&#xff0c;最近有时间将以往遗留问题一一完善。 LeetCode - #141 环形链表 不积跬步&#xff0c;无以至千里&#xff1b;不积小流…

SpringCloud实用-OpenFeign 调用三方接口

文章目录 前言正文一、项目环境二、项目结构2.1 包的含义2.2 代理的场景 三、完整代码示例3.1 定义FeignClient3.2 定义拦截器3.3 配置类3.4 okhttp配置3.5 响应体3.5.1 天行基础响应3.5.2 热点新闻响应 3.6 代理类3.6.1 代理工厂3.6.2 代理客户端3.6.3 FeignClient的建造器 四…

C++设计模式行为模式———中介者模式

文章目录 一、引言二、中介者模式三、总结 一、引言 中介者模式是一种行为设计模式&#xff0c; 能让你减少对象之间混乱无序的依赖关系。 该模式会限制对象之间的直接交互&#xff0c; 迫使它们通过一个中介者对象进行合作。 中介者模式可以减少对象之间混乱无序的依赖关系&…

HarmonyOS:使用ArkWeb构建页面

一、简介 页面加载是Web组件的基本功能。根据页面加载数据来源可以分为三种常用场景&#xff0c;包括加载网络页面、加载本地页面、加载HTML格式的富文本数据。 页面加载过程中&#xff0c;若涉及网络资源获取&#xff0c;需要配置ohos.permission.INTERNET网络访问权限。 二、…