FreeRTOS_系统内核控制函数

news2024/11/16 15:38:47

目录

1. 系统内核控制函数预览

2. 系统内核函数详解

2.1 函数 taskYIELD()

2.2 函数 taskENTER_CRITICAL()

2.3 函数 taskEXIT_CRITICAL()

2.4 函数 taskENTER_CRITICAL_FROM_ISR()

2.5 函数 taskEXIT_CRITICAL_FROM_ISR()

2.6 函数 taskDISABLE_INTERRUPTS()

2.7 函数 taskENABLE_INTERRUPTS()

2.8 函数 vTaskStartScheduler()

2.9 函数 vTaskEndScheduler()

2.10 函数 vTaskSuspendAll()

2.11 函数 xTaskResumeAll()

2.12 函数 vTaskStepTick()


        我们最初看到的计算机称为裸机,在裸机的基础上我们看到最外围的是操作系统,操作系统中的程序主要分为两部分:一是系统系统内核函数,另一个是用户自编程序;其中系统内核函数只供系统内核使用,用户应用程序一般不允许使用,这些 API 函数就是系统内核控制函数;本节我们就来学习这些系统内核控制函数。

1. 系统内核控制函数预览

        顾名思义,内核控制函数就是 FreeRTOS 内核所使用的函数,一般情况下应用层程序不使用这些函数,在 FreeRTOS 官方可以找到这些函数,

        这些函数的含义如下:

        taskYIELD()                                                                                                        任务切换

        taskENTER_CRITICAL()                                                                                    进入临界区,用于任务中

        taskEXIT_CRITICAL()                                                                                        退出临界区,用于任务中

        taskENTER_CRITICAL_FROM_ISR()                                                               进入临界区,用于中断服务函数中

        taskEXIT_CRITICAL_FROM_ISR()                                                                    离开临界区,用于中断服务函数中

        taskDISABLE_INTERRUPTS()                                                                           关闭中断

        taskDISABLE_INTERRUPTS()                                                                           打开中断

        vTaskStartScheduler()                                                                                         开启任务调度器

        vTaskEndScheduler()                                                                                          关闭任务调度器

        vTaskSuspendAll()                                                                                               挂起任务调度器                       

        xTaskResumeAll()                                                                                                恢复任务调度器

        vTaskStepTick()                                                                                                    设置系统节拍值

2. 系统内核函数详解

2.1 函数 taskYIELD()

        此函数用于任务切换,此函数本质上是一个宏。

        taskYIELD() 是一个函数调用,用于主动触发任务调度器进行任务切换。当任务调用 taskYIELD() 时,它会主动让出CPU,并将控制权交给调度器,以便调度器可以选择下一个要执行的任务。

        使用 taskYIELD() 的目的是实现任务之间的合理切换和资源共享。通过显式地调用 taskYIELD(),任务可以主动放弃CPU,让其他就绪态的任务有机会执行,从而实现任务的公平竞争和平衡运行。

一些常见的使用场景包括:

  1. 任务优先级调整:通过在任务中调用 taskYIELD(),可以使当前任务放弃CPU并允许具有更高优先级的任务运行。这可以有效地改变任务的执行顺序和优先级,以满足不同任务的实时要求。

  2. 资源共享:在某些情况下,多个任务可能需要共享某些资源,如共享数据结构、设备接口等。通过调用 taskYIELD(),可以让其他等待该资源的任务得到执行,从而避免资源的独占和饥饿现象。

需要注意的是,taskYIELD() 并不会强制切换到任何特定的任务,它只是将控制权交给调度器,由调度器决定下一个要运行的任务。因此,具体任务的切换顺序和频率还取决于任务的优先级、时间片轮转等调度策略。

2.2 函数 taskENTER_CRITICAL()

        进入临界区,用于任务函数中,本质上是一个宏。

        在FreeRTOS中,临界区是一段代码,需要在其中保证原子性和一致性,防止被并发访问干扰。通常,临界区用于保护对共享资源的访问,以避免竞态条件和数据不一致的问题。

