0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

線程的基本知識

黃工的嵌入式技術(shù)圈 ? 來源:黃工的嵌入式技術(shù)圈 ? 作者:黃工的嵌入式技術(shù) ? 2020-02-04 15:42 ? 次閱讀

今天給大家分享一點(diǎn)RT-Thread的基礎(chǔ)知識。

什么是線程?

人們在生活中處理復(fù)雜問題時,慣用的方法就是分而治之,即把一個大問題分解成多個相對簡單、比較容易解決的小問題,小問題逐個被解決了,大問題也就隨之解決了。同樣,在設(shè)計一個較為復(fù)雜的應(yīng)用程序時,也通常把一個大型任務(wù)分解成多個小任務(wù),然后通過運(yùn)行這些小任務(wù),最終達(dá)到完成大任務(wù)的目的。

在裸機(jī)系統(tǒng)中, 系統(tǒng)的主體就是 main 函數(shù)里面順序執(zhí)行的無限循環(huán),這個無限循環(huán)里面 CPU 按照順序完成各種事情。在多線程系統(tǒng)中,我們根據(jù)功能的不同,把整個系統(tǒng)分割成一個個獨(dú)立的且無法返回的函數(shù),這個函數(shù)我們稱為線程。

線程由哪些部分組成?

RT-Thread 中的線程由三部分組成:線程代碼(函數(shù))、線程控制塊、線程堆棧。

線程棧

在一個裸機(jī)系統(tǒng)中, 如果有全局變量,有子函數(shù)調(diào)用,有中斷發(fā)生。那么系統(tǒng)在運(yùn)行的時候,全局變量放在哪里,子函數(shù)調(diào)用時,局部變量放在哪里, 中斷發(fā)生時,函數(shù)返回地址發(fā)哪里。

如果只是單純的裸機(jī)編程,它們放哪里我們不用管,但是如果要寫一個 RTOS,這些種種環(huán)境參數(shù),我們必須弄清楚他們是如何存儲的。

在裸機(jī)系統(tǒng)中,他們統(tǒng)統(tǒng)放在一個叫棧的地方,棧是單片機(jī) RAM 里面一段連續(xù)的內(nèi)存空間,棧的大小一般在啟動文件或者鏈接腳本里面指定, 最后由 C 庫函數(shù)_main 進(jìn)行初始化。

但是, 在多線程系統(tǒng)中,每個線程都是獨(dú)立的,互不干擾的,所以要為每個線程都分配獨(dú)立的??臻g,這個??臻g通常是一個預(yù)先定義好的全局?jǐn)?shù)組, 也可以是動態(tài)分配的一段內(nèi)存空間,但它們都存在于 RAM 中。如:

staticrt_uint8_tled_stack[512];

線程棧其實(shí)就是一個預(yù)先定義好的全局?jǐn)?shù)據(jù),數(shù)據(jù)類型為rt_uint8_t,大小我們設(shè)置為 512。在 RT-Thread 中,凡是涉及到數(shù)據(jù)類型的地方, RTThread 都會將標(biāo)準(zhǔn)的 C 數(shù)據(jù)類型用 typedef 重新取一個類型名, 以“rt”前綴開頭。這些經(jīng)過重定義的數(shù)據(jù)類型放在 rtdef.h ,如:

線程控制塊

在 RT-Thread 中,線程控制塊由結(jié)構(gòu)體 struct rt_thread 表示,線程控制塊是操作系統(tǒng)用于管理線程的一個數(shù)據(jù)結(jié)構(gòu),它會存放線程的一些信息,例如優(yōu)先級、線程名稱、線程狀態(tài)等,也包含線程與線程之間連接用的鏈表結(jié)構(gòu),線程等待事件集合等,詳細(xì)定義如下(在rtdef.h中定義):

為led線程定義一個線程控制塊:

staticstructrt_threadled_thread;

線程函數(shù)

線程控制塊中的 entry 是線程的入口函數(shù),它是線程實(shí)現(xiàn)預(yù)期功能的函數(shù)。線程的入口函數(shù)由用戶設(shè)
計實(shí)現(xiàn),一般有以下兩種代碼形式:

無限循環(huán)模式:

在實(shí)時系統(tǒng)中,線程通常是被動式的:這個是由實(shí)時系統(tǒng)的特性所決定的,實(shí)時系統(tǒng)通??偸堑却饨缡录陌l(fā)生,而后進(jìn)行相應(yīng)的服務(wù):

