劉火良FreeRTOS內核實現與應用學習之6——多優先級

? ? ? ? 在FreeRTOS中,數字優先級越小,邏輯優先級也越小;在任務創建時,會根據任務的優先級將任務插入就緒列表不同的位置。

????????List_t pxReadyTasksLists[ configMAX_PRIORITIES ] 就緒列表是一個數組,數組中存儲的是就緒任務TCB(任務控制塊通過自己的鉤子<TCB中的xStateListItem節點>掛上了List_t)。

? ? ? ? 創建任務時,a. 會根據任務的優先級將任務插入就緒列表數組的不同的位置;

? ? ? ?b.? 相同優先級的任務插入就緒列表數組中的同一條鏈表中。

? ? ? ? 要想任務支持優先級,即只要實現在任務切換(taskYIELD)時,讓pxCurrentTCB指向最高優先級的就緒任務的TCB既可以。

重要數據

0.? 全局TCB指針

/* 當前正在運行的任務的任務控制塊指針,默認初始化為NULL */
TCB_t * volatile pxCurrentTCB = NULL;

要想讓任務支持優先級,即只要實現任務切換(portYIELD)時,讓pxCurrentTCB指向最高優先級的就緒任務的TCB即可。

1. 靜態變量:uxTopReadyPriority

位置:在task.c文件中定義;靜態變量;

static volatile UBaseType_t uxTopReadyPriority ?? ??? ?= tskIDLE_PRIORITY;

表示創建的任務的最高優先級,默認初始化為0,即空閑任務的優先級。

數值越大,優先級越高;

2. 修改任務控制塊:增加一變量

? ? ? ? 增加了一個變量:UBaseType_t?? ??? ??? ?uxPriority;

描述任務塊的優先級。

typedef struct tskTaskControlBlock
{volatile StackType_t    *pxTopOfStack;    /* 棧頂 */ListItem_t			    xStateListItem;   /* 任務節點 */StackType_t             *pxStack;         /* 任務棧起始地址 *//* 任務名稱,字符串形式 */char                    pcTaskName[ configMAX_TASK_NAME_LEN ];TickType_t xTicksToDelay;UBaseType_t			uxPriority;    
} tskTCB;
typedef tskTCB TCB_t;

3. 全局任務數

static volatile UBaseType_t uxCurrentNumberOfTasks ?? ?= ( UBaseType_t ) 0U;

static UBaseType_t uxTaskNumber ?? ??? ??? ??? ??? ?= ( UBaseType_t ) 0U;

此處有一個疑問:這個變量做什么用?

? ? ? ? 查找當前最高優先級的就緒任務,給uxTopReadyPriority 賦值,給pxCurrentTCB賦值,有兩種方法。

兩種方法

? ? ? ? 查找最高優先級的就緒任務有兩種方法,具體由宏configUSE_PORT_OPTIMISED_TASK_SELECTION控制,定義為0選擇通用方法,定義為1選擇根據處理器優化的方法,該宏默認在portmacro.h文件中定義為1,即使用優化過的方法。

#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif

? ? ? 該功能主要是通過四個宏來實現:

????????taskRECORD_READY_PRIORITY( uxPriority )? ?:記錄就緒最高優先級的就緒任務uxTopReadyPriority 賦值;

????????taskSELECT_HIGHEST_PRIORITY_TASK():在任務列表中尋找就緒最高優先級的就緒任務,獲取優先級最高的就緒任務的TCB,然后更新到pxCurrentTCB;

????????taskRESET_READY_PRIORITY( uxPriority )

????????portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )

通用方法

? ? ? ? 在通用方法中實現了上面的宏1、宏2;宏3~4為空。

兩個宏定義

taskRECORD_READY_PRIORITY( uxPriority )? ?

位置:在task.c文件中定義;

實現記錄當前運行任務的優先級,直接得到優先級的序號,并更新到靜態變量 uxTopReadyPriority 中;

	#define taskRECORD_READY_PRIORITY( uxPriority )														\{																									\if( ( uxPriority ) > uxTopReadyPriority )														\{																								\uxTopReadyPriority = ( uxPriority );														\}																								\} /* taskRECORD_READY_PRIORITY */