taskENTER_CRITICAL() 宏定义的作用是禁用任务调度器中断,并保存中断状态。它将执行以下操作:

  1. 禁用任务调度器中断:通过调用 taskDISABLE_CRITICAL() 函数来禁用中断,这样其他中断将无法打断临界区的执行。
  2. 保存中断状态:将当前中断状态保存在一个变量中。这样,在临界区结束后,通过调用 taskEXIT_CRITICAL() 宏来还原中断状态。

        通过使用 taskENTER_CRITICAL() 和 taskEXIT_CRITICAL() 对临界区进行保护,可以确保代码在临界区执行期间不被任务切换或其他中断处理程序打断,从而保证了临界区代码的原子性和一致性。

        需要注意的是,临界区应尽量保持简短,避免在临界区内执行耗时操作,以免影响系统的实时性和响应性。

2.3 函数 taskEXIT_CRITICAL()

        退出临界区,用于任务函数中,本质上也是一个宏。

        在FreeRTOS中,taskEXIT_CEITICAL() 宏定义的作用是恢复之前保存的中断状态,并允许任务调度器中断重新启用。它执行以下操作:

  1. 恢复中断状态:根据之前保存的中断状态,将中断重新设置为相应的状态,即恢复中断控制器中的中断使能状态。

  2. 可能唤醒任务调度器:如果在临界区期间有更高优先级的任务就绪,并且之前禁止任务调度器中断,taskEXIT_CEITICAL() 将会唤醒任务调度器,并触发任务切换,让更高优先级的任务开始执行(前提是没有其他阻塞或延迟任务)。

        通过使用 taskENTER_CEITICAL() 和 taskEXIT_CEITICAL() 对临界区代码进行保护,可以实现对共享资源的安全访问,避免竞态条件和数据不一致问题。

        需要注意的是,进入临界区和退出临界区的操作应成对出现,确保临界区代码逻辑正确,并且不会长时间禁用任务调度器中断,影响系统的实时性。

2.4 函数 taskENTER_CRITICAL_FROM_ISR()

        进入临界区,用于中断服务函数中,此函数本质上是一个宏。

        在有 taskENTER_CRITICAL 和 taskEXIT_CRITICAL 的基础上还要引入 taskENTER_CRITICAL_FROM_ISR 的原因是:在中断服务程序执行的上下文不同于任务上下文,因此不能直接使用 taskENTER_CRITICAL 和 taskEXIT_CRITICAL 这些宏来保护临界区。相反,需要使用特定的宏定义来确保在中断服务程序执行期间对共享资源的原子性和一致性保护。

        taskENTER_CRITICAL_FROM_ISR 宏定义的作用是在中断服务程序中禁用中断,并保存中断状态。

        1. 禁用中断:使用适当的机制禁用当前的中断,这样其它中断无法打断临界区的执行。

        2. 保存中断状态:将当前中断保存在一个变量中。这样,在临界区结束以后,通过调用宏 taskEXIT_CRITICAL_FROM_ISR 来恢复中断状态。

        通过使用 taskENTER_CRITICAL_FROM_ISR() 和 taskEXIT_CRITICAL_FROM_ISR() 宏对中断服务程序中的临界区进行保护,可以确保在中断服务程序执行期间不被同优先级的中断或其他任务切换打断,从而保证了临界区代码的原子性和一致性。

        需要注意:进入和退出临界区的操作应该成对出现,确保临界区代码逻辑正确,并且不会长时间禁用中断,影响系统的实时性。

