(学习日记)2024.03.10:UCOSIII第十二节:多优先级

news2025/2/23 17:23:48

写在前面:
由于时间的不足与学习的碎片化,写博客变得有些奢侈。
但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈。
既然如此
不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录,记录笔者认为最通俗、最有帮助的资料,并尽量总结几句话指明本质,以便于日后搜索起来更加容易。


标题的结构如下:“类型”:“知识点”——“简短的解释”
部分内容由于保密协议无法上传。


点击此处进入学习日记的总目录

2024.03.10

  • 二十五、UCOSIII:多优先级
    • 1、定义优先级相关全局变量
    • 2、修改OSInit()函数
    • 3、修改任务控制块TCB
    • 4、修改OSTaskCreate()函数
    • 5、修改OS_IdleTaskInit()函数
    • 6、修改OSStart()函数
    • 7、修改PendSV_Handler()函数
    • 8、修改OSTimeDly()函数
    • 9、修改OSSched()函数
    • 10、修改OSTimeTick()函数
  • 二十六、UCOSIII:修改main()函数
    • 1、修改部分:
    • 2、实验现象

二十五、UCOSIII:多优先级

在本章之前,OS还没有到优先级,只支持两个任务互相切换,从本章开始,任务中我们开始加入优先级的功能。 在μC/OS-III中,数字优先级越小,逻辑优先级越高。

1、定义优先级相关全局变量

在支持任务多优先级的时候,需要在os.h头文件添加两个优先级相关的全局变量

/* 在os.h中定义 */
/* 当前优先级 */
OS_EXT            OS_PRIO                OSPrioCur;
/* 最高优先级 */
OS_EXT            OS_PRIO                OSPrioHighRdy;

2、修改OSInit()函数

刚刚新添加的优先级相关的全部变量,需要在OSInit()函数中进行初始化
其实OS中定义的所有的全局变量都是在OSInit()中初始化的。

void OSInit (OS_ERR *p_err)
{
    /* 配置OS初始状态为停止态 */
    OSRunning =  OS_STATE_OS_STOPPED;

    /* 初始化两个全局TCB,这两个TCB用于任务切换 */
    OSTCBCurPtr = (OS_TCB *)0;
    OSTCBHighRdyPtr = (OS_TCB *)0;

    /* 初始化优先级变量 */
    OSPrioCur                       = (OS_PRIO)0;
    OSPrioHighRdy                   = (OS_PRIO)0;

    /* 初始化优先级表 */
    OS_PrioInit();

    /* 初始化就绪列表 */
    OS_RdyListInit();

    /* 初始化空闲任务 */
    OS_IdleTaskInit(p_err);
    if (*p_err != OS_ERR_NONE) {
        return;
    }
}

3、修改任务控制块TCB

在任务控制块中,加入优先级字段Prio
优先级Prio的数据类型为OS_PRIO, 宏展开后是8位的整型,所以只支持255个优先级。

struct os_tcb {
    CPU_STK         *StkPtr;
    CPU_STK_SIZE    StkSize;

    /* 任务延时周期个数 */
    OS_TICK         TaskDelayTicks;

    /* 任务优先级 */
    OS_PRIO         Prio;

    /* 就绪列表双向链表的下一个指针 */
    OS_TCB          *NextPtr;
    /* 就绪列表双向链表的前一个指针 */
    OS_TCB          *PrevPtr;
};

4、修改OSTaskCreate()函数