taskSELECT_HIGHEST_PRIORITY_TASK()

位置:在task.c文件中定義;

	#define taskSELECT_HIGHEST_PRIORITY_TASK()															\{																									\UBaseType_t uxTopPriority = uxTopReadyPriority;														\\/* 尋找包含就緒任務的最高優先級的隊列 */                                                          \while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) )							\{																								\--uxTopPriority;																			\}																								\\/* 獲取優先級最高的就緒任務的TCB,然后更新到pxCurrentTCB */							            \listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );			\/* 更新uxTopReadyPriority */                                                                    \uxTopReadyPriority = uxTopPriority;																\} /* taskSELECT_HIGHEST_PRIORITY_TASK */

1)用于尋找優先級最高的就緒任務、更新靜態變量 uxTopReadyPriority;調用宏:listLIST_IS_EMPTY( pxList )

/* 判斷鏈表是否為空 */
#define listLIST_IS_EMPTY( pxList )	( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) )

此處有一個疑問:鏈表中的變量計數器(uxNumberOfItems)用來做什么用?

/* 鏈表結構體定義 */
typedef struct xLIST
{
?? ?UBaseType_t uxNumberOfItems; ? ?/* 鏈表節點計數器 */
?? ?ListItem_t * ?pxIndex;?? ??? ??? ?/* 鏈表節點索引指針 */
?? ?MiniListItem_t xListEnd;?? ??? ?/* 鏈表最后一個節點 */
} List_t;
?

現在可以回答這個問題了,也就是這列鏈表中節點的個數,當任務的優先級一樣的話,是插到就緒任務鏈表數組的同一位置的,所以同一優先級就緒任務需要計數:uxNumberOfItems
a. 將節點從鏈表中刪除:

UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) 函數會減1;

b. 將節點插入到鏈表的尾部 :void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) 函數中加1;

2)更新全局變量pxCurrentTCB;調用宏:listGET_OWNER_OF_NEXT_ENTRY(..)

/* 獲取鏈表節點的OWNER,即TCB */
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )										\
{																							\List_t * const pxConstList = ( pxList );											    \/* 節點索引指向鏈表第一個節點調整節點索引指針,指向下一個節點,如果當前鏈表有N個節點,當第N次調用該函數時,pxInedex則指向第N個節點 */\( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;							\/* 當前鏈表為空 */                                                                       \if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) )	\{																						\( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;						\}																						\/* 獲取節點的OWNER,即TCB */                                                             \( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;											 \
}

/* 節點結構體定義 */
struct xLIST_ITEM
{
?? ?TickType_t xItemValue; ? ? ? ? ? ? /* 輔助值,用于幫助節點做順序排列 */?? ??? ??? ?
?? ?struct xLIST_ITEM * ?pxNext; ? ? ? /* 指向鏈表下一個節點 */?? ??? ?
?? ?struct xLIST_ITEM * ?pxPrevious; ? /* 指向鏈表前一個節點 */?? ?
?? ?void * pvOwner;?? ??? ??? ??? ??? ? ? /* 指向擁有該節點的內核對象,通常是TCB */
?? ?void * ?pvContainer;?? ??? ? ? ? ? /* 指向該節點所在的鏈表 */
};
typedef struct xLIST_ITEM ListItem_t; ?/* 節點數據類型重定義 */

3)繼續更新靜態變量 uxTopReadyPriority;

優化方法

? ? ? ? Cortex-M 內核有一個計算前導零的指令:CLZ。用于計算一個變量從高位開始第一次出現1的位前面的0的個數。

