目前市面上有很多的rtos系統,他們各有特點,首先聲明,本文並非基於某一款rtos系統,關於rtos系統的介紹的解釋網上一大把,就不去炒剩飯了.傳統的rtos系統教程把系統的各個組件拆成幾部分,好比線程郵箱消息隊列分開來說,我的以爲這種方式對新手不友好,本文將本身的理解以問答形式梳理一下,整體的思路以下:編程
能夠看出來這主要的知識點都是一環套一環,新手若是不理解這其中的因果關係,而是一章一章的去看教程不少時候都會看蒙,下面就幾個主要知識點作簡單總結,鑑於篇幅和理解深度的緣由,有的地方只能是點到爲止,有說錯地方,還望各位踊躍指正多線程
通俗來說,線程就是任務,系統爲了實現多任務就要引入多線程.
那麼怎麼形容這個任務呢:領導叫你給客戶倒杯水能夠認爲是一個任務,給孩子在網上買一包紙尿褲能夠是一個任務,說人話就是事情,那麼對應到計算機甚至是咱們的嵌入式系統裏面,任務就是:點個燈?發送一串串口數據或者是執行一次復位重啓也能算一個任務.
那麼多線程其實省略了"同時執行"這幾個字,爲何多線程,顯然是爲了執行更多的任務.那有同窗要說:之前咱們不帶系統的時候也能夠作到一個板子作多個事情呀.哈哈,別忘了,這裏面還有一個實時呢,關於這部份內容能夠查看一下關於先後臺系統和實時系統的解析,這裏就不造輪子了框架
其實在單核芯片內部多線程並非同時運行的,而是根據系統調度規則保持在某一個時刻只有一個線程在運行,那有同窗就問了,什麼是調度?咱們能夠理解爲調控和分配,打個比方,春晚有一個小品叫<<裝修>>,黃大錘先拿大錘破磚,再拿小錘摳縫,這個從大錘變到小錘就是一個調度,發現牆破的差很少了,中止大錘活動,小錘上場繼續.對應到計算機上,就是一個任務執行完了,系統自動將當前任務中止,轉而去執行另外一個線程.
中斷不屬於任何一個線程,中斷的優先級大於全部的線程,拿手機去對比:哪怕你立刻要吃雞成功或者王者榮耀正在進行激烈的團戰,只要有電話進來,你的手機都會把遊戲中止,讓你決定是否接聽電話,由於在手機的設定中,接打電話是最高優先級事件,全部的其餘任務都得給這個事件讓路.學習
很好理解,搶佔式就是某一任務很緊急,必需要打斷其餘線程的運行,舉例:你正在吃飯或者正在走路的時候,忽然肚子痛要拉肚子,那這時候吃飯和走路的優先級就沒有這個要去上廁所的優先級高,那麼咱們說:吃飯和走路被上廁所搶佔運行.
而時間片輪轉調度就更好理解:給某一線程分配一個最大運行時間,時間一到,無論如今的任務進行的如何,若是還有同等優先級的任務要執行,就轉去執行這個同等優先級的任務,能夠結合下面寫做業的例子去理解線程
再舉個不形象的例子:語文課和數學課地位同等重要,因此在學校不會有語文老師去搶數學老師的課時,頂多拖下堂.--->這就是時間片輪轉調度,而體育課相比之下數學語文這種"正課"顯得重要,因此不少時候數學老師會跟大家說,這節體育課改上數學.-->優先級搶佔教程
打個比方,上學的時候咱們學習語文數學英語,老師規定做業要這樣寫:寫一分鐘語文,一分鐘的數學,而後再去寫一分鐘英語,這樣不段循環,直到全部的做業都寫完.好等到你開始寫了,先打開語文做業本,找到對應的頁碼和題目,開始寫做業,嘀嘀嘀一分鐘很快到了,你不得不把語文做業本合起來,標記一下寫到了哪裏,而後打開數學做業本,,找到對應的頁碼和題目,開始寫做業,嘀嘀嘀一分鐘又到了,你又不得不合上數學做業本,把頁碼和題目標記起來,開始一樣的動做去寫英語,等到英語的時間到了以後,又得去把語文做業本打開,找到剛剛記錄的頁碼和題目繼續寫.那麼咱們想象一下有三個竹筒,裏面分別裝有語文,數學,英語的做業相關的信息,這個筒子就是線程棧,那這個筒子裏記錄的頁碼和題目就是上下文信息.簡單說來:上下文用於保存和恢復線程運行的狀態和結果等信息,是多線程程序的基石,要實現多任務,就必要有上下文.隊列
上文說了,每個線程的棧區和上下文是分別獨立存儲的.如今有個問題:怎麼肯定線程執行的順序,和對資源訪問的一致性?就比如不對裏有嚴格的紀律和軍銜來限制士兵的活動同樣,rtos系統基於優先級來控制線程的運行順序,那總不能高優先級程序一直在運行吧,低優先級任務得不到執行叫什麼多線程.
放心,這些問題早都有辦法了,高優先級的任務能夠經過調用定時器來達到阻塞當前運行,交出cpu的控制權,當控制權交出後,其餘線程得以運行,那麼用定時器的阻塞有一個問題:假如線程是要獲取某個東西,當時當定時器到期了還沒獲取到或者說不知道這個東西是否是有效的,那怎麼辦?
此時,就要用到信號量或者消息隊列等線程同步或者線程通訊等手段了.
區別在於:線程同步不攜帶數據,而線程通訊攜帶數據.
舉個線程間同步的例子,當某個線程正打算要讀取某個變量的值,忽然被一個高優先級的線程搶佔,這個高優先級的任務正好會改變這個變量的值,而後高優先級線程執行完畢,又輪到這個線程去執行,而後這個變量由於被變掉了,因此可能形成該線程的錯誤運行,這個時候就須要用到線程同步了,在當前程序在訪問或者修改某個變量或者外設的時候,用信號量等手段把操做保護起來,這樣當正好發生了高優先級線程搶佔式運行的時候,可以提示一下:嘿哥們我還沒完事呢,你等會哈,這時候等待仍是不等,等多久就由高優先級去選擇了.通俗的比方:如今有一個公廁只有一個坑,列兵小王正在蹲坑,這時候團長來了,由於不敢得罪團長,小王不得不讓出坑位讓團長先上,有了線程同步以後,至關於公廁上加了一個鎖,小王上廁所的時候,把門一鎖,管你是多大的領導也得給我等着,哈哈
再舉個線程間通訊的例子:食堂有王姨和張姨,王姨管打飯,張姨管打菜,去食堂吃飯先打飯再打菜,若是不創建起一個良好的線程通訊機制,可能就是這樣的:張姨不知道王姨如今是在打菜仍是等本身的飯,王姨打完一個菜就不知道幹嗎了,玩會手機或者跟別人嘮嘮閒嗑都有可能.或者是張姨不知道王姨打飯速度不夠快,使勁裝飯把王姨的工做臺都佔滿了,或者張姨打菜慢王姨打完飯老來問飯好了沒有(不停去訪問某一變量看是否有值),這樣的狀況顯然是不合理的.那麼用線程間通訊,王姨打完飯就在那邊阻塞等飯送過來,張姨裝完飯就放在某個地方,等王姨打完一個菜再裝下一個,這裏面的盤子就至關與消息隊列或者郵箱裏的一份數據,雙方都須要這個數據,而後經過線程間通訊機制正確的執行本身的任務.遊戲
一般在嵌入式編程中,中斷的處理須要遵循快進快出的原則,而不帶rtos系統由於沒有多任務編程的概念,幾乎不會採用上半部和下半部編程(某些狀態機框架能夠實現),通俗來講:上半部就是獲得數據,下半部就是處理數據,像這樣把數據的產生和數據的處理分紅上下兩層的方式就叫上半部和下半部,因此要是如今上半部和下半部編程,最好就是採用多線程編程,由於可讓一個線程用消息隊列或者郵箱等方式阻塞在數據接收的地方去等待數據過來,在阻塞期間不影響其餘線程的運行.事件