《FreeRTOS任务删除篇》

任务删除函数

  • 源码
  • 1. 进入临界区
    • 1.1 第一步
    • 1.2 第二步
    • 1.3 第三步
    • 1.4 第四步
  • 2. 获取待删除任务的任务控制块TCB
  • 3. 从就绪/延迟列表中删除任务
  • 4. 从事件列表中删除任务
  • 5. 如果待删除任务是当前运行的任务
  • 6. 如果待删除任务是其它任务
  • 7. 退出临界区
    • 7.1 第一步
    • 7.2 第二步
    • 7.3 第三步
    • 7.4 第四步
  • 8. 如果待删除的任务不是当前运行的任务
  • 9. 如果待删除的任务不是当前运行的任务

  1. 介绍FreeRTOS任务删除函数的执行过程,逐行分析源代码。
  2. 要使用任务删除函数vTaskDelete,需要配置宏INCLUDE_vTaskDelete为1。
  3. 删除任务函数vTaskDelete的参数为待删除任务的任务句柄(即任务控制块)。
  4. 当函数参数为NULL时,代表删除的是调用函数的任务本身(即正在运行的任务)。

源码

/* 示例,在正在运行的任务中调用任务删除函数。*/
vTaskDelete(NULL); 
/* 任务删除 */
#if ( INCLUDE_vTaskDelete == 1 ) /* 需要INCLUDE_vTaskDelete宏配置为1 */void vTaskDelete( TaskHandle_t xTaskToDelete ) /* 函数参数为待删除任务的任务句柄,可以用NULL代替当前任务句柄。 */{TCB_t * pxTCB;taskENTER_CRITICAL(); /* 进入临界区,本质是关闭全局中断。 */{/* If null is passed in here then it is the calling task that is* being deleted.* 如果在此处传递NULL,则删除的是调用函数的任务本身。*/pxTCB = prvGetTCBFromHandle( xTaskToDelete );/* Remove task from the ready/delayed list.* 从就绪/延迟列表中删除任务* 如果删除后列表中没有列表项,则uxListRemove返回0*//* 将任务控制块的成员状态列表项xStateListItem从列表中移除 */if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ){taskRESET_READY_PRIORITY( pxTCB->uxPriority );}else{mtCOVERAGE_TEST_MARKER();}/* Is the task waiting on an event also?* 任务是否也在等待事件?* 任务控制块的成员xEventListItem是否挂载在其他列表中*/if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ){/* 将事件列表项从等待事件列表中移出 */( void ) uxListRemove( &( pxTCB->xEventListItem ) );}else{mtCOVERAGE_TEST_MARKER();}/* Increment the uxTaskNumber also so kernel aware debuggers can* detect that the task lists need re-generating.  This is done before* portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will* not return.* 同时自增uxTaskNumber,以便内核感知调试器可以检测到任务列表需要重新生成。* 这是在portPRE_TASK_DELETE_HOOK之前完成的,因为在Windows端口中,宏不会返回*/uxTaskNumber++; /* 任务列表需要重新生成 *//* 删除的是调用任务本身时 */if( pxTCB == pxCurrentTCB ){/* A task is deleting itself.  This cannot complete within the* task itself, as a context switch to another task is required.* Place the task in the termination list.  The idle task will* check the termination list and free up any memory allocated by* the scheduler for the TCB and stack of the deleted task.* 一个任务正在删除自己。* 这无法在任务本身内完成,因为需要切换到另一个任务的上下文。* 将任务放入等待结束列表中。* 空闲任务将检查等待结束列表,并释放调度器为准备删除任务分配的TCB和堆栈内存。*/vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );/* Increment the ucTasksDeleted variable so the idle task knows* there is a task that has been deleted and that it should therefore* check the xTasksWaitingTermination list.* 递增ucTasksDeleted变量,以便空闲任务知道有一个任务已被删除,* 因此它应该检查xTasksWaitingTermination列表。*/++uxDeletedTasksWaitingCleanUp;/* Call the delete hook before portPRE_TASK_DELETE_HOOK() as* portPRE_TASK_DELETE_HOOK() does not return in the Win32 port.* 在调用portPRE_TASK_delete_hook之前调用delete钩子,* 因为portPRE_TAS K_delete_ hook在Win32端口中不返回。*/traceTASK_DELETE( pxTCB );/* The pre-delete hook is primarily for the Windows simulator,* in which Windows specific clean up operations are performed,* after which it is not possible to yield away from this task -* hence xYieldPending is used to latch that a context switch is* required.* 预删除挂钩主要用于Windows模拟器,* 在该模拟器中执行特定于Windows的清理操作,之后不可能放弃此任务,* 因此xYieldPending用于锁定需要进行上下文切换。*/portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );}else{--uxCurrentNumberOfTasks; /* 当前任务个数自减一 */traceTASK_DELETE( pxTCB );/* Reset the next expected unblock time in case it referred to* the task that has just been deleted.* 重置下一个预期的解锁时间,以防它引用了刚刚被删除的任务*/prvResetNextTaskUnblockTime();}}taskEXIT_CRITICAL(); /* 退出临界区,本质是开启全局中断 *//* If the task is not deleting itself, call prvDeleteTCB from outside of* critical section. If a task deletes itself, prvDeleteTCB is called* from prvCheckTasksWaitingTermination which is called from Idle task.* 如果任务不是删除自己,请从临界区外部调用prvDeleteTCB。* 如果任务删除自己,则从空闲任务调用的prvCheckTasksWaitingTermination中调用prvDeleteTCB删除任务*/if( pxTCB != pxCurrentTCB ){prvDeleteTCB( pxTCB );}/* Force a reschedule if it is the currently running task that has just* been deleted.* 如果删除的是当前正在运行的任务,则强制重新开启一次任务调度*/if( xSchedulerRunning != pdFALSE ) /* 任务调度器正在运行中 */{if( pxTCB == pxCurrentTCB ) /* 删除的是当前正在运行的任务 */{configASSERT( uxSchedulerSuspended == 0 );portYIELD_WITHIN_API();}else{mtCOVERAGE_TEST_MARKER();}}}#endif /* INCLUDE_vTaskDelete */

