GD32F30X-RT-Thread學習-線程管理

1. 軟硬件平臺

  1. GD32F307E-START Board開發板
  2. MDK-ARM Keil
    在這里插入圖片描述

2.RT-Thread Nano

在這里插入圖片描述

3.RT-Thread 內核學習-線程管理

? 在多線程操作系統中,可以把一個復雜的應用分解成多個小的、可調度的、序列化的程序單元,當合理地劃分任務并正確地執行時,這種設計能夠讓系統滿足實時系統的性能及時間的要求。在多線程實時系統中,可以將這個任務分解成子任務。

? 在 RT-Thread 中,與上述子任務對應的程序實體就是線程線程是實現任務的載體,它是 RT-Thread 中最基本的調度單位,它描述了一個任務執行的運行環境,也描述了這個任務所處的優先等級,重要的任務可設置相對較高的優先級,非重要的任務可以設置較低的優先級,不同的任務還可以設置相同的優先級,輪流運行。(RT-Thread 中Thread 對應于FreeRTOS中的task)。

當線程運行時,它會認為自己是以獨占 CPU 的方式在運行,線程執行時的運行環境稱為上下文,具體來說就是各個變量和數據,包括所有的寄存器變量、堆棧、內存信息等

? RT-Thread 線程管理的主要功能是對線程進行管理和調度,系統中總共存在兩類線程,分別是系統線程和用戶線程,**系統線程是由 RT-Thread 內核創建的線程,用戶線程是由應用程序創建的線程,**這兩類線程都會從內核對象容器中分配線程對象,當線程被刪除時,也會被從對象容器中刪除,如下圖所示,每個線程都有重要的屬性,如線程控制塊、線程棧、入口函數等。

在這里插入圖片描述

RT-Thread 的線程調度器是搶占式的,主要的工作就是從就緒線程列表中查找最高優先級線程,保證最高優先級的線程能夠被運行,最高優先級的任務一旦就緒,總能得到 CPU 的使用權。

當一個運行著的線程使一個比它優先級高的線程滿足運行條件,當前線程的 CPU 使用權就被剝奪了,或者說被讓出了,高優先級的線程立刻得到了 CPU 的使用權。

如果是中斷服務程序使一個高優先級的線程滿足運行條件,中斷完成時,被中斷的線程掛起,優先級高的線程開始運行。

當調度器調度線程切換時,先將當前線程上下文保存起來,當再切回到這個線程時,線程調度器將該線程的上下文信息恢復。

重要概念1 線程控制塊

? 在 RT-Thread 中,線程控制塊由結構體 struct rt_thread 表示,線程控制塊是操作系統用于管理線程的一個數據結構,它會存放線程的一些信息,例如優先級、線程名稱、線程狀態等,也包含線程與線程之間連接用的鏈表結構,線程等待事件集合等,詳細定義如下:

/* 線程控制塊 */
struct rt_thread
{/* rt 對象 */char        name[RT_NAME_MAX];     /* 線程名稱 */rt_uint8_t  type;                   /* 對象類型 */rt_uint8_t  flags;                  /* 標志位 */rt_list_t   list;                   /* 對象列表 */rt_list_t   tlist;                  /* 線程列表 *//* 棧指針與入口指針 */void       *sp;                      /* 棧指針 */void       *entry;                   /* 入口函數指針 */void       *parameter;              /* 參數 */void       *stack_addr;             /* 棧地址指針 */rt_uint32_t stack_size;            /* 棧大小 *//* 錯誤代碼 */rt_err_t    error;                  /* 線程錯誤代碼 */rt_uint8_t  stat;                   /* 線程狀態 *//* 優先級 */rt_uint8_t  current_priority;    /* 當前優先級 */rt_uint8_t  init_priority;        /* 初始優先級 */rt_uint32_t number_mask;......rt_ubase_t  init_tick;               /* 線程初始化計數值 */rt_ubase_t  remaining_tick;         /* 線程剩余計數值 */struct rt_timer thread_timer;      /* 內置線程定時器 */void (*cleanup)(struct rt_thread *tid);  /* 線程退出清除函數 */rt_uint32_t user_data;                      /* 用戶數據 */
};

其中 init_priority 是線程創建時指定的線程優先級,在線程運行過程當中是不會被改變的(除非用戶執行線程控制函數進行手動調整線程優先級)。**cleanup 會在線程退出時,被空閑線程回調一次以執行用戶設置的清理現場等工作。**最后的一個成員 user_data 可由用戶掛接一些數據信息到線程控制塊中,以提供一種類似線程私有數據的實現方式。