void OSTaskCreate (OS_TCB        *p_tcb,
                OS_TASK_PTR   p_task,
void          *p_arg,
                OS_PRIO       prio,			//(1)
                CPU_STK       *p_stk_base,
                CPU_STK_SIZE  stk_size,
                OS_ERR        *p_err)
{
    CPU_STK       *p_sp;
    CPU_SR_ALLOC();			//(2)

    /* 初始化TCB为默认值 */
    OS_TaskInitTCB(p_tcb);			//(3)

    /* 初始化栈 */
    p_sp = OSTaskStkInit( p_task,
                        p_arg,
                        p_stk_base,
                        stk_size );

    p_tcb->Prio = prio;			//(4)

    p_tcb->StkPtr = p_sp;
    p_tcb->StkSize = stk_size;

    /* 进入临界段 */
    OS_CRITICAL_ENTER();			//(5)

    /* 将任务添加到就绪列表 */			//(6)
    OS_PrioInsert(p_tcb->Prio);
    OS_RdyListInsertTail(p_tcb);

    /* 退出临界段 */
    OS_CRITICAL_EXIT();			//(7)

    *p_err = OS_ERR_NONE;
}
  • (1):在函数形参中,加入优先级字段。任务的优先级由用户在创建任务的时候通过形参Prio传进来。
  • (2):定义一个局部变量,用来存CPU关中断前的中断状态,因为接下来将任务添加到就绪列表这段代码属于临界短代码,需要关中断。
  • (3):初始化TCB为默认值,其实就是全部初始化为0OS_TaskInitTCB()函数在os_task.c的开头定义
void  OS_TaskInitTCB (OS_TCB  *p_tcb)
{
    p_tcb->StkPtr             = (CPU_STK       *)0;
    p_tcb->StkSize            = (CPU_STK_SIZE   )0u;

    p_tcb->TaskDelayTicks     = (OS_TICK       )0u;

    p_tcb->Prio               = (OS_PRIO        )OS_PRIO_INIT;
    //OS_PRIO_INIT是任务TCB初始化的时候给的默认的一个优先级,宏展开等于OS_CFG_PRIO_MAX, 这是一个不会被OS使用到的优先级。
    //OS_PRIO_INIT具体在os.h中定义。

    p_tcb->NextPtr            = (OS_TCB        *)0;
    p_tcb->PrevPtr            = (OS_TCB        *)0;
}
  • (4):将形参传进来的优先级存到任务控制块TCB的优先级字段。
  • (5):进入临界段。
  • (6):将任务插入就绪列表,这里需要分成两步来实现:
    1、根据优先级置位优先级表中的相应位置;
    2、将任务TCB放到OSRdyList[优先级]中,如果同一个优先级有多个任务,那么这些任务的TCB就会被放到OSRdyList[优先级]串成一个双向链表。
  • (7):退出临界段。

5、修改OS_IdleTaskInit()函数

修改OS_IdleTaskInit()函数,是因为该函数调用了任务创建函数OSTaskCreate()OSTaskCreate()我们刚刚加入了优先级, 所以这里我们要跟空闲任务分配一个优先级

/* 空闲任务初始化 */
void  OS_IdleTaskInit(OS_ERR  *p_err)
{
    /* 初始化空闲任务计数器 */
    OSIdleTaskCtr = (OS_IDLE_CTR)0;

    /* 创建空闲任务 */
    OSTaskCreate( (OS_TCB     *)&OSIdleTaskTCB,
                (OS_TASK_PTR )OS_IdleTask,
                (void       *)0,
                (OS_PRIO)(OS_CFG_PRIO_MAX - 1u),(1)
                (CPU_STK    *)OSCfg_IdleTaskStkBasePtr,
                (CPU_STK_SIZE)OSCfg_IdleTaskStkSize,
                (OS_ERR     *)p_err );
}

空闲任务是μC/OS-III的内部任务,在OSInit()中被创建,在系统没有任何用户任务运行的情况下, 空闲任务就会被运行,优先级最低,即等于OS_CFG_PRIO_MAX- 1u

6、修改OSStart()函数

加入优先级之后,OSStart()函数需要修改,具体哪一个任务最先运行,由优先级决定