????????__clz( ( uxReadyPriorities ):

a.?uxReadyPriorities 為32位,每一個位號對應一個任務的優先級,1就緒,反之為0;

b.?32個優先級的任務:?( 31UL - ( uint32_t ) __clz( ( uxReadyPriorities ) ) )表示最高就緒任務的等級;

#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) __clz( ( uxReadyPriorities ) ) )

兩個宏定義

taskRECORD_READY_PRIORITY( uxPriority )

位置:在task.c文件中定義;

#define taskRECORD_READY_PRIORITY( uxPriority )	portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )

里頭又涉及到兩個宏:portRECORD_READY_PRIORITY? ?和 portRESET_READY_PRIORITY

位置:在portmacro.h文件中定義;

a.?portRECORD_READY_PRIORITY 完成功能:任務就緒就把uxReadyPriorities相應的位置1;得到能夠反應就緒的32位的變量uxReadyPriorities;

b.portRESET_READY_PRIORITY 功能相反;

#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1/* 根據優先級設置/清除優先級位圖中相應的位 */#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )/*-----------------------------------------------------------*/#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) __clz( ( uxReadyPriorities ) ) )#endif /* taskRECORD_READY_PRIORITY */
taskSELECT_HIGHEST_PRIORITY_TASK()

位置:在portmacro.h文件中定義;

就是利用前面提到的計算前導零的指令:CLZ 實現,算出就緒最高優先級任務的的級別出來;

#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) __clz( ( uxReadyPriorities ) ) )

從而實現宏:taskSELECT_HIGHEST_PRIORITY_TASK。

	#define taskSELECT_HIGHEST_PRIORITY_TASK()														    \{																								    \UBaseType_t uxTopPriority;																		    \\/* 尋找最高優先級 */								                            \portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );								    \/* 獲取優先級最高的就緒任務的TCB,然后更新到pxCurrentTCB */                                       \listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );		    \} /* taskSELECT_HIGHEST_PRIORITY_TASK() */

有關任務操作重要函數

1. 修改:TaskHandle_t xTaskCreateStatic(...)

1)內部增加了將任務添加到就緒列表的功能:prvAddNewTaskToReadyList;

2)在原本的prvInitialiseNewTask中增加了設置優先級的功能;

prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters,uxPriority, &xReturn, pxNewTCB);

原來的函數,初始化與任務相關的列表,如就緒列表;

static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )

是一個帶參宏,位置:在task.c文件中定義;

static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
{/* 進入臨界段 */taskENTER_CRITICAL();{/* 全局任務計時器加一操作 */uxCurrentNumberOfTasks++;/* 如果pxCurrentTCB為空,則將pxCurrentTCB指向新創建的任務 */if( pxCurrentTCB == NULL ){pxCurrentTCB = pxNewTCB;/* 如果是第一次創建任務,則需要初始化任務相關的列表 */if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 ){/* 初始化任務相關的列表 */prvInitialiseTaskLists();}}else /* 如果pxCurrentTCB不為空,則根據任務的優先級將pxCurrentTCB指向最高優先級任務的TCB */{if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority ){pxCurrentTCB = pxNewTCB;}}uxTaskNumber++;/* 將任務添加到就緒列表 */prvAddTaskToReadyList( pxNewTCB );}/* 退出臨界段 */taskEXIT_CRITICAL();
}

完成如下功能:

a. 初始化任務鏈表(若是第一次):prvInitialiseTaskLists;

b. 把任務加到就緒列表:prvAddTaskToReadyList;

?這個是通過前面的宏 (查找優先級)+ 列表插入函數實現(根據優先級將任務插入就緒列表pxReadyTasksLists[])

prvAddTaskToReadyList( pxNewTCB );

* 將任務添加到就緒列表 */ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
#define prvAddTaskToReadyList( pxTCB )?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ? \
?? ?taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority );?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ? \
?? ?vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) );?

完成
a.?任務控制塊的鉤子(過自己的鉤子<TCB中的xStateListItem節點>掛上了List_t)。);

b. 任務控制塊的容納者是鏈表數組的某一個;

c.該鏈表擁有的任務(控制塊)的數量加一;

2. vTaskStartScheduler()維持不變

完成如下功能:

1)創建空閑任務;

2)啟動任務調度器xPortStartScheduler;

3.修改:void vTaskDelay( const TickType_t xTicksToDelay )

位置:在task.c文件中定義;