重要概念2 線程狀態

線程運行的過程中,同一時間內只允許一個線程在處理器中運行,從運行的過程上劃分,線程有多種不同的運行狀態,如初始狀態、掛起狀態、就緒狀態等。在 RT-Thread 中,線程包含五種狀態,操作系統會自動根據它運行的情況來動態調整它的狀態。 RT-Thread 中線程的五種狀態,如下表所示:

狀態描述
初始狀態當線程剛開始創建還沒開始運行時就處于初始狀態;在初始狀態下,線程不參與調度。此狀態在 RT-Thread 中的宏定義為 RT_THREAD_INIT
就緒狀態在就緒狀態下,線程按照優先級排隊,等待被執行;一旦當前線程運行完畢讓出處理器,操作系統會馬上尋找最高優先級的就緒態線程運行。此狀態在 RT-Thread 中的宏定義為 RT_THREAD_READY
運行狀態線程當前正在運行。在單核系統中,只有 rt_thread_self() 函數返回的線程處于運行狀態;在多核系統中,可能就不止這一個線程處于運行狀態。此狀態在 RT-Thread 中的宏定義為 RT_THREAD_RUNNING
掛起狀態也稱阻塞態。它可能因為資源不可用而掛起等待,或線程主動延時一段時間而掛起。在掛起狀態下,線程不參與調度。此狀態在 RT-Thread 中的宏定義為 RT_THREAD_SUSPEND
關閉狀態當線程運行結束時將處于關閉狀態。關閉狀態的線程不參與線程的調度。此狀態在 RT-Thread 中的宏定義為 RT_THREAD_CLOSE

RT-Thread 提供一系列的操作系統調用接口,使得線程的狀態在這五個狀態之間來回切換。幾種狀態間的轉換關系如下圖所示:

在這里插入圖片描述

  • 線程通過調用函數 rt_thread_create/init() 進入到初始狀態(RT_THREAD_INIT)
  • 初始狀態的線程通過調用函數 rt_thread_startup() 進入到就緒狀態(RT_THREAD_READY);就緒狀態的線程被調度器調度后進入運行狀態(RT_THREAD_RUNNING)
  • 當處于運行狀態的線程調用 rt_thread_delay(),rt_sem_take(),rt_mutex_take(),rt_mb_recv() 等函數或者獲取不到資源時,將進入到掛起狀態(RT_THREAD_SUSPEND)
  • 處于掛起狀態的線程,如果等待超時依然未能獲得資源或由于其他線程釋放了資源,那么它將返回到就緒狀態。
  • 掛起狀態的線程,如果調用 rt_thread_delete/detach() 函數,將更改為關閉狀態(RT_THREAD_CLOSE)
  • 而運行狀態的線程,如果運行結束,就會在線程的最后部分執行 rt_thread_exit() 函數,將狀態更改為關閉狀態
重要概念3 線程優先級

RT-Thread 線程的優先級是表示線程被調度的優先程度。每個線程都具有優先級,線程越重要,賦予的優先級就應越高,線程被調度的可能才會越大。

**RT-Thread 最大支持 256 個線程優先級 (0~255),數值越小的優先級越高,0 為最高優先級。**在一些資源比較緊張的系統中,可以根據實際情況選擇只支持 8 個或 32 個優先級的系統配置;對于 ARM Cortex-M 系列,普遍采用 32 個優先級。最低優先級默認分配給空閑線程使用,用戶一般不使用。在系統中,當有比當前線程優先級更高的線程就緒時,當前線程將立刻被換出,高優先級線程搶占處理器運行。

絕大多數的RTOS的優先級都是數值越小,優先級越高,除了FreeRTOS。

在這里插入圖片描述

重要概念4 系統線程:空閑線程 主線程
空閑線程

**空閑線程(idle)是系統創建的最低優先級的線程,線程狀態永遠為就緒態。當系統中無其他就緒線程存在時,調度器將調度到空閑線程,它通常是一個死循環,且永遠不能被掛起。**另外,空閑線程在 RT-Thread 也有著它的特殊用途:

若某線程運行完畢,系統將自動刪除線程:自動執行 rt_thread_exit() 函數,先將該線程從系統就緒隊列中刪除,再將該線程的狀態更改為關閉狀態,不再參與系統調度,然后掛入 rt_thread_defunct 僵尸隊列(資源未回收、處于關閉狀態的線程隊列)中,最后空閑線程會回收被刪除線程的資源。