/* 启动RTOS,将不再返回 */
void OSStart (OS_ERR *p_err)
{
if ( OSRunning == OS_STATE_OS_STOPPED ) {
#if 0
        /* 手动配置任务1先运行 */
        OSTCBHighRdyPtr = OSRdyList[0].HeadPtr;
#endif
        /* 寻找最高的优先级 */
        OSPrioHighRdy   = OS_PrioGetHighest();(1)
        OSPrioCur       = OSPrioHighRdy;

        /* 找到最高优先级的TCB */
        OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;(2)
        OSTCBCurPtr     = OSTCBHighRdyPtr;

        /* 标记OS开始运行 */
        OSRunning       = OS_STATE_OS_RUNNING;

        /* 启动任务切换,不会返回 */
        OSStartHighRdy();

        /* 不会运行到这里,运行到这里表示发生了致命的错误 */
        *p_err = OS_ERR_FATAL_RETURN;
    } else {
        *p_err = OS_STATE_OS_RUNNING;
    }
}
  • (1):调取OS_PrioGetHighest()函数从全局变量优先级表OSPrioTbl[]获取最高的优先级, 放到OSPrioHighRdy这个全局变量中, 然后把OSPrioHighRdy的值再赋给当前优先级OSPrioCur这个全局变量。在任务切换的时候需要用到OSPrioHighRdyOSPrioCur这两个全局变量。
  • (2):根据OSPrioHighRdy的值, 作为全局变量OSRdyList[]的下标索引找到最高优先级任务的TCB,传给全局变量OSTCBHighRdyPtr, 然后再将OSTCBHighRdyPtr赋值给OSTCBCurPtr。在任务切换的时候需要使用到OSTCBHighRdyPtrOSTCBCurPtr这两个全局变量。

7、修改PendSV_Handler()函数

PendSV_Handler()函数中添加了优先级相关的代码。
有关PendSV_Handler()这个函数的具体讲解要参考《任务切换》这个章节,这里不再赘述。

;*******************************************************************
;                          PendSVHandler异常
;*******************************************************************

OS_CPU_PendSVHandler_nosave

; OSPrioCur   = OSPrioHighRdy
    LDR     R0, =OSPrioCur
    LDR     R1, =OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]

; OSTCBCurPtr = OSTCBHighRdyPtr
LDR     R0, = OSTCBCurPtr
LDR     R1, = OSTCBHighRdyPtr
LDR     R2, [R1]
STR     R2, [R0]

LDR     R0, [R2]
LDMIA   R0!, {R4-R11}

MSR     PSP, R0
ORR     LR, LR, #0x04
CPSIE   I
BX      LR


NOP

ENDP

8、修改OSTimeDly()函数

任务调用OSTimeDly()函数之后,任务就处于阻塞态,需要将任务从就绪列表中移除

/* 阻塞延时 */
void  OSTimeDly(OS_TICK dly)
{
#if 0
    /* 设置延时时间 */
    OSTCBCurPtr->TaskDelayTicks = dly;

    /* 进行任务调度 */
    OSSched();
#endif

    CPU_SR_ALLOC();		//(1)

    /* 进入临界区 */
    OS_CRITICAL_ENTER();		//(2)

    /* 设置延时时间 */
    OSTCBCurPtr->TaskDelayTicks = dly;

    /* 从就绪列表中移除 */
    //OS_RdyListRemove(OSTCBCurPtr);
    OS_PrioRemove(OSTCBCurPtr->Prio);		//(3)

    /* 退出临界区 */
    OS_CRITICAL_EXIT();		//(4)

    /* 任务调度 */
    OSSched();
}
  • (1):定义一个局部变量,用来存CPU关中断前的中断状态,因为接下来将任务从就绪列表移除这段代码属于临界短代码,需要关中断。
  • (2):进入临界段
  • (3):将任务从就绪列表移除, 这里只需将任务在优先级表中对应的位清除即可,暂时不需要把任务TCB从OSRdyList[]中移除, 因为接下来OSTimeTick()函数还是通过扫描OSRdyList[]来判断任务的延时时间是否到期。当我们加入了时基列表之后, 当任务调用OSTimeDly()函数进行延时,就可以把任务的TCB从就绪列表删除,然后把任务TCB插入时基列表, OSTimeTick()函数判断任务的延时是否到期只需通过扫描时基列表即可,时基列表在下一个章节实现。 所以这里暂时不能把TCB从就绪列表中删除,只是将任务优先级在优先级表中对应的位清除来达到任务不处于就绪态的目的。
  • (4):退出临界段。