2.5 函数 taskEXIT_CRITICAL_FROM_ISR()

        退出临界区,用于中断服务函数中,函数本质上也是一个宏。

        在有 taskENTER_CRITICAL 和 taskEXIT_CRITICAL 的基础上还要引入 taskEXIT_CRITICAL_FROM_ISR 的原因同样是是:在中断服务程序执行的上下文不同于任务上下文,因此不能直接使用 taskENTER_CRITICAL 和 taskEXIT_CRITICAL 这些宏来保护临界区。相反,需要使用特定的宏定义来确保在中断服务程序执行期间对共享资源的原子性和一致性保护。

        taskEXIT_CRITICAL_FROM_ISR() 宏定义的作用是恢复之前保存的中断状态,并允许同优先级的中断重新启用。它执行以下操作:

        1. 恢复中断状态:根据之前保存的中断状态,将中断重新设置为相应的状态,即恢复中断控制器中的中断使能状态。

        2. 唤醒更高优先级的中断:如果在临界区期间有更高优先级的中断发生,并且之前禁止同优先级的中断,taskEXIT_CRITICAL_FROM_ISR() 将会唤醒该中断,让它继续执行(前提是没有其他阻塞或延迟任务)。

        通过使用 taskENTER_CRITICAL_FROM_ISR() 和 taskEXIT_CRITICAL_FROM_ISR() 宏对中断服务程序中的临界区进行保护,可以确保在中断服务程序执行期间不被同优先级的中断或其他任务切换打断,从而保证了临界区代码的原子性和一致性。

        需要注意:进入和退出临界区的操作应该成对出现,确保临界区代码逻辑正确,并且不会长时间禁用中断,影响系统的实时性。

2.6 函数 taskDISABLE_INTERRUPTS()

        关闭可屏蔽中断,此函数本质上是一个宏。

        在 FreeRTOS 中,taskDISABLE_INTERRUPST() 函数的作用是禁用任务调度器中断。调用该函数将禁用中断,防止中断处理程序打断正在执行的任务,从而确保任务的原子性和一致性。

        需要注意的是,禁用中断会影响系统的实时性和响应性,因此应谨慎使用。通常情况下,禁用中断是为了保护关键的数据操作或临界区。禁用中断的时间应尽量控制在最短的时间内,以避免对系统的影响过大

        在使用 taskDISABLE_INTERRUPTS() 函数禁用中断后,可以使用 taskENABLE_INTERRUPTS() 函数来重新启用中断。

        需要注意:taskDISABLE_INTERRUPTS() 函数和 taskENABLE_INTERRUPTS() 函数通常用于任务上下文中,而在中断服务程序(ISR)中,应使用适当的宏定义来禁用和启用中断,如 portENTER_INTERRUPTS() 和 portEXIT_INTERRUPTS()。

2.7 函数 taskENABLE_INTERRUPTS()

        打开可屏蔽中断,此函数本质上是一个宏。

        在 FreeRTOS 中,taskENTER_INTERRUPTS() 函数的作用是启用任务调度器中断。调用该函数将允许中断处理程序打断正在执行的任务,使得系统能够响应其他中断和事件。

        在使用 taskDISABLE_INTERRUPTS() 函数禁用中断后,可以使用 taskENABLE_INTERRUPTS() 函数来重新启用中断,从而恢复任务的正常调度和中断处理。

        需要注意的是,启用中断应谨慎使用,并且应尽量控制在必要的时间内。尽管启用中断可以提高系统的实时性和响应性,但在某些情况下,过多的中断可能导致系统负载过重或产生竞态条件。因此,应根据具体的应用需求和系统性能进行细致的考虑和调整。