1. 进入临界区

taskENTER_CRITICAL(); /* 进入临界区,本质是关闭全局中断。 */

1.1 第一步

#define taskENTER_CRITICAL()               portENTER_CRITICAL() /* 从任务中进入临界区 */

1.2 第二步

#define portENTER_CRITICAL()  vPortEnterCritical()

1.3 第三步

void vPortEnterCritical( void )
{portDISABLE_INTERRUPTS();ulCriticalNesting++;
}

1.4 第四步

#define portDISABLE_INTERRUPTS() __asm(" setc INTM") /* 关闭全局中断 */

2. 获取待删除任务的任务控制块TCB

portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL; /* 指向当前运行的任务控制块。 */
/** Several functions take a TaskHandle_t parameter that can optionally be NULL,* where NULL is used to indicate that the handle of the currently executing* task should be used in place of the parameter.  This macro simply checks to* see if the parameter is NULL and returns a pointer to the appropriate TCB.* 有几个函数接受一个TaskHandle_t参数,该参数可以选择设置为NULL,* 其中NULL用于表示使用当前正在执行的任务的句柄来代替该参数。* 此宏只是检查参数是否为NULL,并返回指向相应TCB的指针。*/
#define prvGetTCBFromHandle( pxHandle )    ( ( ( pxHandle ) == NULL ) ? pxCurrentTCB : ( pxHandle ) )

3. 从就绪/延迟列表中删除任务

/* Remove task from the ready/delayed list.* 从就绪/延迟列表中删除任务* 如果删除后列表中没有列表项,则返回0*/
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
{taskRESET_READY_PRIORITY( pxTCB->uxPriority );
}
else
{mtCOVERAGE_TEST_MARKER();
}
/* 从列表中移除待移除的列表项 */
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{/* The list item knows which list it is in.  Obtain the list from the list* item.* 从列表项的成员pxContainer可以知道它在哪个列表中。从列表项中获取列表。* */List_t * const pxList = pxItemToRemove->pxContainer;/* 将列表项从列表中移除 */pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;/* Only used during decision coverage testing.* 仅在决策覆盖率测试期间使用。*/mtCOVERAGE_TEST_DELAY();/* Make sure the index is left pointing to a valid item.* 确保索引指向有效项*/if( pxList->pxIndex == pxItemToRemove ) /* 如果列表的列表索引号指向待移除的列表项 */{pxList->pxIndex = pxItemToRemove->pxPrevious; /* 将索引号指向待移除列表项的前一个列表项 */}else{mtCOVERAGE_TEST_MARKER();}pxItemToRemove->pxContainer = NULL; /* 将待删除列表项的成员pxContainer设置为NULL,表示其不属于任何列表 */( pxList->uxNumberOfItems )--; /* 列表的列表项个数减一 */return pxList->uxNumberOfItems; /* 返回列表中剩余的列表项个数 */
}