順序執(zhí)行或有限次循環(huán)模式:

如簡單的順序語句、 do whlie() 或 for() 循環(huán)等,此類線程不會循環(huán)或不會永久循環(huán),可謂是 “一次性”線程,一定會被執(zhí)行完畢。在執(zhí)行完畢后,線程將被系統(tǒng)自動刪除。

動態(tài)線程與靜態(tài)線程

我們的用戶線程有兩種創(chuàng)建方式,一種是靜態(tài)線程,另一種是動態(tài)線程。

創(chuàng)建靜態(tài)線程的函數(shù):

返回值為錯誤代碼。

創(chuàng)建動態(tài)線程的函數(shù):

返回值為線程控制塊 。

線程創(chuàng)建實(shí)例

創(chuàng)建一個靜態(tài)線程

1、確定線程棧

2、定義線程控制塊

3、創(chuàng)建線程函數(shù)。

#include #include #include /*靜態(tài)線程相關(guān)宏定義*/ #defineTHREAD_PRIORITY25/*優(yōu)先級*/ #defineSTACK_SIZE512/*棧大小*/ #defineTIMESLICE5/*時間片*/ /*線程三要素*/ staticrt_uint8_tstatic_thread_stack[STACK_SIZE];/*線程棧*/ staticstructrt_threadstatic_thread;/*線程控制塊*/ staticvoidstatic_thread_entry(void*parameter);/*線程入口函數(shù)*/ /*靜態(tài)線程入口函數(shù)*/ staticvoidstatic_thread_entry(void*parameter) { rt_uint32_ti=0; rt_kprintf("Thisisstaticthread!\n"); /*無限循環(huán)*/ while(1) { rt_kprintf("staticthreadcount:%d\r\n",++i); /*等待0.5s,讓出cpu權(quán)限,切換到其他線程*/ rt_thread_delay(500); } } /*主函數(shù)*/ intmain(void) { rt_err_tresult; /*創(chuàng)建靜態(tài)線程:優(yōu)先級 25 ,時間片 5個系統(tǒng)滴答,線程棧512字節(jié)*/ result=rt_thread_init(&static_thread, "static_thread", static_thread_entry, RT_NULL, (rt_uint8_t*)&static_thread_stack[0], STACK_SIZE, THREAD_PRIORITY, TIMESLICE); /*創(chuàng)建成功則啟動靜態(tài)線程*/ if(result==RT_EOK) { rt_thread_startup(&static_thread); } }

運(yùn)行結(jié)果為:

可見,在T-Thread中創(chuàng)建一個線程需要線程棧、線程控制塊與線程函數(shù)這三要素。除此之外,需要設(shè)置一個線程優(yōu)先級,因?yàn)镽T-Thread的調(diào)度器是基于優(yōu)先級的搶占式調(diào)度算法。還需要設(shè)置一個時間片參數(shù),這個用于多個線程具有同等優(yōu)先級的情況下,采用時間片的輪轉(zhuǎn)調(diào)度算法進(jìn)行調(diào)度,這個值與時間節(jié)拍有關(guān),每一秒的節(jié)拍數(shù)可在rtconfig.h里進(jìn)行設(shè)置:

在這里我們只創(chuàng)建一個線程,所以時間片我們沒有用到,但也需要傳遞一個時間片的值給rt_thread_init函數(shù)。最后,在主函數(shù)里調(diào)用相關(guān)接口創(chuàng)建一個靜態(tài)線程,創(chuàng)建成功則啟動該線程。

創(chuàng)建一個動態(tài)線程

創(chuàng)建動態(tài)線程與創(chuàng)建靜態(tài)線程類似:

#include #include #include /*動態(tài)線程相關(guān)宏定義*/ #defineTHREAD_PRIORITY25/*優(yōu)先級*/ #defineSTACK_SIZE512/*棧大小*/ #defineTIMESLICE5/*時間片*/ /*線程三要素*/ staticrt_uint8_tdynamic_thread_stack[STACK_SIZE];/*線程棧*/ staticstructrt_threaddynamic_thread;/*線程控制塊*/ staticvoiddynamic_thread_entry(void*parameter);/*線程入口函數(shù)*/ /*動態(tài)線程入口函數(shù)*/ staticvoiddynamic_thread_entry(void*parameter) { rt_uint32_ti; /*無限循環(huán)*/ while(1) { for(i=0;i