9、修改OSSched()函数

任务调度函数OSSched()不再是之前的两个任务轮流切换,需要根据优先级来调度, 被迭代的代码已经通过条件编译屏蔽。

void OSSched(void)
{
#if 0
    /* 如果当前任务是空闲任务,那么就去尝试执行任务1或者任务2,
    看看他们的延时时间是否结束,如果任务的延时时间均没有到期,
    那就返回继续执行空闲任务 */
    if ( OSTCBCurPtr == &OSIdleTaskTCB )
    {
        if (OSRdyList[0].HeadPtr->TaskDelayTicks == 0)
        {
            OSTCBHighRdyPtr = OSRdyList[0].HeadPtr;
        }
        else if (OSRdyList[1].HeadPtr->TaskDelayTicks == 0)
        {
            OSTCBHighRdyPtr = OSRdyList[1].HeadPtr;
        }
        else
        {
            return;   /* 任务延时均没有到期则返回,继续执行空闲任务 */
        }
    }
    else
    {
        /*如果是task1或者task2的话,检查下另外一个任务,
        如果另外的任务不在延时中,就切换到该任务,
        否则,判断下当前任务是否应该进入延时状态,
        如果是的话,就切换到空闲任务。否则就不进行任何切换 */
        if (OSTCBCurPtr == OSRdyList[0].HeadPtr)
        {
            if (OSRdyList[1].HeadPtr->TaskDelayTicks == 0)
            {
                OSTCBHighRdyPtr = OSRdyList[1].HeadPtr;
            } else if (OSTCBCurPtr->TaskDelayTicks != 0) {
                OSTCBHighRdyPtr = &OSIdleTaskTCB;
            } else {
            /* 返回,不进行切换,因为两个任务都处于延时中 */
            return;
            }
        }
        else if (OSTCBCurPtr == OSRdyList[1].HeadPtr)
        {
            if (OSRdyList[0].HeadPtr->TaskDelayTicks == 0)
            {
                OSTCBHighRdyPtr = OSRdyList[0].HeadPtr;
            }
            else if (OSTCBCurPtr->TaskDelayTicks != 0)
            {
                OSTCBHighRdyPtr = &OSIdleTaskTCB;
            }
            else
            {
                /* 返回,不进行切换,因为两个任务都处于延时中 */
                return;
            }
        }
    }

    /* 任务切换 */
    OS_TASK_SW();
#endif

    CPU_SR_ALLOC();		//(1)

    /* 进入临界区 */
    OS_CRITICAL_ENTER();		//(2)

    /* 查找最高优先级的任务 */		//(3)
    OSPrioHighRdy   = OS_PrioGetHighest();
    OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;

    /* 如果最高优先级的任务是当前任务则直接返回,不进行任务切换 */		//(4)
    if (OSTCBHighRdyPtr == OSTCBCurPtr)
    {
        /* 退出临界区 */
        OS_CRITICAL_EXIT();

        return;
    }
    /* 退出临界区 */
    OS_CRITICAL_EXIT();		//(5)

    /* 任务切换 */
    OS_TASK_SW();		//(6)
}
  • (1):定义一个局部变量,用来存CPU关中断前的中断状态,因为接下来查找最高优先级这段代码属于临界短代码,需要关中断。
  • (2):进入临界段。
  • (3):查找最高优先级任务。
  • (4):判断最高优先级任务是不是当前任务,如果是则直接返回,否则将继续往下执行,最后执行任务切换。
  • (5):退出临界段。
  • (6):任务切换。

10、修改OSTimeTick()函数