4. 从事件列表中删除任务

/* Is the task waiting on an event also?* 任务是否也在等待事件?* 任务控制块的成员xEventListItem是否挂载在其他列表中*/
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
{/* 将事件列表项从等待事件列表中移出 */( void ) uxListRemove( &( pxTCB->xEventListItem ) );
}
else
{mtCOVERAGE_TEST_MARKER();
}
/** Return the list a list item is contained within (referenced from).* 返回列表项所挂载的列表** @param pxListItem The list item being queried. pxListItem表示正在查询的列表项。* @return A pointer to the List_t object that references the pxListItem.  指向挂载pxListItem的List_t对象的指针*/
#define listLIST_ITEM_CONTAINER( pxListItem )            ( ( pxListItem )->pxContainer )

5. 如果待删除任务是当前运行的任务

  1. 将列表项xStateListItem按尾部插入法挂载到xTasksWaitingTermination列表中
  2. 变量uxDeletedTasksWaitingCleanUp自增一,以供空闲任务使用。
/* 删除的是调用任务本身时 */
if( pxTCB == pxCurrentTCB )
{/* A task is deleting itself.  This cannot complete within the* task itself, as a context switch to another task is required.* Place the task in the termination list.  The idle task will* check the termination list and free up any memory allocated by* the scheduler for the TCB and stack of the deleted task.* 一个任务正在删除自己。* 这无法在当前任务执行内部完成,因为还需要切换到另一个任务的上下文。* 因此将待删除任务放入等待结束任务列表中。* 空闲任务将检查等待结束任务列表,并释放调度器为待删除任务分配的TCB和堆栈内存。*/vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );/* Increment the ucTasksDeleted variable so the idle task knows* there is a task that has been deleted and that it should therefore* check the xTasksWaitingTermination list.* 递增ucTasksDeleted变量,以便空闲任务知道有一个任务已被删除,* 因此它应该检查xTasksWaitingTermination列表。* */++uxDeletedTasksWaitingCleanUp;/* Call the delete hook before portPRE_TASK_DELETE_HOOK() as* portPRE_TASK_DELETE_HOOK() does not return in the Win32 port.* 在调用portPRE_TASK_delete_hook之前调用delete钩子,* 因为portPRE_TAS K_delete_ hook在Win32端口中不返回。* */traceTASK_DELETE( pxTCB );/* The pre-delete hook is primarily for the Windows simulator,* in which Windows specific clean up operations are performed,* after which it is not possible to yield away from this task -* hence xYieldPending is used to latch that a context switch is* required.* 预删除挂钩主要用于Windows模拟器,* 在该模拟器中执行特定于Windows的清理操作,之后不可能放弃此任务,* 因此xYieldPending用于锁定需要进行上下文切换。* */portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
}

6. 如果待删除任务是其它任务