運(yùn)行結(jié)果:

靜態(tài)線程VS動態(tài)線程

上例中,從運(yùn)行結(jié)果上看,是沒有任何差別的!那么,我們在實(shí)際中如何抉擇?

使用靜態(tài)線程時,必須先定義靜態(tài)的線程控制塊,并且定義好??臻g,然后調(diào)用rt_thread_init()函數(shù)來完成線程的初始化工作。采用這種方式,線程控制塊和堆棧占用的內(nèi)存會放在 RW/ZI 段,這段空間在編譯時就已經(jīng)確定,它不是可以動態(tài)分配的,所以不能被釋放,而只能使用 rt_thread_detach()函數(shù)將該線程控制塊從對象管理器中脫離。
使用動態(tài)定義方式 rt_thread_create()時, RT-Thread 會動態(tài)申請線程控制塊和堆??臻g。在編譯時,編譯器是不會感知到這段空間的,只有在程序運(yùn)行時, RT-Thread 才會從系統(tǒng)堆中申請分配這段內(nèi)存空間,當(dāng)不需要使用該線程時,調(diào)用 rt_thread_delete()函數(shù)就會將這段申請的內(nèi)存空間重新釋放到內(nèi)存堆中。

這兩種方式各有利弊,靜態(tài)定義方式會占用 RW/ZI 空間,但是不需要動態(tài)分配內(nèi)存,運(yùn)行時效率較高,實(shí)時性較好。動態(tài)方式不會占用額外的 RW/ZI 空間,占用空間小,但是運(yùn)行時需要動態(tài)分配內(nèi)存,效率沒有靜態(tài)方式高。

總的來說,這兩種方式就是空間和時間效率的平衡,可以根據(jù)實(shí)際環(huán)境需求選擇采用具體的分配方式。就像C編程中,何時使用動態(tài)空間,何時使用靜態(tài)空間,也需要根據(jù)實(shí)際情況平衡選擇。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 多線程
    +關(guān)注

    關(guān)注

    0

    文章

    277

    瀏覽量

    19897
  • 線程
    +關(guān)注

    關(guān)注

    0

    文章

    503

    瀏覽量

    19636
  • RT-Thread
    +關(guān)注

    關(guān)注

    31

    文章

    1261

    瀏覽量

    39838