空閑線程也提供了接口來運行用戶設置的鉤子函數,在空閑線程運行時會調用該鉤子函數,適合處理功耗管理、看門狗喂狗等工作。空閑線程必須有得到執行的機會,即其他線程不允許一直while(1)死卡,必須調用具有阻塞性質的函數;否則例如線程刪除、回收等操作將無法得到正確執行。

主線程

在系統啟動時,系統會創建 main 線程,它的入口函數為 main_thread_entry(),用戶的應用入口函數 main() 就是從這里真正開始的,系統調度器啟動后,main 線程就開始運行,過程如下圖,用戶可以在 main() 函數里添加自己的應用程序初始化代碼。

在這里插入圖片描述

線程管理函數API
/** thread interface*/
rt_err_t rt_thread_init(struct rt_thread *thread,const char       *name,void (*entry)(void *parameter),void             *parameter,void             *stack_start,rt_uint32_t       stack_size,rt_uint8_t        priority,rt_uint32_t       tick);
rt_err_t rt_thread_detach(rt_thread_t thread);
rt_thread_t rt_thread_create(const char *name,void (*entry)(void *parameter),void       *parameter,rt_uint32_t stack_size,rt_uint8_t  priority,rt_uint32_t tick);
rt_thread_t rt_thread_self(void);
rt_thread_t rt_thread_find(char *name);
rt_err_t rt_thread_startup(rt_thread_t thread);
rt_err_t rt_thread_delete(rt_thread_t thread);rt_err_t rt_thread_yield(void);
rt_err_t rt_thread_delay(rt_tick_t tick);
rt_err_t rt_thread_mdelay(rt_int32_t ms);
rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg);
rt_err_t rt_thread_suspend(rt_thread_t thread);
rt_err_t rt_thread_resume(rt_thread_t thread);
void rt_thread_timeout(void *parameter);#ifdef RT_USING_SIGNALS //使用信號量
void rt_thread_alloc_sig(rt_thread_t tid);
void rt_thread_free_sig(rt_thread_t tid);
int  rt_thread_kill(rt_thread_t tid, int sig);
#endif#ifdef RT_USING_HOOK  //使用鉤子函數
void rt_thread_suspend_sethook(void (*hook)(rt_thread_t thread));
void rt_thread_resume_sethook (void (*hook)(rt_thread_t thread));
void rt_thread_inited_sethook (void (*hook)(rt_thread_t thread));
#endif/** idle thread interface*/
void rt_thread_idle_init(void);
#if defined(RT_USING_HOOK) || defined(RT_USING_IDLE_HOOK)
rt_err_t rt_thread_idle_sethook(void (*hook)(void));
rt_err_t rt_thread_idle_delhook(void (*hook)(void));
#endif
void rt_thread_idle_excute(void);
rt_thread_t rt_thread_idle_gethandler(void);

在這里插入圖片描述

線程的創建(動態創建、靜態創建)

動態創建 rt_thread_create

rt_thread_t rt_thread_create(const char* name,void (*entry)(void* parameter),void* parameter,rt_uint32_t stack_size,rt_uint8_t priority,rt_uint32_t tick);
參數描述
name線程的名稱;線程名稱的最大長度由 rtconfig.h 中的宏 RT_NAME_MAX 指定,多余部分會被自動截掉
entry線程入口函數
parameter線程入口函數參數
stack_size線程棧大小,單位是字節
priority線程的優先級。優先級范圍根據系統配置情況(rtconfig.h 中的 RT_THREAD_PRIORITY_MAX 宏定義),如果支持的是 256 級優先級,那么范圍是從 0~255,數值越小優先級越高,0 代表最高優先級
tick線程的時間片大小。時間片(tick)的單位是操作系統的時鐘節拍。當系統中存在相同優先級線程時,這個參數指定線程一次調度能夠運行的最大時間長度。這個時間片運行結束時,調度器自動選擇下一個就緒態的同優先級線程進行運行
返回值
thread線程創建成功,返回線程句柄
RT_NULL線程創建失敗

一般情況下,入口參數沒有的情況比較多。

靜態創建 rt_thread_init