2.8 函数 vTaskStartScheduler()

        启动任务调度器。

        在 FreeRTOS 中,任务调度器是负责任务调度和管理的核心部件。在应用程序初始化完成以后,调用 vTaskStartScheduler() 函数可以启动任务调度器,使得任务能够按照特定的调度算法进行调度和执行。

        vTaskStartScheduler() 函数执行以下操作:

        1. 初始化任务管理器。首先,它会初始化任务管理器,设置相关的数据结构和全局变量,为任务调度器做准备。

        2. 进入主调度循环。它会进入一个主调度循环,不断地选择要执行的下一个任务,并将控制权转移到该任务的执行函数。

        3. 任务切换和调度。在主调度循环中,任务调度器根据任务的优先级、调度策略和调度算法,决定在给定时间片内应该运行哪个任务。任务切换涉及保存当前任务的上下文,切换到下一个任务的上下文,并执行与任务切换相关的操作,如栈切换、任务状态更新等。

        需要注意的是:vTaskStartScheduler() 函数只能在初始化完所有任务和相关的 FreeRTOS 组件后调用,且不能返回。一旦任务调度器启动,它将接管程序的控制权,并开始调度和执行任务。

        在调用 vTaskStartScheduler() 函数之前,通常需要先创建并初始化任务、队列、信号量、定时器等相关的 FreeRTOS 组件,以确保任务调度器具备正确的任务和资源配置。

2.9 函数 vTaskEndScheduler()

        关闭任务调度器。

        vTaskEndScheduler() 是 FreeRTOS 中的一个函数,用于终止任务调度器。

        在 FreeRTOS 中,任务调度器负责任务的调度和管理。调用 vTaskEndScheduler() 函数可以结束任务调度器的运行,终止任务的调度和执行。

        调用 vTaskEndScheduler() 函数执行以下操作:

        1. 停止任务调度。首先,它会停止任务调度器的运行,禁止任务切换和调度。

        2. 清理资源。然后,它会执行一些清理操作,释放任务调度器和其他相关组件占用的资源,包括堆栈空间、定时器资源、队列和信号量等。

        需要注意的是:调用 vTaskEndScheduler() 函数会导致任务调度器停止运行,并将控制权返回到调用 vTaskEndScheduler() 的位置。因此,该函数通常用于任务调度器停止之后的清理操作或特殊情况的处理。

        在调用 vTaskEndScheduler() 之前,确保在任务调度器中没有正在执行的任务,并根据需要停止的定时器、删除队列或信号量等。

        需要注意的是:一旦调用 vTaskEndScheduler() 函数将会终止任务调度器,后序的任务调度和和执行将无法继续,除非重新启用任务调度器。

        FreeRTOS 中对此函数的解释如上:

        可以看出此函数仅用于 x86 架构的处理器,调用此函数以后所有系统时钟就会停止运行,所有创建的任务都会自动的删除掉,多任务性能关闭。可以调用函数 vTaskStartScheduler() 来重新开启任务调度器。

        此函数在文件 tasks.c 中有如下定义:

void vTaskEndScheduler( void ) 
{ 
    portDISABLE_INTERRUPTS(); //关闭中断 
    xSchedulerRunning = pdFALSE; //标记任务调度器停止运行 
    vPortEndScheduler(); //调用硬件层关闭中断的处理函数 
} 

//函数 vPortEndScheduler() 在 port.c 中有定义,这个函数在移植 FreeRTOS 的时候要根据实际使用的处理器来编写

void vPortEndScheduler(void)
{
    configASSERT(UXCriticalNesting == 1000UL);
}

2.10 函数 vTaskSuspendAll()

        挂起任务调度器,调用此函数不需要关闭可屏蔽中断即可挂起任务调度器,此函数在文件 tasks.c 中有如下定义:

