Linux 嵌入式開發 – 並行開發—進程與線程
Contents
Linux 嵌入式開發 – 並行開發—進程與線程
Process概念
- program
- 存放在disk上的指令和數據的有序集合(文件)
- 靜態的
- process
- 執行一個program所分配的資源總稱
- 是program一次執行的總稱
- 動態的,包括創建,調度,執行,死亡
- 有獨立的地址空間
- linux為每個進程創建task_struct
Process 內容
|
|
Process control block
- PID
- process user
- process status / priority
- file description table
Process 類型
- 交互進程:在shell下啟動,可在前臺/後台運行
- 批處理進程:和在終端無關,被提交到一個作業隊列中以便順序執行
- 守護進程:和終端無關,一直在後台運行
Process status
- running / ready
- waiting
- interrupt
- not interrupt
- terminated : 收到signal後可以繼續運行
- zombie : pcb沒有被釋放
殭屍與孤兒
-
殭屍:一個process 使用
fork()建立child,如果child退出(terminated),而父進程沒有呼叫wait/waitpid並回收時,OS進程表中仍然存在子進程的進程控制塊(PCB),長時間保持殭屍狀態會導致resource leak- 簡而言之可以說子進程已死但沒有被回收,且
kill()指令對其無效
- 簡而言之可以說子進程已死但沒有被回收,且
-
孤兒:process fork後,父程序退出,但他的一個或多個子程序還在執行,這些子程序即是孤兒程序,孤兒程序將被init程序(程序號為1的程序)所收養,並由init程序對它們完成狀態收集工作。
-
收割殭屍進程的方法是通過kill命令手工向其父進程發送SIGCHLD信號。如果其父進程仍然拒絕收割殭屍進程,則終止父進程,使得init進程收養殭屍進程。init進程周期執行wait系統調用收割其收養的所有殭屍進程。
為避免產生殭屍進程,實際應用中一般採取的方式是:
- 將父進程中對SIGCHLD信號的處理函數設為SIG_IGN(忽略信號或稱作不註冊handler)-> 子進程死掉會直接被回收
- fork兩次並殺死一級子進程,令二級子進程成為孤兒進程而被init所「收養」、清理

Thread
- process在切換時系統開銷大
- 同一個process中的thread共享相同的空間
- Linux 不區分thread process
特點
- 通常thread指的是共享地址空間的多個任務
- 大大提高了任務切換的效率
- 避免額外的TLB & cache的刷新
thread共享:
- 可執行的命令
- 靜態資料
- 進程中打開的file descriptor
- 當前工作目錄
- user id
- user group id
thread私有:
- tid
- pc & 相關暫存器
- stack & heap
- errno
- priority
- 執行狀態和屬性
Linux thread lib
pthread提供如下基本操作
- 創建
- 回收
- 結束
同步和互斥機制
- 信號量
- 互斥鎖
創建
|
|
- thread 線程對象
- attr 線程屬性,NULL表示默認
- routine線程執行的函數
- arg 傳遞給routine的參數
- 成功返回0
回收
|
|
- thread要回收的對象
- 調用thread阻塞直到thread結束
- *retval接收thread 的返回值
結束
|
|
- 結束當前線程
- retval可以被其他thread通過pthread_join獲取
- thread私有資源將被釋放
範例
|
|
編譯:
|
|
Thread通信 – 同步synchronization
- 由信號量來決定線程是繼續運行還是阻塞
信號量
- 信號量代表某一類資源,其值表示系統中該資源的數量
- 是一個受保護的變數,只能通過三種操作來訪問
- 初始化
- P操作(申請資源)
- V操作(釋放資源)=> 一定會阻塞
P/V操作
-
P(S): if(信號量>0){ 申請資源的任務繼續運行; 信號量的值減1; } else{ 申請資源的任務阻塞 };
-
V(S): 信號值加一 if(有任務在等待資源){ 喚醒等待的任務,讓其讓其繼續運行 }
Posix 信號量
-
posix有兩種信號量
- 無名信號量(基於memory的信號量)=> 用於線程
- 有名信號量 => 可用於線程或是進程
-
pthread庫常用的信號量操作函數:
|
|
初始化
|
|
- 成功返回0,失敗時EOF
- sem指向要初始化的信號量對象
- pshared 0-thread間,1-process間
- val信號量初值
P/V操作
|
|
- 成功返回0,失敗時EOF
- sem指向要初始化的信號量對象
線程同步–範例一
兩個線程同步讀寫緩衝區(生產者與消費者問題)
|
|
|
|
互斥
-
臨界資源 (共享資源)
- 一次只允許一個任務(進程、線程)訪問的共享資源
-
臨界區
- 訪問臨界資源的code
-
互斥機制
- mutex互斥鎖
- 任務訪問臨界資源前,申請鎖,訪問完後釋放鎖
互斥鎖初始化
|
|
- 成功時返回0,失敗返回錯誤
- mutex指向要初始化的互斥鎖對象
- attr互斥鎖屬性,NULL表示缺少屬性
申請鎖
|
|
- 成功時返回0,失敗返回錯誤
- mutex指向要初始化的互斥鎖對象
- 如果無法獲得鎖,任務阻塞
釋放鎖
|
|
- 成功時返回0,失敗返回錯誤
- mutex指向要初始化的互斥鎖對象
- 執行完臨界區必須即時釋放鎖
範例
|
|
編譯:
|
|