rt_err_t rt_thread_init(struct rt_thread *thread,const char       *name,void (*entry)(void *parameter),void             *parameter,void             *stack_start,rt_uint32_t       stack_size,rt_uint8_t        priority,rt_uint32_t       tick);
參數描述
thread線程句柄。線程句柄由用戶提供出來,并指向對應的線程控制塊內存地址
name線程的名稱;線程名稱的最大長度由 rtconfig.h 中定義的 RT_NAME_MAX 宏指定,多余部分會被自動截掉
entry線程入口函數
parameter線程入口函數參數
stack_start線程棧起始地址
stack_size**線程棧大小,單位是字節。**在大多數系統中需要做棧空間地址對齊(例如 ARM 體系結構中需要向 4 字節地址對齊)
priority線程的優先級。優先級范圍根據系統配置情況(rtconfig.h 中的 RT_THREAD_PRIORITY_MAX 宏定義),如果支持的是 256 級優先級,那么范圍是從 0 ~ 255,數值越小優先級越高,0 代表最高優先級
tick**線程的時間片大小。**時間片(tick)的單位是操作系統的時鐘節拍。當系統中存在相同優先級線程時,這個參數指定線程一次調度能夠運行的最大時間長度。這個時間片運行結束時,調度器自動選擇下一個就緒態的同優先級線程進行運行
返回
RT_EOK線程創建成功
RT_ERROR線程創建失敗

在靜態創建過程中,需要預先定義一個數組,提前申請空間,動態創建過程則不需要,系統會從動態堆內存中分配一個線程句柄以及按照參數中指定的棧大小從動態堆內存中分配相應的空間。

線程啟動

創建(初始化)的線程狀態處于初始狀態,并未進入就緒線程的調度隊列,我們可以在線程初始化 / 創建成功后調用下面的函數接口讓該線程進入就緒態:

rt_err_t rt_thread_startup(rt_thread_t thread);

當調用這個函數時,將把線程的狀態更改為就緒狀態,并放到相應優先級隊列中等待調度。如果新啟動的線程優先級比當前線程優先級高,將立刻切換到這個線程。線程啟動接口 rt_thread_startup() 的參數和返回值見下表:

參數描述
thread線程句柄
返回
RT_EOK線程啟動成功
RT_ERROR線程啟動失敗
/** 程序清單:創建、初始化/脫離線程** 這個例子會創建兩個線程,一個動態線程,一個靜態線程。* 靜態線程在運行完畢后自動被系統脫離,動態線程打印計數。*/
#include <rtthread.h>#define THREAD_PRIORITY         15
#define THREAD_STACK_SIZE       512
#define THREAD_TIMESLICE        5static rt_thread_t tid1 = RT_NULL;/* 線程1的入口函數 */
static void thread1_entry(void *parameter)
{rt_uint32_t count = 0;for (count =0 ;count< 20;count++){/* 線程1采用低優先級運行,打印計數值20結束 */rt_kprintf("thread1 count: %d\n", count ++);}rt_kprintf("thread1 exit\n");
}ALIGN(RT_ALIGN_SIZE)
static char thread2_stack[1024];
static struct rt_thread thread2;/* 線程2入口 */
static void thread2_entry(void *param)
{rt_uint32_t count = 0;/* 線程2擁有較高的優先級,以搶占線程1而獲得執行 */for (count = 0; count < 10 ; count++){/* 線程2打印計數值 */rt_kprintf("thread2 count: %d\n", count);}rt_kprintf("thread2 exit\n");/* 線程2運行結束后也將自動被系統脫離 */
}/* 線程示例 */
int thread_sample(void)
{/* 創建線程1,名稱是thread1,入口是thread1_entry*/tid1 = rt_thread_create("thread1",thread1_entry, RT_NULL,THREAD_STACK_SIZE,THREAD_PRIORITY, THREAD_TIMESLICE);/* 如果獲得線程控制塊,啟動這個線程 */if (tid1 != RT_NULL)rt_thread_startup(tid1);/* 初始化線程2,名稱是thread2,入口是thread2_entry */rt_thread_init(&thread2,"thread2",thread2_entry,RT_NULL,&thread2_stack[0],sizeof(thread2_stack),THREAD_PRIORITY - 1, THREAD_TIMESLICE);rt_thread_startup(&thread2);return 0;
}/* 導出到 msh 命令列表中 */
MSH_CMD_EXPORT(thread_sample, thread sample);
#include "main.h"void Hardware_Init(void)
{SystemInit (); systick_config();bsp_uart_init();HW_LED_Init();  }int main(void)
{Hardware_Init();printf("SystemInit [ok] \r\n");printf("systick_config[ok] \r\n");printf("bsp_uart_init [ok] \r\n");printf("Hardware_Init [ok] \r\n");printf("LED_Init [ok] \r\n");printf("GD32307E-START Board Testing \r\n");printf("GD32307E-START Board thread_sample test start...\r\n");thread_sample();printf("GD32307E-START Board thread_sample test end...\r\n");while(1){gpio_bit_set(GPIOC,GPIO_PIN_6);rt_thread_delay(500);   /* 延時500個tick */rt_kprintf("led_thread running,LED1_ON\r\n");gpio_bit_reset(GPIOC,GPIO_PIN_6);    rt_thread_delay(500);   /* 延時500個tick */		 		rt_kprintf("led_thread running,LED1_OFF\r\n");}  
}