--uxCurrentNumberOfTasks; /* 当前任务个数自减一 */
traceTASK_DELETE( pxTCB );/* Reset the next expected unblock time in case it referred to* the task that has just been deleted.* 重置下一个预期的解锁时间,以防它引用了刚刚被删除的任务,即下一个解除等待准备运行的任务就是待删除任务。*/
prvResetNextTaskUnblockTime();
/* 重置下一个任务解锁时间 */
static void prvResetNextTaskUnblockTime( void )
{if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) /* 延迟任务列表是否为空 */{/* The new current delayed list is empty.  Set xNextTaskUnblockTime to* the maximum possible value so it is  extremely unlikely that the* if( xTickCount >= xNextTaskUnblockTime ) test will pass until* there is an item in the delayed list.* 当前新的延迟列表为空。将xNextTaskUnblockTime设置为最大可能值*/xNextTaskUnblockTime = portMAX_DELAY;}else{/* The new current delayed list is not empty, get the value of* the item at the head of the delayed list.  This is the time at* which the task at the head of the delayed list should be removed* from the Blocked state.* 当前新的延迟列表不为空,请获取延迟列表头部项目的值。* 此时,应将延迟列表开头的任务从“阻塞”状态中删除。* 即准备让下一个被阻塞的任务开始执行*/xNextTaskUnblockTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxDelayedTaskList );}
}
/** Access macro to determine if a list contains any items.  The macro will* only have the value true if the list is empty.* 访问宏以确定列表是否包含任何列表项。只有当列表为空时,宏才会具有值true。*/
#define listLIST_IS_EMPTY( pxList ) ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE )
PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. 指向当前正在使用的延迟任务列表*/
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/** Access macro to retrieve the value of the list item at the head of a given list. * 访问宏以检索给定列表开头的列表项的值*/
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList )        ( ( ( pxList )->xListEnd ).pxNext->xItemValue ) /* 末尾列表项的下一个列表项即为头部列表项。 */
PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. 在调度程序启动之前,已初始化为portMAX_DELAY*/

7. 退出临界区

taskEXIT_CRITICAL(); /* 退出临界区,本质是开启全局中断 */

7.1 第一步

#define taskEXIT_CRITICAL()                portEXIT_CRITICAL()

7.2 第二步

#define portEXIT_CRITICAL()   vPortExitCritical()

7.3 第三步

void vPortExitCritical( void )
{ulCriticalNesting--;if( ulCriticalNesting == 0 ){portENABLE_INTERRUPTS();}
}

7.4 第四步

#define portENABLE_INTERRUPTS()   __asm(" clrc INTM") /* 打开全局中断 */

8. 如果待删除的任务不是当前运行的任务

/* If the task is not deleting itself, call prvDeleteTCB from outside of* critical section. If a task deletes itself, prvDeleteTCB is called* from prvCheckTasksWaitingTermination which is called from Idle task.* 如果任务不是删除自己,请从临界区外部调用prvDeleteTCB。* 如果任务删除自己,则从空闲任务调用的prvCheckTasksWaitingTermination中调用prvDeleteTCB删除任务*/
if( pxTCB != pxCurrentTCB )
{prvDeleteTCB( pxTCB );
}
/* 删除任务控制块,根据分配内存的方式释放TCB和堆栈内存 */
#if ( INCLUDE_vTaskDelete == 1 )static void prvDeleteTCB( TCB_t * pxTCB ){/* This call is required specifically for the TriCore port.  It must be* above the vPortFree() calls.  The call is also used by ports/demos that* want to allocate and clean RAM statically.* 此调用是TriCore端口特有的。它必须位于vPortFree调用之上。* 该调用也被希望静态分配和清理RAM的端口/演示使用。* */portCLEAN_UP_TCB( pxTCB );#if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) ){/* Free up the memory allocated for the task's TLS Block. */configDEINIT_TLS_BLOCK( pxCurrentTCB->xTLSBlock );}#endif#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) ){/* The task can only have been allocated dynamically - free both* the stack and TCB.* 该任务只能是被动态分配,需要释放堆栈和TCB* */vPortFreeStack( pxTCB->pxStack );vPortFree( pxTCB );}#elif ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */{/* The task could have been allocated statically or dynamically, so* check what was statically allocated before trying to free the* memory.* 任务可以静态或动态分配,因此在尝试释放内存之前,请检查静态分配的内容* */if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ){/* Both the stack and TCB were allocated dynamically, so both* must be freed.* 堆栈和TCB都是动态分配的,因此必须释放它们。* */vPortFreeStack( pxTCB->pxStack );vPortFree( pxTCB );}else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY ){/* Only the stack was statically allocated, so the TCB is the* only memory that must be freed.* 只有堆栈是静态分配的,因此TCB是唯一必须释放的内存。* */vPortFree( pxTCB );}else{/* Neither the stack nor the TCB were allocated dynamically, so* nothing needs to be freed.* 堆栈和TCB都不是动态分配的,因此不需要释放任何内容* */configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB );mtCOVERAGE_TEST_MARKER();}}#endif /* configSUPPORT_DYNAMIC_ALLOCATION */}#endif /* INCLUDE_vTaskDelete */