void vTaskSuspendAll(void)
{
    ++uxSchedulerSuspended;
}

        可看出,此函数只是简单的将变量 uxSchedulerSuspended 加一,uxSchedulerSuspended 是挂起嵌套计数器,调度器挂起是支持嵌套的。使用函数 xTaskResumeAll() 可以恢复任务调度器。注意:调用了几次 vTaskSuspendAll() 挂起调度器,同样的也得调用几次 xTaskResumeAll() 才会最终恢复任务调度器。

        假设现在有这样一种情况,任务 1 的优先级为 10,此时任务 1 由于等待队列 TestQueue 而处于阻塞态。但是有段其他的代码调用函数 vTaskSuspendAll()挂起了任务调度器,在还没有调用 xTaskResumeAll()恢复任务调度器之前,有 个在外部中断发生了,在中断服务程序里面调用函数 xQueueSendFromISR()向任务 1 发送了队 列 TestQueue。如果任务调度器没有阻塞的话函数 xQueueSendFromISR()会使任务 1 进入就绪 态,也就是将任务 1 添加到优先级 10 对应的就绪列表 pxReadyTasksLists[10] 中,这样当任务切 换的时候任务 1 就会运行。但是现在任务调度器由于函数 vTaskSuspendAll() 而挂起,这个时候 任务 1 就不是添加到任务就绪列表 pxReadyTasksLists[10] 中了,而是添加到另一个叫做 xPendingReadyList 的列表中,xPendingReadyList 是个全局变量,在文件 tasks.c 中有定义。当调 用函数 xTaskResumeAll()恢复调度器的时候就会将挂到列表 xPendingReadyList 中的任务重新移 动到它们所对应的就绪列表 pxReadyTasksLists 中。(以上描述的现象简单来说就是:现在有一个任务 1 ,等待队列而处于阻塞态,有段程序调用了 vTaskSuspendAll() 挂起了任务调度器,任务调度器不能再进行任务切换了,在还没有恢复之前, 有一个中断服务函数,中断服务函数向任务 1 发送了队列,如果任务调度器没有被挂起的话,现在任务 1 是要进入就绪态的,但是因为被挂起了,所以现在任务 1 不是进入就绪态,而是被添加到了一个叫做 xPendingReadyList 的列表中;此时如果调用函数 xTaskResumeAll() 恢复调度器的话,被挂到列表 xPendingReadyList 中的任务会重新移动到它们所对应的就绪列表 pxReadyTasksLists 中)

2.11 函数 xTaskResumeAll()

        此函数用于将任务调度器从挂起状态恢复。

        xTaskResumeAll() 是 FreeRTOS 中的一个函数,用于恢复中断嵌套计数,并允许低优先级任务重新抢占。

        在 FreeRTOS 中,任务抢占是通过嵌套中断计数实现的。当调用 xTaskResumeAll() 函数时,它会将中断嵌套计数减一。当中断嵌套计数为 0 时,低优先级的任务将有机会重新抢占执行,以确保多任务间的公平调度。

        具体而言,xTaskResumeAll() 函数执行以下操作:

        1. 递减中断嵌套计数。该函数将嵌套中断计数减一,表示允许任务调度器重新对低优先级任务进行调度。

        2. 是否进行任务切换。如果中断嵌套计数减一后为 0 ,并且当前的中断处于待处理状态,则可以发生任务切换。这将使得等待执行的低优先级任务得到机会,并可能暂停当前正在执行的高优先级任务。

        需要注意的是:xTaskResumeAll() 函数必须与先前调用的 vTaskSuspendAll() 函数成对使用,以确保正确的中断嵌套计数管理。在调用 vTaskSuspendAll() 函数后,任务调度器将停止进行任务切换,所有任务都会暂时被挂起。而在调用 xTaskResumeAll() 函数后,中断嵌套计数将递减并可能导致任务切换。

        在实际应用中,xTaskResumeAll() 函数通常在临界区保护的上下文中使用,以确保对中断嵌套计数的正常操作。

BaseType_t xTaskResumeAll( void ) 
{ 
    TCB_t *pxTCB = NULL; 
    BaseType_t xAlreadyYielded = pdFALSE; 
 
    configASSERT( uxSchedulerSuspended ); 
    taskENTER_CRITICAL(); (1) 
    { 
        --uxSchedulerSuspended; (2) 
        if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) (3) 
        { 
            if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U ) 
            { 
                while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE ) (4) 
                { 
                    pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY\ (5) 
                            ( ( &xPendingReadyList ) ); 
                    ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); (6) 
                    ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); (7) 
                    prvAddTaskToReadyList( pxTCB ); (8) 
                    if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) (9) 
                    { 
                        xYieldPending = pdTRUE; 
                    } 
                    else 
                    { 
                        mtCOVERAGE_TEST_MARKER(); 
                    } 
                } 
                                    /************************************************************************/ 
