切換線程時需要保存什么
- 函數需要保存嗎?函數在Flash上,不會被破壞,無需保存。
- 函數執行到了哪里?需要保存嗎?需要保存。
- 全局變量需要保存嗎?全局變量在內存上,無需保存。
- 局部變量需要保存嗎?局部變量在棧里,也是在內存里,只要避免棧不會被破壞即可,局部變量無需保存。
- 運算的中間值需要保存嗎?中間值保存在CPU寄存器里,另一個線程也需要用到寄存器,所以CPU寄存器要保存。
- 函數運行到了哪里:也是一個CPU寄存器,名為“PC”。
總結:CPU寄存器需要保存,保存在線程的棧里。
ARM架構
ARM芯片屬于精簡指令計算機(RISC:Reduced Instruction Set Computor),它所用的指令比較簡單,有如下特點:
- 對內存只有讀、寫指令。
- 對于數據的運算都是在CPU內部實現。
- 使用RISC指令的CPU復雜度小一點,易于設計。
幾條匯編指令
- 讀內存指令:LDR,即Load之意。
- 寫內存指令:STR,即Store之意。
- 加減指令:ADD、SUB
- 跳轉:BL,Branch And Link
- 入棧指令:PUSH
- 出棧指令:POP
加載指令LDR:LDR r0,[addrA],意思是將地址addrA的內容加載到r0里面。
存儲指令STR:STR r0,[addr A],把r0的值存儲到地址addrA上。
加法運算指令(ADD):ADD r0,r1,r2,意思為r0=r1+r2。
減法運算指令(SUB):SUB r0,r1,r2,意思為r0=r1-r2。
寄存器入棧/出棧指令(PUSH/POP)
寄存器入棧(PUSH):PUSH {r3, lr}意思是將寄存器r3和lr寫入內存棧。
- 本質是寫內存STR指令,高標號寄存器寫入高地址的棧里,低標號寄存器寫入低地址的棧里。
- lr即r14,寫入地址為sp-4的內存,然后sp=sp-4。
- r3,寫入地址為sp-4的內存,然后sp=sp-4。
寄存器出棧指令(POP):POP {r3,pc}意思是取出內存棧的數據放入r3和pc中。
- 本質是讀內存LDR指令,高標號寄存器的內容來自高地址的棧,低標號寄存器的內容來自低地址的棧。
- 讀地址為sp的內容存入r3,然后sp=sp+4。
- 讀地址為sp的內容存入pc,然后sp=sp+4。
寄存器別名
PUSH指令=多次調用STR指令,并且會調整SP的值。
BL A:會記錄返回地址,保存在R14里,然后跳轉到A執行,執行完后,PC會跳轉到R14所指向的地址。
初始化棧
IPC
引入IPC,主要是為了兩項功能:
- 線程間互斥
- 休眠-喚醒機制
隊列
隊列里有多個消息塊,消息塊里面可以存儲消息(數據),每個消息塊大小相同。
隊列里有兩個鏈表:Sender List、Receiver List。
掛起線程也就是將線程從就緒鏈表中移出。
再將線程掛到隊列的等待鏈表中。
啟動定時器。
互斥量如何實現
對于互斥變量a
- 關中斷
- 匯編指令:原子地修改a
IPC
消息隊列的讀取都是使用memcpy()。
郵箱的讀取直接賦值即可。
鏈表、定時器、環形緩沖區(讀、寫位置)
信號量的缺點:
- 誰都可以釋放信號量
- 優先級反轉
Mutex解決
- 誰擁有誰釋放
- 優先級繼承
一個互斥量可以被同一個線程多次take
信號不是信號量,是一種異步通知機制。
**信號就是線程的軟件中斷。 **
信號處理流程
信號就是線程的“軟件中斷”,跟“硬件中斷”類似:
要安裝信號處理函數,相當于給硬件中斷提供處理函數。
/* thread1 安裝信號,自定義處理函數 */rt_signal_install(SIGUSR1, thread1_signal_handler);/* thread1 要使能信號,相當于使能硬件中斷,解除屏蔽 */
rt_signal_unmask(SIGUSR1);/* 向thread1發出信號,相當于觸發硬件中斷 */
rt_thread_kill(thread1, SIGUSR1);
什么是塊設備?
有存儲功能:寫入數據到pos位置,再讀pos可以得到一樣的數據。
數據的傳輸單位是:扇區。
掛載
掛載點(path)
文件系統
塊設備