9. 如果待删除的任务不是当前运行的任务

/* Force a reschedule if it is the currently running task that has just* been deleted.* 如果删除的是当前正在运行的任务,则强制重新开启一次任务调度*/
if( xSchedulerRunning != pdFALSE ) /* 任务调度器正在运行中 */
{if( pxTCB == pxCurrentTCB ) /* 删除的是当前正在运行的任务 */{configASSERT( uxSchedulerSuspended == 0 );portYIELD_WITHIN_API();}else{mtCOVERAGE_TEST_MARKER();}
}
PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
#ifndef portYIELD_WITHIN_API#define portYIELD_WITHIN_API    portYIELD
#endif
#define portYIELD() do{bYield = 1; __asm(" INTR INT14");}while(0)

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源项目-如何更好的参与开源项目开发

开源之谜-提升自我核心竞争力 一、寻找适合自己的开源项目二、像坐牢一样闭关修炼三、最后的实践 开源代码对所有人开放&#xff0c;开发者可以基于现有代码进行扩展和创新&#xff0c;而不是从零开始&#xff0c;参与开源项目可以提升自我的技术能力&#xff0c;丰富个人的经历…

利用c语言详细介绍下插入排序

插入排序&#xff0c;被称为直接插入排序。它的基本思想是将一个记录插入到已经排好序的有序表中&#xff0c;从而一个新的、记录数增 1 的有序表。 一、图文介绍 我们还是使用数组【10&#xff0c;5&#xff0c;3&#xff0c;20&#xff0c;1]&#xff0c;排序使用升序的方式&…

STL——string类常用接口说明

目录 一、string类的介绍 二、string类常用接口的使用说明 1.成员函数 ​编辑 2.迭代器 3.容量 一、string类的介绍 下面是string类的文档对string类的介绍 1.string类是表示字符序列的对象 2.标准字符串类通过类似于标准字符容器的接口为此类对象提供支持&#xff0c…

Excel的图表使用和导出准备

目的 导出Excel图表是很多软件要求的功能之一&#xff0c;那如何导出Excel图表呢&#xff1f;或者说如何使用Excel图表。 一种方法是软件生成图片&#xff0c;然后把图片写到Excel上&#xff0c;这种方式&#xff0c;因为格式种种原因&#xff0c;导出的图片不漂亮&#xff0c…

2024年亚太地区数学建模大赛A题-复杂场景下水下图像增强技术的研究

复杂场景下水下图像增强技术的研究 对于海洋勘探来说&#xff0c;清晰、高质量的水下图像是深海地形测量和海底资源调查的关键。然而&#xff0c;在复杂的水下环境中&#xff0c;由于光在水中传播过程中的吸收、散射等现象&#xff0c;导致图像质量下降&#xff0c;导致模糊、…

【数据分享】2024年我国省市县三级的住宿服务设施数量(8类住宿设施/Excel/Shp格式)

宾馆酒店、旅馆招待所等住宿服务设施的配置情况是一个城市公共基础设施完善程度的重要体现&#xff0c;一个城市住宿服务设施种类越丰富&#xff0c;数量越多&#xff0c;通常能表示这个城市的公共服务水平越高&#xff01; 本次我们为大家带来的是我国各省份、各地级市、各区…

一文学习Android系统核心服务ServiceManager

ServiceManager 是 Android 系统中核心的系统服务注册与发现机制&#xff0c;它在 Android Framework 层扮演服务注册中心的角色。它允许进程通过它注册、查询和使用系统服务&#xff0c;实现进程间通信 (IPC) 的基础架构。 ServiceManager 的作用 服务注册&#xff1a;应用程…

DMA理论篇

DMA理论篇 简介 传统的数据传输都是需要CPU来实现&#xff0c;从一个地方拷贝到另一个地方&#xff1b;而DMA(Direct Memory Access)则不完全依赖CPU&#xff0c;DMA更新芯片SOC的一个控制器&#xff0c;他可以控制数据从内存中传输到另一个地方(外设、soc其它模块)&#xff…

SpringBoot 集成 html2Pdf