OSTimeTick()函数在SysTick中断服务函数中被调用,是一个周期函数,具体用于扫描就绪列表OSRdyList[], 判断任务的延时时间是否到期,如果到期则将任务在优先级表中对应的位置位, 被迭代的代码则通过条件编译屏蔽。

void  OSTimeTick (void)
{
    unsigned int i;
    CPU_SR_ALLOC();		//(1)

    /* 进入临界区 */
    OS_CRITICAL_ENTER();		//(2)

/* 扫描就绪列表中所有任务的TaskDelayTicks,如果不为0,则减1 */
#if 0
    for (i=0; i<OS_CFG_PRIO_MAX; i++)
    {
        if (OSRdyList[i].HeadPtr->TaskDelayTicks > 0)
        {
            OSRdyList[i].HeadPtr->TaskDelayTicks --;
        }
    }
#endif

    for (i=0; i<OS_CFG_PRIO_MAX; i++) 		//(3)
    {
        if (OSRdyList[i].HeadPtr->TaskDelayTicks > 0)
        {
            OSRdyList[i].HeadPtr->TaskDelayTicks --;
            if (OSRdyList[i].HeadPtr->TaskDelayTicks == 0)
            {
                /* 为0则表示延时时间到,让任务就绪 */
                //OS_RdyListInsert (OSRdyList[i].HeadPtr);
                OS_PrioInsert(i);
            }
        }
    }

    /* 退出临界区 */
    OS_CRITICAL_EXIT();		//(4)

    /* 任务调度 */
    OSSched();
}
  • (1):定义一个局部变量,用来存CPU关中断前的中断状态, 因为接下来扫描就绪列表OSRdyList[]这段代码属于临界短代码,需要关中断。
  • (2):进入临界段。
  • (3):扫描就绪列表OSRdyList[],判断任务的延时时间是否到期, 如果到期则将任务在优先级表中对应的位置位。
  • (4):退出临界段。

二十六、UCOSIII:修改main()函数

1、修改部分:

在这里插入图片描述

/*
*******************************************************************
*                             全局变量
*******************************************************************
*/

uint32_t flag1;
uint32_t flag2;
uint32_t flag3;

/*
*******************************************************************
*                        TCB & STACK &任务声明
*******************************************************************
*/
#define  TASK1_STK_SIZE       128
#define  TASK2_STK_SIZE       128
#define  TASK3_STK_SIZE       128


static   OS_TCB    Task1TCB;
static   OS_TCB    Task2TCB;
static   OS_TCB    Task3TCB;


static   CPU_STK   Task1Stk[TASK1_STK_SIZE];
static   CPU_STK   Task2Stk[TASK2_STK_SIZE];
static   CPU_STK   Task3Stk[TASK2_STK_SIZE];


void     Task1( void *p_arg );
void     Task2( void *p_arg );
void     Task3( void *p_arg );


/*
*******************************************************************
*                             函数声明
*******************************************************************
*/
void delay(uint32_t count);