收藏 人收藏

    評論

    相關(guān)推薦

    IGB基本知識匯總

    本文對IGBT領(lǐng)域的深入研究與綜合剖析成果,首先與您分享關(guān)于IGBT的基本原理及其構(gòu)成元素,如芯片、單管及模塊等方面的知識。接下來將共同關(guān)注的是IGBT在各個行業(yè)中的廣泛應(yīng)用。
    的頭像 發(fā)表于 10-29 10:15 ?195次閱讀
    IGB<b class='flag-5'>基本知識</b>匯總

    CPU線程和程序線程的區(qū)別

    CPU的線程與程序的線程在概念、作用、實(shí)現(xiàn)方式以及性能影響等方面存在顯著差異。以下是對兩者區(qū)別的詳細(xì)闡述,旨在深入探討這一技術(shù)話題。
    的頭像 發(fā)表于 09-02 11:18 ?707次閱讀

    堆棧和內(nèi)存的基本知識

    本文主要聊聊關(guān)于堆棧的內(nèi)容。包括堆棧和內(nèi)存的基本知識。常見和堆棧相關(guān)的 bug,如棧溢出,內(nèi)存泄漏,堆內(nèi)存分配失敗等。后面介紹軟件中堆棧統(tǒng)計的重要性,以及如何使用工具工具軟件中堆棧使用的范圍,并給出在軟件開發(fā)中,如何降低堆棧問題,優(yōu)化堆棧的一些實(shí)踐。
    的頭像 發(fā)表于 08-29 14:10 ?358次閱讀
    堆棧和內(nèi)存的<b class='flag-5'>基本知識</b>

    光刻工藝的基本知識

    在萬物互聯(lián),AI革命興起的今天,半導(dǎo)體芯片已成為推動現(xiàn)代社會進(jìn)步的心臟。而光刻(Lithography)技術(shù),作為先進(jìn)制造中最為精細(xì)和關(guān)鍵的工藝,不管是半導(dǎo)體芯片、MEMS器件,還是微納光學(xué)元件都離不開光刻工藝的參與,其重要性不言而喻。本文將帶您一起認(rèn)識光刻工藝的基本知識。
    的頭像 發(fā)表于 08-26 10:10 ?559次閱讀
    光刻工藝的<b class='flag-5'>基本知識</b>

    探索虛擬線程:原理與實(shí)現(xiàn)

    虛擬線程的引入與優(yōu)勢 在Loom項(xiàng)目之前,Java虛擬機(jī)(JVM)中的線程是通過java.lang.Thread類型來實(shí)現(xiàn)的,這些線程被稱為平臺線程。 然而,平臺
    的頭像 發(fā)表于 06-24 11:35 ?244次閱讀
    探索虛擬<b class='flag-5'>線程</b>:原理與實(shí)現(xiàn)

    熱釋電傳感器基本知識和使用中的常見問題

    電子發(fā)燒友網(wǎng)站提供《熱釋電傳感器基本知識和使用中的常見問題》資料免費(fèi)下載
    發(fā)表于 06-11 09:06 ?1次下載

    什么是動態(tài)線程池?動態(tài)線程池的簡單實(shí)現(xiàn)思路

    因此,動態(tài)可監(jiān)控線程池一種針對以上痛點(diǎn)開發(fā)的線程池管理工具。主要可實(shí)現(xiàn)功能有:提供對 Spring 應(yīng)用內(nèi)線程池實(shí)例的全局管控、應(yīng)用運(yùn)行時動態(tài)變更線程池參數(shù)以及
    的頭像 發(fā)表于 02-28 10:42 ?567次閱讀

    低壓配電基本知識

    低壓配電基本知識
    的頭像 發(fā)表于 12-21 09:48 ?741次閱讀
    低壓配電<b class='flag-5'>基本知識</b>

    redis多線程還能保證線程安全嗎

    Redis是一種使用C語言編寫的高性能鍵值存儲系統(tǒng),它是單線程的,因?yàn)槭褂昧硕嗦窂?fù)用的方式來處理并發(fā)請求。這樣的實(shí)現(xiàn)方式帶來了很好的性能,但同時也引發(fā)了一些線程安全方面的問題。 在Redis中,由于
    的頭像 發(fā)表于 12-05 10:28 ?1628次閱讀

    電子元器件采購基本知識

    電子元器件是指電子設(shè)備中的各種電子部件,包括電阻、電容、電感、二極管、三極管、集成電路等。在電子設(shè)備的設(shè)計和制造過程中,電子元器件的采購是非常重要的環(huán)節(jié)。以下是一些電子元器件采購的基本知識
    的頭像 發(fā)表于 12-05 09:19 ?1561次閱讀

    核心線程數(shù)和最大線程數(shù)怎么設(shè)置

    核心線程數(shù)和最大線程數(shù)是Java線程池中重要的參數(shù),用來控制線程池中線程的數(shù)量和行為。正確地設(shè)置這兩個參數(shù)可以優(yōu)化系統(tǒng)的性能和資源利用率。本
    的頭像 發(fā)表于 12-01 13:50 ?8497次閱讀

    西門子伺服驅(qū)動器維修的一些基本知識

    西門子伺服驅(qū)動器維修的一些基本知識
    的頭像 發(fā)表于 11-23 10:55 ?1654次閱讀

    示波器應(yīng)用的基本知識

    電子發(fā)燒友網(wǎng)站提供《示波器應(yīng)用的基本知識.pdf》資料免費(fèi)下載
    發(fā)表于 11-18 14:50 ?1次下載
    示波器應(yīng)用的<b class='flag-5'>基本知識</b>

    線程如何保證數(shù)據(jù)的同步

    線程編程是一種并發(fā)編程的方法,意味著程序中同時運(yùn)行多個線程,每個線程可獨(dú)立執(zhí)行不同的任務(wù),共享同一份數(shù)據(jù)。由于多線程并發(fā)執(zhí)行的特點(diǎn),會引發(fā)數(shù)據(jù)同步的問題,即保證多個
    的頭像 發(fā)表于 11-17 14:22 ?1108次閱讀

    如何查看一個線程的ID

    1.什么是線程? linux內(nèi)核中是沒有線程這個概念的,而是輕量級進(jìn)程的概念:LWP。一般我們所說的線程概念是C庫當(dāng)中的概念。 1.1線程是怎樣描述的?
    的頭像 發(fā)表于 11-13 14:38 ?1254次閱讀
    如何查看一個<b class='flag-5'>線程</b>的ID