/****************************省略部分代码********************************/ 
/************************************************************************/ 
                if( xYieldPending != pdFALSE ) (10) 
                { 
                    #if( configUSE_PREEMPTION != 0 ) 
                    { 
                        xAlreadyYielded = pdTRUE; (11) 
                    } 
                #endif 
                taskYIELD_IF_USING_PREEMPTION(); (12) 
            } 
            else 
            { 
                mtCOVERAGE_TEST_MARKER(); 
            } 
        } 
    } 
        else 
        { 
            mtCOVERAGE_TEST_MARKER(); 
        } 
    } 
    taskEXIT_CRITICAL(); (13) 
    return xAlreadyYielded; (14) 
} 

(1)进入临界区

(2)调度器挂起嵌套计数器 uxSchedulerSuspended 减一

(3)如果 uxSchedulerSuspended 为 0 说明所有的挂起都已经解除了,调度器可以开始运行了

(4)while() 循环处理列表 xPendingReadyList,只要列表 xPendingReadyList 不为空,说明还有列表挂到了列表 xPendingReadyList 上,这里需要将这些任务从列表 xPendingReadyList 上移除并添加到这些任务所对应的就绪列表中。

(5)遍历列表 xPendingReadyList,获取挂到列表 xPendingReadyList 上的任务对应的任务控制块。

(6)将任务从事件列表上删除。

(7)将任务从状态列表上移出。

(8)调用函数 prvAddTaskToReadyList() 将任务添加到就绪列表中。

(9)判断任务的优先级是否高于当前正在运行的任务,如果是的话需要将 xYieldPending 标记为 pdTRUE,表示需要进行任务切换。

(10)根据(9)得出需要进行任务切换。

(11)标记在函数 xTaskResumeAll() 中进行了任务切换,变量 xAlreadyYielded 用于标记在函数 xTaskResumeAll() 中是否有进行任务切换。

(12)调用函数 taskYIELD_IF_USING_PREEMPTION() 进行任务切换,此函数本质上是一个宏,其实最终调用是通过函数 portYIELD() 来完成任务切换的。

(13)退出临界区

(14)返回变量 xAlreadyYielded,如果为 pdTRUE 的话表示在函数 xTaskResumeAll() 中进行了任务切换,如果为 pdFALSE 的话表示没有进行任务切换。

2.12 函数 vTaskStepTick()

        此函数在使用 FreeRTOS 的低功耗 tickless 模式的时候会用到,即宏 configUSE_TICKLESS_IDLE 为 1。当使能低功耗 tickless 模式以后在执行空闲任务的时候系统时钟节拍中断就会停止运行,系统时钟中断停止运行的这段时间必须得补上,这个工作就是由函数 vTaskStepTick() 来完成的

void vTaskStepTick( const TickType_t xTicksToJump ) 
{ 
    configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime ); 
    xTickCount += xTicksToJump;                         (1) 
    traceINCREASE_TICK_COUNT( xTicksToJump ); 
}

(1)函数参数 xTicksToJump 是要加上的时间值,系统节拍计数器 xTickCount 加上这个时间值得到新的系统时间。

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

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

相关文章

1. 数字mic驱动分析

一般遇到的音频硬件都是这样的 由于项目不需要播放只需要录音&#xff0c;于是将模拟的mic换成了数字mic&#xff0c;直接通过i2s连接到soc 由于还要使用alsa架构进行录音&#xff0c;所以这里不能简单的写个代码读i2s数据&#xff0c;需要虚拟出一个codec 上面就是我们这次要分…