/*
*******************************************************************
*                             main()函数
*******************************************************************
*/
/*
* 注意事项:1、该工程使用软件仿真,debug需选择 Ude Simulator
*           2、在Target选项卡里面把晶振Xtal(Mhz)的值改为25,默认是12,
*              改成25是为了跟system_ARMCM3.c中定义的__SYSTEM_CLOCK相同,
*              确保仿真的时候时钟一致
*/
int main(void)
{
    OS_ERR err;


    /* CPU初始化:1、初始化时间戳 */
    CPU_Init();

    /* 关闭中断 */
    CPU_IntDis();

    /* 配置SysTick 10ms 中断一次 */
    OS_CPU_SysTickInit (10);

    /* 初始化相关的全局变量 */
    OSInit(&err);		//(1)

    /* 创建任务 */
    OSTaskCreate( (OS_TCB*)&Task1TCB,
                (OS_TASK_PTR )Task1,
                (void *)0,
                (OS_PRIO)1,		//(2)
                (CPU_STK*)&Task1Stk[0],
                (CPU_STK_SIZE)  TASK1_STK_SIZE,
                (OS_ERR *)&err );

    OSTaskCreate( (OS_TCB*)&Task2TCB,
                (OS_TASK_PTR )Task2,
                (void *)0,
                (OS_PRIO)2,		//(3)
                (CPU_STK*)&Task2Stk[0],
                (CPU_STK_SIZE)  TASK2_STK_SIZE,
                (OS_ERR *)&err );

    OSTaskCreate( (OS_TCB*)&Task3TCB,
                (OS_TASK_PTR )Task3,
                (void *)0,
                (OS_PRIO)3,		//(4)
                (CPU_STK*)&Task3Stk[0],
                (CPU_STK_SIZE)  TASK3_STK_SIZE,
                (OS_ERR *)&err );
#if 0
/* 将任务加入到就绪列表 */		//(5)
    OSRdyList[0].HeadPtr = &Task1TCB;
    OSRdyList[1].HeadPtr = &Task2TCB;
#endif

    /* 启动OS,将不再返回 */
    OSStart(&err);
}

/*
*******************************************************************
*                              函数实现
*******************************************************************
*/
/* 软件延时 */
void delay (uint32_t count)
{
    for (; count!=0; count--);
}



void Task1( void *p_arg )
{
    for ( ;; ) {
        flag1 = 1;
        OSTimeDly(2);
        flag1 = 0;
        OSTimeDly(2);
    }
}

void Task2( void *p_arg )
{
    for ( ;; ) {
        flag2 = 1;
        OSTimeDly(2);
        flag2 = 0;
        OSTimeDly(2);
    }
}

void Task3( void *p_arg )
{
    for ( ;; ) {
        flag3 = 1;
        OSTimeDly(2);
        flag3 = 0;
        OSTimeDly(2);
    }
}
  • (1):加入了优先级相关的全局变量OSPrioCurOSPrioHighRdy的初始化。
  • (2)、(3)和(4):为每个任务分配了优先级,任务1的优先级为1,任务2的优先级为2,任务3的优先级为3
  • (5):将任务插入就绪列表这部分功能由OSTaskCreate()实现,这里通过条件编译屏蔽掉。

2、实验现象

进入软件调试,全速运行程序,从逻辑分析仪中可以看到三个任务的波形是完全同步,就好像CPU在同时干三件事情
在这里插入图片描述

任务开始的启动过程具体见图
在这里插入图片描述
上图是任务1、2和3刚开始启动时的软件仿真波形图,系统从启动到任务1开始运行前花的时间为TIME1, 等于0.26MS

任务1开始运行,然后调用OSTimeDly(1)进入延时,随后进行任务切换,切换到任务2开始运行, 从任务1切换到任务2花费的时间等于TIME2-TIME1,等于0.01MS
任务2开始运行,然后调用OSTimeDly(1)进入延时, 随后进行任务切换,切换到任务3开始运行,从任务2切换到任务3花费的时间等于TIME3-TIME1,等于0.01MS
任务3开始运行,然后调用OSTimeDly(1)进入延时,随后进行任务切换,这个时候我们创建的3个任务都处于延时状态, 那么系统就切换到空闲任务,在三个任务延时未到期之前,系统一直都是在运行空闲任务。

当第一个SysTick中断产生, 中断服务函数会调用OSTimeTick()函数扫描每个任务的延时是否到期,因为是延时1个SysTick周期, 所以第一个SysTick中断产生就意味着延时都到期,任务1、2和3依次进入就绪态,再次回到任务本身接着运行, 将自身的Flag清零,然后任务1、2和3又依次调用OSTimeDly(1)进入延时状态,直到下一个SysTick中断产生前, 系统都处在空闲任务中,一直这样循环下去。

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

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

相关文章

私域营销必看:构建超高回复率和超低删除率的私信交流体系

