process-thread
一、程序的概念:
執行一個程式所分配的資源的總稱,程序是程式的一次執行過程動態的,包括建立、排程、執行和消亡
程式就是我們寫好的程式碼,編譯成可執行檔案後成為程式,存放在硬盤裡面。
但是,當我們點選./a,out去執行的時候,它執行起來:把硬碟程式資料讀到記憶體中,佔用的cpu資源。等等執行所要的資源的總稱,稱為程序。
PCB:程序控制塊
我們的程序是由一個一個程序連結串列的來管理的,這個表叫程序控制塊PCB,裡面有程序標識pid,程序使用者,程序狀態,,優先順序檔案描述符表的資訊。通過唯一標識pid號進行管理,這個pid其實和fd檔案描述符的用法類似,就是一個結構體下標。
一個程序有四種狀態:執行態(正常就是執行態) ,等待態(休眠),停止態()程序被命令中止,殭屍態(程序已經被中止,但是pcb資源沒有被回收)
程序建立
#include <unistd.h>
pid_t fork(void);
建立新的程序,失敗時返回-1
成功時父程序返回子程序的程序號,子程序返回0
通過fork的返回值區分父程序和子程序
子程序繼承了父程序的內容
父子程序有獨立的地址空間,互不影響
若父程序先結束
子程序成為孤兒程序,被init程序收養
子程序變成後臺程序
若子程序先結束
父程序如果沒有及時回收,子程序變成殭屍程序
程序回收:
子程序結束時由父程序回收
孤兒程序由init程序回收
若沒有及時回收會出現殭屍程序
回收全部子程序
#include <unistd.h>
pid_t wait(int *status);
成功時返回回收的子程序的程序號;失敗時返回EOF
若子程序沒有結束,父程序一直阻塞
若有多個子程序,哪個先結束就先回收
status 指定儲存子程序返回值和結束方式的地址
status為NULL表示直接釋放子程序PCB,不接收返回值
回收指定程序:
#include <unistd.h>
pid_t waitpid(pid_t pid, int *status, int option);
成功時返回回收的子程序的pid或0;失敗時返回EOF
pid可用於指定回收哪個子程序或任意子程序
status指定用於儲存子程序返回值和結束方式的地址
option指定回收方式,0 或 WNOHANG
二、執行緒的概念;
由於程序間通訊資料互動非常麻煩且程序開銷非常大。所以我們引入了執行緒的概念。執行緒是輕量級的程序:
linux其實不區分程序和執行緒:他們都是一個task_struct連結串列來管理。
程序右不同的pid號,同一程序下所有執行緒都共享同一個pid。並且就算你不建立執行緒,那麼程序裡面也會有一個執行緒。就是你一個./a.out這個程序,執行mian函式即是一個程序也是一個執行緒。多執行緒下的task_structlm裡面的pid號是一樣的。
執行緒的好處:
大大提高了任務切換的效率
避免了額外的TLB & cache的重新整理
執行緒的建立:
#include <pthread.h>
int pthread_create(pthread_t *thread, const
pthread_attr_t *attr, void *(*routine)(void *), void *arg);
成功返回0,失敗時返回錯誤碼
thread 執行緒物件
attr 執行緒屬性,NULL代表預設屬性
routine 執行緒執行的函式
arg 傳遞給routine的引數 ,引數是void * ,注意傳遞引數格式,
pthread_t pthread_self(void) 檢視自己的TID
建立一個執行緒去處理 void *(*routine)(void *)這個函式,處理完畢,執行緒結束並登出。如果程序結束,那麼所有的執行緒都結束,不管你的程式有沒有執行完。一個執行緒用exit();退出,所有的執行緒都會退出。exit()直接退出程式。
執行緒的回收:
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
成功返回0,失敗時返回錯誤碼
thread 要回收的執行緒物件
呼叫執行緒阻塞直到thread結束
*retval 接收執行緒thread的返回值
執行緒的取消:
int pthread_cancel(pthread_t thread);
取消是停止執行緒但是資源沒有釋放
執行緒的結束:
#include <pthread.h>
void pthread_exit(void *retval);
結束當前執行緒
retval可被其他執行緒通過pthread_join獲取
執行緒私有資源被釋放
——————————————————————————————————————————————
三、執行緒間的同步和互斥
執行緒間的同步:
訊號量
適用於,當某事件發生後,另一個事件才能發生的情況:例如:
我一個執行緒要往一個buf裡面寫資料,我另一個執行緒要讀資料。
肯定要先寫才能讀資料啊,所以我可以定義一個訊號量,起始訊號量為0 ,用於訊號的同步,當我寫好之後我的訊號量+1,這樣就可以讀資料了。讀完訊號量減一。這樣就不能再次讀資料了。
訊號量操作:
1)初始化訊號量:
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int val);
成功時返回0,失敗時EOF
sem 指向要初始化的訊號量物件
pshared 0 – 執行緒間 1 – 程序間
val 訊號量初值
2)訊號量的P/V操作:
#include <semaphore.h>
int sem_wait(sem_t *sem); P操作
int sem_post(sem_t *sem); V操作
成功時返回0,失敗時返回EOF
sem 指向要操作的訊號量物件
執行緒間的互斥:
鎖機制:mutex
適用於:多執行緒訪問共享資源時,對共享資源上鎖。讓其它執行緒不可訪問。以避免出現數據紊亂的情況。
比如我一個執行緒在往一個buf裡面寫資料
我另一個也在往buf裡面寫資料
因為執行緒是並行的,這樣這個資料你永遠都預測不到它長什麼樣子了
一個執行緒申請鎖後必須釋放鎖。
要不然共享資源就變成你家的資源了,別人都用不了。
初始化鎖:
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex,
const pthread_mutexattr_t * attr);
成功時返回0,失敗時返回錯誤碼
mutex 指向要初始化的互斥鎖物件
attr 互斥鎖屬性,NULL表示預設屬性
2)申請鎖
#include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex);
成功時返回0,失敗時返回錯誤碼
mutex 指向要初始化的互斥鎖物件
執行完臨界區要及時釋放鎖
3)釋放鎖
#include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex);
成功時返回0,失敗時返回錯誤碼
mutex 指向要初始化的互斥鎖物件
執行完臨界區要及時釋放鎖
——————————————————————————————————
多程序與多執行緒的比較:
程序:
程序有獨立的地址空間
Linux為每個程序建立task_struct
每個程序都參與核心排程,互不影響
執行緒:
程序在切換時系統開銷大
很多作業系統引入了輕量級程序LWP
同一程序中的執行緒共享相同地址空間
Linux不區分程序、執行緒
多執行緒共享的資源:
一個程序中的多個執行緒共享以下資源:
可執行的指令
靜態資料
程序中開啟的檔案描述符
當前工作目錄
使用者ID
使用者組ID
執行緒間私有的資源:
每個執行緒私有的資源包括:
執行緒ID (TID)
PC(程式計數器)和相關暫存器
堆疊
錯誤號 (errno)
優先順序
執行狀態和屬性
什麼時候適用多程序,什麼時候使用多執行緒:
1、首先你得理解多程序的怎麼執行的?它是怎麼做到多執行緒並行的。
這個問題其實,多執行緒是假的並行,根據時間片,一會執行這個執行緒,一會執行另一個執行緒。其實他是一個時間處理一條語句,然後時間片輪轉著去執行各執行緒的語句。這比較費時間。
類似於:單核的多程序
時間片輪詢程序排程演算法,它的思想簡單介紹如下: 在作業系統的管理下,所有正在執行的程序輪流使用CPU,每個程序允許佔用CPU的時間非常短(比如10毫秒),這樣使用者根本感覺不出來CPU是在輪流為多個程序服務,就好象所有的程序都在不間斷地執行一樣。但實際上在任何一個時間內有且僅有一個程序佔有CPU及CPU的運算器。
2多程序的實現:
要是你的程序數小於cpu的核數。比如我exynos4412這個板子是4核的,買手機的時候會看的引數就是什麼四核,八核。就是cpu的個數。要是你的程序數小於cpu的核數。那麼你的程序就可以做到真正的併發。就是在同一時間片下,會有1,2,3,4等程序同時執行程式的可能。要是程序數大於ccpu核數,那麼也將採用 ——時間片輪詢程序排程演算法。不過有四各時間片可以排程。
結合上面的多程序多執行緒的實現,以及執行緒核程序的特性:
如果你想要少消耗資源:多執行緒
如果你兩個程式要頻繁互動資料:多執行緒
如果你想要兩程式間資料少互動為了安全:多程序
如果你想要程式跑的快:多程序
選擇多程序核多執行緒要更據實際來選。
比如我做到安防監控的item。我絕對一個選多程序核多執行緒一起用:
我資料有上行把zigbee的資料交給web。資料下行有web傳送命令到硬體實現控制。
那麼這上行,和下行完全不用資料互動,而且我的開發板有足夠多的空間,而且總共的程序有:cgi 上下行。好像才三個。不過好像還有boa,那這樣也才4個程序。我開發板是4核的牛逼。所以在總的A9框架上我選擇fork多程序。
然後我資料採集程序要採集很多一個的資料,這時候我就採用多執行緒。nice————