一、概述&#xff1a; 1. springboot如何生成pdf&#xff0c;接口可以预览可以下载 2. vue下载通过bold如何下载 3. 一些细节&#xff1a;页脚、页眉、水印、每一页得样式添加 二、直接上代码【主要是一个记录下次开发更快】 模板位置 1. 导入pom包 <dependency><g…

IDEA怎么定位java类所用maven依赖版本及引用位置

在实际开发中&#xff0c;我们可能会遇到需要搞清楚代码所用依赖版本号及引用位置的场景&#xff0c;便于排查问题&#xff0c;怎么通过IDEA实现呢&#xff1f; 可以在IDEA中打开项目&#xff0c;右键点击maven的pom.xml文件&#xff0c;或者在maven窗口下选中项目&#xff0c;…

webStorm安装

一、webStorm安装 简介 Webstorm是一款非常受欢迎的优秀开发工具&#xff0c;跟vscode同誉为卧龙凤雏编辑器&#xff0c;是97%开发人员的理想编辑器&#xff0c; 尤其是webstorm&#xff0c;焕然一新的外观&#xff0c;新的导航功能&#xff0c;githob拉取等&#xff0c;更是备…

案例研究|阿特斯的JumpServer分布式部署和多组织管理实践

苏州阿特斯阳光电力科技有限公司&#xff08;以下简称为阿特斯&#xff09;是一家集太阳能光伏组件制造和为全球客户提供太阳能应用产品研发、设计、制造、销售的专业公司。 阿特斯集团总部位于加拿大&#xff0c;中国区总部位于江苏省苏州市。通过全球战略和多元化的市场布局…

数字信号处理(Digital Signal Procession)总结

0、导入库 import numpy as np import matplotlib.pyplot as plt import numpy as np from matplotlib import pyplot as plt from scipy.signal import find_peaks1、创建时域信号 创建时间序列 T 0.01 # 采样间隔 fs 100 # 采样频率 L 1000 # 采样点数 tl 0 # 起始时间…

医院信息化与智能化系统(22)

医院信息化与智能化系统(22) 这里只描述对应过程&#xff0c;和可能遇到的问题及解决办法以及对应的参考链接&#xff0c;并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图&#xff0c;可以试试PlantUML&#xff0c;告诉GPT你的文件结构&#xff0c;让他给你对应…

01Web3.0行业

目录 一、什么是Web 3.0? 二、Web 1.0 vs Web 2.0 vs Web 3.0 三、为什么选择Web 3.0 四、从法律角度观察Web 3.0 1. Web 3.0前时代的数字身份 问题1&#xff1a;个人信息的过度收集 问题2&#xff1a;个人信息的泄露和滥用 2. Web 3.0的解决方案及其法律问题 问题一&…

width设置100vh但出现横向滚动条的问题

在去做flex左右固定,中间自适应宽度的布局时, 发现这样一个问题: 就是我明明是宽度占据整个视口, 但是却多出了横向的滚动条 效果是这样的 把width改成100%,就没有滚动条了 原因: body是有默认样式的, 会有一定的默认边距, 把默认边距清除就是正常的了 同时, 如果把高度设…

opencv undefined reference to `cv::noarray()‘ 。window系统配置opencv,找到opencv库,但连接不了

之前都是在ubuntu里用opencv&#xff0c;今天为了方便在平时用Window10系统也用下c版的cv&#xff0c;就想配置一下vscode的cv环境&#xff0c;直接下载了一个编译好的opencv库&#xff08;带build文件夹的&#xff09;&#xff0c;刚开始用的是visual studio的编译器&#xff…

php常用伪协议整理

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理php常见的伪协议 php伪协议介绍 直观点&#xff0c;就是php可以识别的协议。 类似于我们访问网站的http协议&#xff0c;我们用浏览器访问我们自己本地文件的file协议等。 php可以识别这些协议&#xf…

神经网络(系统性学习二):单层神经网络(感知机)

此前篇章&#xff1a; 神经网络中常用的激活函数 神经网络&#xff08;系统性学习一&#xff09;&#xff1a;入门篇 单层神经网络&#xff08;又叫感知机&#xff09; 单层网络是最简单的全连接神经网络&#xff0c;它仅有输入层和输出层&#xff0c;没有隐藏层。即&#x…