最近&#xff0c;收到了一位做私域运营的朋友的咨询&#xff0c;他困惑地问我&#xff1a;“为什么我每天给我的企微用户发送群发信息&#xff0c;但回复率却极低&#xff0c;而且删好友率还特别高呢&#xff1f;” 我回应他&#xff1a;“你有没有想过&#xff0c;问题的关键…

C/C++程序设计实验报告2 | 循环结构实验

本文整理自博主学校大一&#xff08;2021级&#xff09;C/C专业课的课程实验报告&#xff0c;适合学弟妹或C语言初学者入门C语言学习、练习。 编译器&#xff1a;gcc 10.3.0 ---- 注&#xff1a; 1.虽然课程名为C程序设计&#xff0c;但实际上当时校内该课的内容大部分其实都是…

idea中操作Git将本地仓库代码完整提交到Gittee中

文章目录 1.在idea中打开你的项目根目录&#xff0c; idea中vcs -> create Git Repository2.选中你的项目所在的目录3. git commit -m"你的备注"4. 直接强制本地仓库覆盖远程仓库的东西5.或者直接使用git 进行这个操作 1.在idea中打开你的项目根目录&#xff0c; …

3d场景重建图像渲染 | 神经辐射场NeRF(Neural Radiance Fields)

神经辐射场NeRF&#xff08;Neural Radiance Fields&#xff09; 概念 NeRF&#xff08;Neural Radiance Fields&#xff0c;神经辐射场&#xff09;是一种用于3D场景重建和图像渲染的深度学习方法。它由Ben Mildenhall等人在2020年的论文《NeRF: Representing Scenes as Neur…

BI数据分析案例详解:零售人货场分析该怎么做?

在当今快节奏、高竞争的商业环境中&#xff0c;人货场分析已成为企业成功的关键因素之一。科技的进步和数据的日益丰富使得企业对人流、货物流和场地布局的深入洞察变得愈发重要。通过科学的人货场分析&#xff0c;企业能更好地理解顾客行为、优化供应链、提高运营效率&#xf…

wpscan专门针对wordpress的安全扫描工具

说明 WPScan是一款专门针对WordPress的漏洞扫描工具&#xff0c;它使用Ruby编程语言编写。WPScan能够扫描WordPress网站中的多种安全漏洞&#xff0c;包括WordPress本身的漏洞、插件漏洞和主题漏洞。此外&#xff0c;WPScan还能扫描类似robots.txt这样的敏感文件&#xff0c;并…

Python打印输出Linux中最常用的linux命令之示例

一、Linux中的~/.bash_history文件说明&#xff1a; 该文件保存了linux系统中运行过的命令的历史。使用该文件来获取命令的列表&#xff0c;并统计命令的执行次数。统计时&#xff0c;只统计命令的名称&#xff0c;以不同参数调用相同的命令也视为同一命令。 二、示例代码&am…

什么是token?token是用来干嘛的?

相信很多从事计算机行业的朋友都听说过token这么个东西&#xff0c;但是其他行业的人就很少了解到token&#xff0c;下面就给大家来详细介绍一下token是什么意思&#xff1f;token是用来干嘛的这一块的内容&#xff0c;希望能帮助到大家。 &#x1f3fb; token是什么意思 作为…

matplotlib-散点图

日期&#xff1a;2024.03.14 内容&#xff1a;将matplotlib的常用方法做一个记录&#xff0c;方便后续查找。 # 引入需要使用的库 from matplotlib import pyplot as plt# 设置画布大小 plt.figure(figsize(20,8),dpi 300)# 全局设置中文字体 plt.rcParams[font.sans-serif]…

DHCP中继实验(思科)

华为设备参考&#xff1a;DHCP中继实验&#xff08;华为&#xff09; 一&#xff0c;技术简介 DHCP中继&#xff0c;可以实现在不同子网和物理网段之间处理和转发DHCP信息的功能。如果DHCP客户机与DHCP服务器在同一个物理网段&#xff0c;则客户机可以正确地获得动态分配的IP…

L2-009 抢红包(Java)