在這里插入圖片描述
整個程序先執行thread2,因為THREAD_PRIORITY優先級比thread1高,thread2打印完成10次計數值之后,就執行thread1,打印完成20次計數值結束。

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

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

相關文章

qt可以詳細寫的項目或技術

1.QT 圖形視圖框架 2.QT 模型視圖結構 3.QT列表顯示大量信息 4.QT播放器 5.QT 編解碼 6.QT opencv

Linux--RedHat--安裝和配置C++環境

百度下載&#xff0c;安裝包&#xff1a; 鏈接&#xff1a;https://pan.baidu.com/s/1IgBfCCRxGYZ_PPiedad0xQ 提取碼&#xff1a;ffff 下載后&#xff0c;建個目錄&#xff0c;先解壓好安裝包&#xff01; &#xff08;兩種方法&#xff09;執行如下命令&#xff1a; 參考…

Bypass open_basedir

講解 open_basedir是php.ini中的一個配置選項&#xff0c;可用于將用戶訪問文件的活動范圍限制在指定的區域。 假設open_basedir/var/www/html/web1/:/tmp/&#xff0c;那么通過web1訪問服務器的用戶就無法獲取服務器上除了/var/www/html/web1/和/tmp/這兩個目錄以外的文件。…

Java——面試:String 和 StringBuffer 的區別?

相同點&#xff1a; String 和 StringBuffer&#xff0c;它們可以儲存和操作字符串&#xff0c; 即包含多個字符的字符數據。 String 和 StringBuffer 的區別有以下幾點&#xff1a; 1.String 類提供了數值不可改變的字符串。而 StringBuffer 類提供的字符串進行修改。 當你知…

洛谷 P8674 [藍橋杯 2018 國 B] 調手表

文章目錄 [藍橋杯 2018 國 B] 調手表題目描述輸入格式輸出格式樣例 #1樣例輸入 #1樣例輸出 #1 提示 題意解析CODE分析一下復雜度 [藍橋杯 2018 國 B] 調手表 題目描述 小明買了塊高端大氣上檔次的電子手表&#xff0c;他正準備調時間呢。 在 M78 星云&#xff0c;時間的計量…

JVM虛擬機:命令行查看JVM垃圾回收器的執行信息

在eclipse中打開命令行窗口 window->show view->Terminal 這樣就打開了Terminal窗口&#xff0c;效果如下所示&#xff1a; java -XX:PrintCommandLineFlags -version 這個命令可以查看一些配置信息&#xff0c;其中最重要的配置信息就是&#xff0c;當前使用的G1回收器…

什么是漏洞掃描

漏洞掃描是指基于漏洞數據庫&#xff0c;通過掃描等手段對指定的遠程或者本地計算機系統的安全脆弱性進行檢測&#xff0c;發現可利用漏洞的一種安全檢測的 行為&#xff0c;也是一類重要的網絡安全技術。它和防火墻、入侵檢測系統互相配合&#xff0c;能夠有效提高網絡的安全性…

鍵盤打字盲打練習系列之成為大師——5

一.歡迎來到我的酒館 盲打&#xff0c;成為大師&#xff01; 目錄 一.歡迎來到我的酒館二.關于盲打你需要知道三.值得收藏的練習打字網站 二.關于盲打你需要知道 盲打系列教程&#xff0c;終于寫到終章了。。。一開始在看網上視頻&#xff0c;看到up主熟練的打字技巧&#xff…

LabVIEW與Tektronix示波器實現電源測試自動化

LabVIEW與Tektronix示波器實現電源測試自動化 在現代電子測試與測量領域&#xff0c;自動化測試系統的構建是提高效率和精確度的關鍵。本案例介紹了如何利用LabVIEW軟件結合Tektronix MDO MSO DPO2000/3000/4000系列示波器&#xff0c;開發一個自動化測試項目。該項目旨在自動…

javascript中Reflect是什么?三分鐘初識

