💓個人主頁:mooridy
💓專欄地址:Linux
關注我🌹,和我一起學習更多計算機的知識!
🔝🔝🔝
什么是線程
程序中的一個執行路線就叫做線程
- 一個進程至少要有一個執行線程,單個進程本身就是一個執行流,所以單個進程某種意義上也是一個線程(是主線程).線程在進程內部運行,本質是在進程地址空間內運行
- 在Linux操作系統下,線程就是輕量化進程,線程是沒有獨立的地址空間的PCN結構,線程的資源是主線程共享給它們的。
![[Pasted image 20250325104542.png]]
線程的優點
? 線程的創建時間比進程快
因為進程在創建的過程中,還需要資源管理信息,比如內存管理信息、文件管理信息,而線程在創建的過程中,不會涉及這些資源管理信息,而是共享它們;
? 同一個進程內的線程切換比進程切換快
因為線程具有相同的地址空間(虛擬內存共享),這意味著同一個進程的線程都具有同一個頁表,同一個虛擬地址空間,那么在切換的時候不需要切換頁表。同時也不會擾亂處理器的緩存機制。
? 線程之間的數據交互效率更高
由于同一進程的各線程間共享內存和文件資源,那么在線程之間數據傳遞的時候,就不需要經過內核了;
線程異常
線程是進程的執?分?,線程出異常,就類似進程出異常,進?觸發信號機制,會終?整個進程,該進程內的所有線程也就隨即退出。
線程與進程的比較
? 進程是資源分配的單位,線程是 CPU 調度的單位;
? 進程擁有一個完整的資源平臺,而線程只獨享必不可少的資源,如寄存器和棧、線程ID、信號屏蔽字、調度優先級
進程的多個線程共享
同?地址空間,因此Text Segment
、Data Segment
都是共享的,如果定義?個函數,在各線程中都可以調?,如果定義?個全局變量,在各線程中都可以訪問到,除此之外,各線程還共享以下進程資源和環境:
?件描述符表、每種信號的處理?式(SIG_ IGN、SIG_ DFL或者?定義的信號處理函數)、當前?作?錄、用戶id和組id
主線程的PID和LWP相同,CPU調度時是在看LWP,而不是PID,線程的PID和主線程相同,自己獨有LWP
Linux線程控制
POSIX線程庫
由于pthred是第三方庫
所以編譯時要加上-lpthread的字段
如何創建線程
功能:創建?個新的線程原型:int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg);參數:thread:返回線程IDattr:設置線程的屬性,attr為NULL表?使?默認屬性start_routine:是個函數地址,線程啟動后要執?的函數arg:傳給線程啟動函數的參數返回值:成功返回0;失敗返回錯誤碼
如何終止線程
-
從線程函數return。這種?法對主線程不適?,從main函數return相當于調?exit。(大多數情況)
-
線程可以調?pthread_ exit終???。
功能:線程終?
原型:void pthread_exit(void *value_ptr);參數:value_ptr: 指向退出狀態的指針,可傳遞任意類型數據value_ptr不要指向?個局部變量。
返回值:?返回值,跟進程?樣,線程結束的時候?法返回到它的調?者(??)
- ?個線程可以調?pthread_ cancel終?同?進程中的另?個線程。
功能:取消?個執?中的線程原型:int pthread_cancel(pthread_t thread);參數:thread:線程ID返回值:成功返回0;失敗返回錯誤碼
如何進行線程等待
功能:等待線程結束原型int pthread_join(pthread_t thread, void **value_ptr);參數:thread:線程IDvalue_ptr:它指向?個指針,后者指向線程的返回值返回值:成功返回0;失敗返回錯誤碼
假如不進行線程等待,可能會出現類似于僵尸進程的問題
調?該函數的線程將掛起等待,直到id為thread的線程終?。
如何進行線程分離
- 默認情況下,新創建的線程是joinable的,線程退出后,需要對其進?pthread_join操作,否則?法釋放資源,從?造成系統泄漏。
- 如果不關?線程的返回值,join是?種負擔,這個時候,我們可以告訴系統,當線程退出時,?動釋放線程資源。
int pthread_detach(pthread_t thread);
pthread_self()
函數可以返回當前線程的線程ID,所以假設我們想要當前線程與主線程脫離關系,可以這樣寫: ```
pthread_detach(pthread_self());
線程ID本質
首先,pthread_create的返回值是線程ID.
線程ID的本質是一個地址,pthread庫是一個動態庫,是第三方庫,這個庫會被映射到進程的地址空間的共享區中,而線程ID所指的地址則是pthread這個庫層面上,線程集合的起始地址
![[Pasted image 20250327113215.png]]
線程棧
- 這種stack不能動態增?,?旦?盡就沒了,這是和?成進程的fork不同的地?。
- 對于?線程的 stack ,它其實是在進程的地址空間中map出來的?塊內存區域,原則上是線程私有的,但是同?個進程的所有線程?成的時候,是會淺拷??成者的
task_struct
的很多字段,如果愿意,其它線程也還是可以訪問到的,于是?定要注意。