没有人没抢过红包吧…… 这里给出N个人之间互相发红包、抢红包的记录&#xff0c;请你统计一下他们抢红包的收获。 输入格式 输入第一行给出一个正整数N&#xff08;≤104&#xff09;&#xff0c;即参与发红包和抢红包的总人数&#xff0c;则这些人从1到N编号。随后N行&…

决策树 | 分类树回归树:算法逻辑

目录 一. 决策树(Decision Tree)1. 决策树的构建1.1 信息熵(Entropy)1.1.1 信息量&信息熵 定义1.1.2 高信息熵&低信息熵 定义1.1.3 信息熵 公式 1.2 信息增益(Information Gain)1.2.1 信息增益的计算1.2.2 小节 2. 小节2.1 算法分类2.2 决策树算法分割选择2.3 决策树算…

【2024 R1 版本更新】Ansys Fluent(下)

Ansys2024R1来了&#xff0c;小宇赶紧将新功能给大家汇报一下。GPU求解器功能势头最强&#xff0c;pyFluent又开始迭代了&#xff0c;CPU模型中又更新了很多功能&#xff0c;fluent meshing中的thin volume mesh功能也来了。

【2024 R1 版本更新】Ansys Fluent(上)

​​Ansys2024R1来了&#xff0c;小宇赶紧将新功能给大家汇报一下。GPU求解器功能势头最强&#xff0c;pyFluent又开始迭代了&#xff0c;CPU模型中又更新了很多功能&#xff0c;fluent meshing中的thin volume mesh功能也来了。

C++函数 加括号与不加括号

很多时候&#xff0c;我们会看到一些在创建对象时有的加括号有的不加括号 那么&#xff0c;这是什么情况呢&#xff1f; 总结&#xff1a;函数需要加上括号&#xff0c;加上括号会对函数初始化&#xff0c;不加括号可能导致未知错误 我们来验证一下。 1.基本数据类型不带括…

Linux编程4.4 网络编程-通信架构

TCP客户端服务器编程模型 1、客户端调用序列 调用socket函数创建套接字调用connect连接服务器端调用I/O函数&#xff08;read/write&#xff09;与服务器端通讯调用close关闭套接字 2、服务器端调用序列 调用socket函数创建套接字调用bind绑定本地地址和端口调用listen启动…

阿里云国际放行DDoS高防回源IP

如果源站服务器上设置了IP白名单访问控制&#xff08;如安全软件、安全组&#xff09;&#xff0c;由于设置了DDoS高防后&#xff0c;回源IP是高防回源IP段&#xff0c;您需要将DDoS高防的回源IP段的地址加入安全软件和安全组的白名单中&#xff0c;避免DDoS高防的回源流量被误…

ElasticSearch之Nested对象

写在前面 本文看下es的nested嵌套对象相关内容。 1&#xff1a;es用了啥范式&#xff1f; 在关系型数据库中定义了6大数据库范式,即1&#xff0c;2&#xff0c;3&#xff0c;BC&#xff0c;4&#xff0c;5的NF&#xff08;normal form&#xff09;,分别如下&#xff1a; 1N…

每一位教师都应该学会的“夸夸术”

在教育领域&#xff0c;我们常常强调正面教育和激励教育的重要性。这其中&#xff0c;教师们的“夸夸术”——也就是赞美和表扬学生的技巧——无疑是极为关键的一环。掌握并运用好“夸夸术”&#xff0c;不仅可以激发学生的学习兴趣和自信心&#xff0c;还能培养他们积极向上的…

武汉星起航:秉承客户至上服务理念,为创业者打造坚实后盾

在跨境电商的激荡浪潮中&#xff0c;武汉星起航电子商务有限公司一直秉持着以客户为中心的发展理念&#xff0c;为跨境创业者提供了独特的支持和经验积累&#xff0c;公司通过多年的探索和实践&#xff0c;成功塑造了一个以卖家需求为导向的服务平台&#xff0c;为每一位创业者…