目錄 1. Reflect是什么&#xff1f;2. 為什么會出現Reflect&#xff1f;3. 需要怎么去使用Reflect&#xff1f;4. 最終的結果解決什么&#xff1f;5. 使用的注意點6. 常用的技巧 Reflect是Javascript中的一個內置對象&#xff0c;它提供了一組用于操作對象的方法&#xff0c;可…

Spring - BeanFactory和FactoryBean的理解

BeanFactory是什么&#xff1f; BeanFactory是Spring 容器的根接口&#xff0c;它是IOC的基本容器&#xff0c;負責管理和加載Bean&#xff0c;它為具體的IOC容器提供了最基本的規范&#xff0c;比如DefaultListableBeanFactory和ConfigurableBeanFactory&#xff0c;BeanFact…

《C++新經典設計模式》之第17章 中介者模式

《C新經典設計模式》之第17章 中介者模式 中介者模式.cpp 中介者模式.cpp #include <iostream> #include <map> #include <memory> using namespace std;// 中介者封裝一系列的對象交互 // 4種角色 // Mediator&#xff08;抽象中介者類&#xff09;&#x…

MYSQL練題筆記-高級查詢和連接-指定日期的產品價格

這依舊是中等題&#xff0c;想了好久&#xff0c;終于理解了很開心&#xff01; 一、題目相關內容 1&#xff09;相關的表和題目 2&#xff09;幫助理解題目的示例&#xff0c;提供返回結果的格式 二、自己初步的理解 題目是找出2019-08-16 時全部產品的價格&#xff0c;所以…

數字化時代的到來,IT運維產業正在發生深刻的變革

IT運維產業是隨著信息技術的發展而產生的&#xff0c;它涵蓋了從硬件到軟件、從應用到數據、從終端到云端等各個方面的維護和管理。隨著數字化時代的到來&#xff0c;IT運維產業正在發生深刻的變革。其中&#xff0c;大數據技術的廣泛應用和數據資源的日益豐富&#xff0c;正在…

使用最小花費爬樓梯

1.狀態表示 2.狀態轉移方程 3.初始化 保證填表時&#xff0c; 不越界 4.填表順序 從左往右 5.返回值 解法2&#xff1a; 1.狀態表示 2.狀態轉移方程 3.初始化 4.填表 從右往左 5.返回值 min( dp[0] , dp[1] ) ----------------------------------------------------…

java+springboot+ssm學生社團管理系統76c2e

本系統包括前臺和后臺兩個部分。前臺主要是展示社團列表、社團風采、社團活動、新聞列表等&#xff0c;前臺登錄后進入個人中心&#xff0c;在個人中心能申請加入社團、查看參加的社團活動等&#xff1b;后臺為管理員與社團負責人使用&#xff0c;應用于對社團的管理及內容發布…

Vue3源碼梳理:源碼目錄結構及源碼閱讀方法

VUE3 源碼目錄結構 1 ) 下載源碼三種方式 方式1&#xff0c;Download ZIP&#xff0c;不推薦方式2&#xff0c;通過https,或ssh或github cli來克隆項目 $ git clone https://github.com/vuejs/core.git$ git clone gitgithub.com:vuejs/core.git 方式3&#xff0c;點擊Fork, …

常見統計學習方法特點總結

1. 概述 方法適用問題模型特點模型類型學習策略損失函數學習算法1感知機二分類分離超平面判別模型極小化誤分點到超平面距離誤分點到超平面距離SGD2KNN多分類&#xff0c;回歸特征空間&#xff0c;樣本點判別模型---3樸素貝葉斯多分類特征與類別的聯合概率分布&#xff0c;條件…

【CMU 15-445】Proj2 Hash Index

EXTENDIBLE HASH INDEX 通關記錄Task1 Read/Write Page Guards移動構造函數Drop方法移動賦值運算符析構函數UpgradeRead函數FetchPageBasic、FetchPageRead、FetchPageWrite、NewPageGuarded Task2 Extendible Hash Table PagesHeaderPageDirectoryPageBucketPage Task3 Extend…

飛天使-linux操作的一些技巧與知識點5

文章目錄 roles批量替換文件 role 的依賴關系role 的實際案例 roles tasks 和 handlers &#xff0c;那怎樣組織 playbook 才是最好的方式呢&#xff1f;簡 單的回答就是&#xff1a;使用 Roles Roles 基于一個已知的文件結構&#xff0c;去自動的加載 vars&#xff0c;tasks 以…