void vTaskDelay( const TickType_t xTicksToDelay )
{TCB_t *pxTCB = NULL;/* 獲取當前任務的TCB */pxTCB = pxCurrentTCB;/* 設置延時時間 */pxTCB->xTicksToDelay = xTicksToDelay;/* 將任務從就緒列表移除 *///uxListRemove( &( pxTCB->xStateListItem ) );taskRESET_READY_PRIORITY( pxTCB->uxPriority );/* 任務切換 */taskYIELD();
}

此處的修改注意,以前是從任務列表中移除:uxListRemove( &( pxTCB->xStateListItem ) );

現在是通過函數(宏):taskRESET_READY_PRIORITY( pxTCB->uxPriority ) ;實現復位變量uxReadyPriorities相對于的位;

然后是調用任務切換taskYIELD,觸發中斷:vTaskSwitchContext;

4. 修改:void vTaskSwitchContext( void )

任務切換,即尋找優先級最高的就緒任務;

利用宏自動尋找優先級最高的就緒任務的TCB,然后更新到全局變量任務控制塊指針pxCurrentTCB中;

/* 任務切換,即尋找優先級最高的就緒任務 */
void vTaskSwitchContext( void )
{/* 獲取優先級最高的就緒任務的TCB,然后更新到pxCurrentTCB */taskSELECT_HIGHEST_PRIORITY_TASK();
}

5. 修改:void xTaskIncrementTick( void )

位置:在task.c文件中定義;

由定時中斷xPortSysTickHandler調用;完成如下功能:

a. 實現全局變量xTickCount?計數操作;

此處有一個疑問:xTickCount?的加1為何這么麻煩,通過xConstTickCount常量來實現啊

? ? const TickType_t xConstTickCount = xTickCount + 1;
? ? xTickCount = xConstTickCount;

可能的原因 這種寫法可能是出于以下原因之一: 1. 調試方便:使用局部變量 xConstTickCount 可以方便地在調試時觀察 xTickCount 自增后的值。 2. 代碼風格:某些開發者可能傾向于通過局部變量來分離計算和賦值邏輯,以提高代碼的可讀性。 3. 歷史遺留:這段代碼可能是從更復雜的邏輯簡化而來的,原本 xConstTickCount 可能有其他用途,但后來簡化成了當前的形式。

b. 掃描所有的就緒列表的時間是否到了,到了記錄:taskRECORD_READY_PRIORITY( pxTCB->uxPriority );

c. 掃描結束進行任務切換portYIELD,觸發中斷;

void xTaskIncrementTick( void )
{TCB_t *pxTCB = NULL;BaseType_t i = 0;/* 更新系統時基計數器xTickCount,xTickCount是一個在port.c中定義的全局變量 */const TickType_t xConstTickCount = xTickCount + 1;xTickCount = xConstTickCount;/* 掃描就緒列表中所有線程的xTicksToDelay,如果不為0,則減1 */for(i=0; i<configMAX_PRIORITIES; i++){pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &pxReadyTasksLists[i] ) );if(pxTCB->xTicksToDelay > 0){pxTCB->xTicksToDelay --;}}/* 任務切換 */portYIELD();
}

6. 任務切換函數?portYIELD() 與taskYIELD

? ? ? ? 功能:設置 PendSV 的中斷掛起位,產生上下文切換。

#define taskYIELD()?? ??? ??? ??? ??? ? ? ? ? portYIELD()

#define portYIELD()																\
{																				\/* 設置 PendSV 的中斷掛起位,產生上下文切換 */								\portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;								\\/* Barriers are normally not required but do ensure the code is completely	\within the specified behaviour for the architecture. */						\__dsb( portSY_FULL_READ_WRITE );											\__isb( portSY_FULL_READ_WRITE );											\
}

主函數及其調試

重要文件

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/75915.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/75915.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/75915.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

生成信息提取的大型語言模型綜述

摘要 信息提取&#xff08;IE&#xff09;旨在從簡單的自然語言文本中提取結構知識。最近&#xff0c;生成型大型語言模型&#xff08;LLMs&#xff09;在文本理解和生成方面表現出了顯著的能力。因此&#xff0c;已經提出了許多基于生成范式將LLM集成到IE任務中的工作。為了對…