第九十六天学习记录:Linux基础:实用操作Ⅰ

注&#xff1a;第一张图与学习记录无关&#xff0c;是为了参与CSDN的AI绘图活动 CtrlC强制停止 1、Linux某些程序的运行&#xff0c;如果想要强制停止它&#xff0c;可以使用快捷键CtrlC中止 2、在命令输入错误时&#xff0c;也可以通过快捷键CtrlC快速退出当前输入 CtrlD…

projection介绍及EPSG:4326和EPSG:3857的投射转换

每个地图数据在Web端加载显示时&#xff0c;都需要设罝其投影坐标系。众所周知&#xff0c;地图是不规则的椭球体&#xff0c;如果我们将其展开到二维平面上&#xff0c;会发现地图与实际情况有出入。所以&#xff0c;人们提出 投影的方式来尽量减小失真的程度。 openlayers的…

技术驱动美丽:动态贴纸与美颜SDK的应用实践与创新

随着科技的迅速发展&#xff0c;智能手机的普及以及社交媒体的兴起&#xff0c;人们对于美颜和创意贴纸的需求日益增长。动态贴纸和美颜技术的应用已经成为当今互联网时代的一种趋势。本文将重点讨论动态贴纸与美颜SDK的应用实践与创新&#xff0c;探讨它们对美容美妆行业和社交…

运维必学 | 变量定义调用-从零开始学Windows批处理(Batch)编程系列教程

欢迎关注「全栈工程师修炼指南」公众号 设为「星标⭐」每天带你 基础入门 到 进阶实践 再到 放弃学习&#xff01; 专注 企业运维实践、网络安全、系统运维、应用开发、物联网实战、全栈文章 等知识分享 “ 花开堪折直须折&#xff0c;莫待无花空折枝。 ” 作者主页&#xff1…

vue中如何封装一个基础组件---demo

在 Vue 中封装基础组件可以提高代码的可复用性和维护性&#xff0c;使开发过程更高效。下面是封装基础组件的一般步骤&#xff1a; 确定组件功能&#xff1a;首先确定要封装的基础组件的功能和用途。基础组件通常是具有单一功能的&#xff0c;可以在不同的项目中多次使用的组件…

【C++初阶】C++入门——缺省参数、函数重载

目录 一、缺省参数1.1 定义1.2 缺省参数分类1.3 缺省参数只能出现在函数声明中 二、函数重载2.1 定义2.2 构成重载的几种情况2.3 C支持函数重载的原理 一、缺省参数 1.1 定义 缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时&#xff0c;如果没有指定实…

下一代Windows被披露,任何硬件都能运行

这么些年来&#xff0c;微软似乎一直没能打破 Windows 系统隔代香魔咒。 继 Win XP 惊艳世界后 Win Vista 表现平平&#xff0c;到 Win 7 引领一个时代&#xff1b; 接着 Win 8 含泪淹没在前代耀眼光环之下&#xff0c;直到 Win 10 再创辉煌成功走入家家户户。 而最新的 Win …

vue-antd-admin——关闭当前页面,跳转到指定页面——bus事件总线的用法

最近在写后台管理系统时&#xff0c;遇到一个需求&#xff1a; 关闭当前页面&#xff0c;然后跳转到指定页面。 具体实现方法如下&#xff1a; 1.tabsView.vue文件中添加bus文件&#xff0c;并实现跨组件之间的监听 1.1 引入bus文件 import Bus from /utils/bus; bus文件内…

C#winform自定义圆角按钮控件

本篇介绍自定义圆角渐变按钮,实现过程,实现效果如下 创建winform项目,添加组件类控件 修改的名称为ButtonEx,并点击添加 修改cs中的代码 using System; using System.ComponentModel;using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms;…

HKDF秘钥生成算法