簡單談談很火的MCP( Model Context Protocol,模型上下文協議)

MCP( Model Context Protocol&#xff0c;模型上下文協議)是由Anthropic推出的開放協議&#xff0c;并非獨立的大模型&#xff0c;而是連接大模型與外部工具/數據源的標準化接口?&#xff0c;旨在解決AI工具開發中接口不統一、跨模型共享困難等問題。? 一、工作原理 MCP 協…

解決linux centos ubuntu等無法啟動谷歌chrome瀏覽器問題

命令啟動chrome時候提示&#xff1a; Running as root without --no-sandbox is not supported. See https://crbug.com/638180. 解決無法啟動谷歌chrome瀏覽器&#xff1a; cd /usr/bin 發現目錄下有 google-chrome google-chrome-stable 執行&#xff1a; vim go…

深入解析緩沖區:計算機世界的“蓄水池”與“加速器”

引言 想象這樣一個場景&#xff1a; 你的手機正在播放4K視頻&#xff0c;同時下載大型文件 視頻畫面流暢無卡頓&#xff0c;下載速度穩定在滿帶寬 但手機的內存只有8GB&#xff0c;下載文件的大小卻超過20GB 這看似矛盾的現象背后&#xff0c;緩沖區&#xff08;Buffer&am…

網絡故障診斷

一 網絡故障診斷的方法 1 試錯法&#xff1a;通過推測提出解決方案&#xff0c;最后得出故障原因的方法。 2 參照法&#xff1a;是一種比較快速解決網絡故障的方法&#xff0c;只有當故障設備與正常工作設備具有相近的條件時&#xff0c;才可以使用參照法。 3 替換法&#xff1…

界面控件Telerik和Kendo UI 2025 Q1亮點——AI集成與數據可視化

Telerik DevCraft包含一個完整的產品棧來構建您下一個Web、移動和桌面應用程序。它使用HTML和每個.NET平臺的UI庫&#xff0c;加快開發速度。Telerik DevCraft提供完整的工具箱&#xff0c;用于構建現代和面向未來的業務應用程序&#xff0c;目前提供UI for ASP.NET MVC、Kendo…

ollama遷移已下載的單個模型到服務器

ollama遷移已下載的單個模型到服務器 場景 ollama是面向用戶級的&#xff0c;部署和運行都很簡單&#xff0c;是否高效就另說了。但最起碼&#xff0c;他能充分利用用戶的硬件設備&#xff0c;在GPU不足也能調用cpu和內存去加持。 ollama運行的模型基本是量化版本的&#xf…

怎么對asp.web api進行單元測試?

在 ASP.NET Web API 中進行單元測試是一種確保代碼質量和功能正確性的重要實踐。單元測試的重點是針對 API 控制器中的邏輯進行測試&#xff0c;而不依賴于外部依賴&#xff08;如數據庫、文件系統或網絡請求&#xff09;。以下是實現 ASP.NET Web API 單元測試的步驟和方法&am…

UDP視頻傳輸中的丟包和播放花屏處理方法

在處理UDP視頻傳輸中的丟包和花屏問題時,需要結合編碼優化、網絡傳輸策略和接收端糾錯技術。以下是分步驟的解決方案: 1. 前向糾錯(FEC,Forward Error Correction) 原理:在發送數據時附加冗余包,接收方通過冗余信息恢復丟失的數據包。 實現方法: 使用Reed-Solomon、XO…

WebGL圖形編程實戰【3】:矩陣操控 × 從二維到三維的跨越

上一篇文章&#xff1a;WebGL圖形編程實戰【2】&#xff1a;動態著色 紋理貼圖技術揭秘 倉庫地址&#xff1a;github…、gitee… 矩陣操控 矩陣變換 回到前面關于平移縮放、旋轉的例子當中&#xff0c;我們是通過改變傳遞進去的xy的值來改變的。 在進行基礎變換的時候&…

并發編程--共享內存SHM

共享內存SHM 文章目錄 共享內存SHM1. 基本概念2. 函數接口2.1 創建或打開SHM對象2.2 映射 / 解除映射SHM對象2.3 其余操作2.4示例代碼 1. 基本概念 共享內存&#xff0c;顧名思義&#xff0c;就是通過不同進程共享一段相同的內存來達到通信的目的&#xff0c;由于SHM對象不再交…

Redis中的數據類型與適用場景

目錄 前言1. 字符串 (String)1.1 特點1.2 適用場景 2. 哈希 (Hash)2.1 特點2.2 適用場景 3. 列表 (List)3.1 特點3.2 適用場景 4. 集合 (Set)4.1 特點4.2 適用場景 5. 有序集合 (Sorted Set)5.1 特點5.2 適用場景 6. Redis 數據類型的選型建議結語 前言 Redis 作為一款高性能的…

科技賦能建筑業變革:中建海龍創新引領高質量發展新路徑

在建筑工業化浪潮中&#xff0c;中建海龍科技有限公司&#xff08;以下簡稱“中建海龍”&#xff09;憑借深厚的技術積累與持續創新&#xff0c;成為推動行業轉型升級的標桿企業。作為中國建筑國際集團旗下核心科技力量&#xff0c;中建海龍深耕模塊化集成建筑&#xff08;MiC&…

Vue下 Sortable 實現 table 列表字段可拖拽排序,顯示隱藏組件開發

vue 開發table 列表時&#xff0c;需要動態調整列字段的順序和顯示隱藏 實現效果如圖所示&#xff1a; vue 組件代碼 <template><div style"width: 90%; margin: 0 auto;"><el-table :data"tableData" border"" ref"table…

故障扭曲棱鏡反射照片效果ps特效濾鏡樣機 Distorted Mirror Poster Effect

只需單擊幾下即可執行令人著迷的高質量圖像和攝影&#xff01;此照片效果包含智能對象圖層&#xff0c;提供完全自定義、易用性和多功能性的工作流程。只需雙擊其縮略圖打開所需的圖層&#xff0c;刪除占位符鏡頭&#xff0c;添加圖形&#xff0c;保存它&#xff0c;然后觀看 P…

基于dify平臺批量分析excel格式信息

如何以表格形式批量輸入一些信息&#xff0c;然后讓大模型以對話應用形式逐條進行推理分析&#xff1f; 這里提供一個分步解決方案&#xff0c;結合 Dify平臺功能 和 API調用優化 的思路&#xff0c;既保證效率又降低復雜度&#xff1a; 1. 優先檢查 Dify 的「數據集」功能 Di…

CARLA常見技術問題集錦(一)地圖與場景構建篇

編者薦語&#xff1a; 在自動駕駛技術加速落地的今天&#xff0c;CARLA 仿真引擎憑借其開源生態與高保真仿真能力&#xff0c;已成為全球開發者構建智能駕駛算法的核心工具之一。隨著虛幻引擎 5.5 的全面升級&#xff0c;CARLA 0.10.0 版本實現了視覺革命&#xff1a;Lumen 全…

vue+webpack5(高級配置)

項目地址 基礎配置可查看文檔 1、devtool 配置 (找到報錯位置)2、優化打包速度3、oneOf 每個文件只被一個loader處理4、 include/exclude 處理某些文件或者排除某些文件5、 cache 緩存 &#xff08;提升后面幾次的打包速度&#xff09;6、 多進程打包7、減少代碼體積 Tree Shak…

JavaWeb——事務管理、AOP

目錄 一、事管理 1.開啟事務管理日志 2.開啟事務管理 3.傳播行為 二、AOP 1.通知類型 2.通知順序 3.切入點表達式 4.連接點 一、事務管理 1.開啟事務管理日志 2.開啟事務管理 3.傳播行為 當一個事務方法被另一個事務方法調用時&#xff0c;這個事物方法應該如何進行事…

okhttp3網絡請求

一、使用okhttp3和gson build.gradle ... dependencied {...implementation com.squareup.okhttp3:okhttp:3.9.0implementation com.google.code.gson:gson:2.10.1 }二、響應模型 可根據實際情況進行調整&#xff0c;目前我所需的就是這三個變量 HttpResponseData.java im…