HKDF叫HMAC-based KDF(key derivation function)&#xff0c;基于HMAC的密钥推导函数&#xff0c;所以我们先认识HMAC算法。 1. HMAC 基于一个共同密钥&#xff0c;在两个对端之间提供消息完整性确认的机制叫"message authentication codes(MAC)&#xff0c;消息认证码&…

【CSS】CSS使用变量与变量定义

如何定义可以在CSS中使用的变量 CSS变量&#xff08;也称为自定义属性&#xff09;的定义规则如下&#xff1a; 使用–作为前缀&#xff0c;后跟变量名。变量名可以由字母、数字、连字符和下划线组成&#xff0c;并且不能以连字符开头。变量名区分大小写。变量定义在选择器范…

数据中心可视化——智慧机房数字孪生,高效运维管理

IDC&#xff08;Internet Data Center&#xff09;数据中心可视化是指通过可视化的方式对数据中心的运行状态、资源使用情况、安全监控等进行展示和管理。可以帮助管理员更好地了解数据中心的运行情况和趋势&#xff0c;及时发现问题并采取措施&#xff0c;提高数据中心的运行效…

鼠标悬停,用气泡形式提示用户信息

需求 鼠标悬停,用气泡形式提示用户名字信息 效果图 分析 图中深浅两色的小方块是由v-if遍历二维数组得来的,所以这个需求本质上是原生html元素的出现与隐藏,重点在于知道显示或隐藏哪一个元素 代码 <!-- shelvesList就是后台给前端的,关于库位信息的二维数组 --> &l…

用RunnerGo平替JMeter?这个测试平台确实可以!

1、前言 目前在性能测试领域市场jmeter占有率非常高&#xff0c;主要原因是相对比其他性能测试工具使用更简单&#xff08;开源、易扩展&#xff09;&#xff0c;功能更强大&#xff08;满足多种协议的接口&#xff09;&#xff0c;但是随着研发协同的升级&#xff0c;平台化…

java版本企业电子招标采购系统源码+二次开+Spring Cloud + Spring Boot 发

一、立项管理 1、招标立项申请 功能点&#xff1a;招标类项目立项申请入口&#xff0c;用户可以保存为草稿&#xff0c;提交。 2、非招标立项申请 功能点&#xff1a;非招标立项申请入口、用户可以保存为草稿、提交。 3、采购立项列表 功能点&#xff1a;对草稿进行编辑&#x…

耳骨传导耳机哪个牌子好,几款实战性高的耳骨传导耳机分享

骨传导耳机是一种利用骨头直接传声的耳机&#xff0c;因为它不需要通过耳道来听音乐&#xff0c;所以能够更好地保护听力&#xff0c;也不会因为佩戴耳机而影响到我们正常的交流&#xff0c;可以说是一种比较健康的耳机。不过骨传导耳机的价格相对于普通蓝牙耳机来说还是要贵一…

二叉树题目:相同的树

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;相同的树 出处&#xff1a;100. 相同的树 难度 3 级 题目描述 要求 给你两个二叉树的根结点 p \texttt{p} p …

振动在线监测:如何优化您的设备维护计划?

在工业生产中&#xff0c;设备的维护计划对于确保设备可靠性和生产效率至关重要。而振动在线监测作为一种先进的技术手段&#xff0c;可以实时监测设备振动情况&#xff0c;帮助企业优化维护计划&#xff0c;提高设备维护效率。本文将介绍振动在线监测的重要性&#xff0c;并分…

SparkSQL的分布式执行引擎(Spark ThriftServer)

文章目录 1.Spark ThriftServer2.启动 Spark ThriftServer3.Beeline方式连接4.DataGrip方式连接5. 代码方式6. SparkSQL运行方式7.参考文章 1.Spark ThriftServer Spark ThriftServer 相当于一个持续性的Spark on Hive集成模式&#xff0c;可以启动并监听在10000端口&#xff…