|
1、進程和線程的區別% Z3 M" t# S) V2 a ~0 j" t
進程的目的就是擔當分配系統資源(CPU時間、內存等)的基本單位。線程是進程的一個執行流,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。一個進程由幾個線程組成,線程與同屬一個進程的其他的線程共享進程所擁有的全部資源。
) A: }; G5 \/ X& e8 V, u
- c) p j4 S t4 J地址空間:進程有獨立的地址空間,包括文本區域(text region)、數據區域(data region)和堆棧(stack region);一個進程崩潰后,在保護模式下不會對其它進程產生影響;線程只是一個進程中的不同執行路徑,線程有自己的堆棧和局部變量(在運行中必不可少的資源),但線程之間沒有單獨的地址空間,一個線程死掉就等于整個進程死掉。同一進程內的線程共享進程的地址空間。9 w2 P. G$ K/ H6 r1 q
8 b$ }/ I& F# V" y" w
通信:進程間通信IPC,線程間可以直接讀寫進程數據段(如全局變量)來進行通信——需要進程同步和互斥手段的輔助,以保證數據的一致性。
. o5 @, ~& `6 H7 a7 v
% p7 F' I+ E2 q8 C8 z4 g調度和切換:線程上下文切換比進程上下文切換要快得多。# \4 g5 U% D: [- I; r$ F7 n: G
0 s1 Y: G5 T& v! s7 V9 U2 n0 P
在多線程OS中,進程不是一個可執行的實體。
( P# ]. j9 Q2 {9 o/ N# d6 R
7 n$ t$ R. ?9 F3 G# W# Y% Q地址空間:進程內的一個執行單元;進程至少有一個線程;它們共享進程的地址空間;而進程有自己獨立的地址空間;
) w5 K% v+ P# D6 U( D9 V' U5 i' h
, C+ q, ?: |* l" G資源擁有:進程是資源分配和擁有的單位,同一個進程內的線程共享進程的資源+ d0 J# L' L5 p8 m Q' n- G5 s
7 S$ N$ \( X+ w) a1 u# T
線程是處理器調度的基本單位,但進程不是.) u" `0 U+ @% a f0 I% }1 R
7 `; H7 d9 t/ O4 I) D# M
二者均可并發執行.
" \0 X, K* O7 e/ @% o
8 p2 F( S0 T& p2、使用線程原因8 Q8 h/ ^! C# _9 E1 ]+ ?, g/ ^
在Linux系統下,啟動一個新的進程必須分配給它獨立的地址空間,建立眾多的數據表來維護它的代碼段、堆棧段和數據段,這是一種"昂貴"的多任務工作方式。而運行于一個進程中的多個線程,它們彼此之間使用相同的地址空間,共享大部分數據,啟動一個線程所花費的空間遠遠小于啟動一個進程所花費的空間,而且,線程間彼此切換所需的時間也遠遠小于進程間切換所需要的時間。
- z% i+ X$ a* B& N; m 線程間方便的通信機制。對不同進程來說,它們具有獨立的數據空間,要進行數據的傳遞只能通過通信的方式進行,這種方式不僅費時,而且很不方便。線程則不然,由于同一進程下的線程之間共享數據空間,所以一個線程的數據可以直接為其它線程所用,這不僅快捷,而且方便。
4 u) h/ [; d; N3 b
C* p& l' k9 y, Q- |$ h# C4 H( c5 O2 s4 J( c2 c! j& |
3、線程操作的函數* |0 @: y+ R# A) p- }! {: m
#include <pthread.h>
& w; p( }& I- j; a' hint pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*func) (void *), void *arg); + \$ P0 |4 T' |9 {
int pthread_join (pthread_t tid, void ** status); & c# X' `' ~8 S9 v0 S
pthread_t pthread_self (void);
! X% G( E: `% T6 \- Y3 W2 ^int pthread_detach (pthread_t tid); 9 V3 v, b4 m2 R6 s1 b9 G
void pthread_exit (void *status);
9 o* V; p: b4 q" j$ [% U3 q$ f4 H7 u& u" r
pthread_create:用于創建一個線程,成功返回0,否則返回Exxx(為正數)。3 C# W g( j' c, H6 P
pthread_t *tid:線程id的類型為pthread_t,通常為無符號整型,當調用pthread_create成功時,通過*tid指針返回。
6 o# b; I1 ]' t" [' L- M( o$ p1 E
' W) K- |' Q% jconst pthread_attr_t *attr:指定創建線程的屬性,如線程優先級、初始棧大小、是否為守護進程等。可以使用NULL來使用默認值,通常情況下我們都是使用默認值。/ l" r/ ]! ^$ m+ S" P6 G6 \8 ~
2 y% W0 {1 |* Z9 Y% ?: g' S6 t# Q
void *(*func) (void *):函數指針func,指定當新的線程創建之后,將執行的函數。
% l4 y4 f: t* o1 y& @! J- J" L" x7 ~; D2 a0 W9 Y
void *arg:線程將執行的函數的參數。嵌入式系統學習意義氣嗚嗚吧久零就易,如果想傳遞多個參數,請將它們封裝在一個結構體中。7 R" u' ]3 F' ]5 B- ?. [& D
/ A& b9 f3 _' }) o/ jpthread_join:用于等待某個線程退出,成功返回0,否則返回Exxx(為正數)。
7 N2 G+ H% @. G2 z/ Xpthread_t tid:指定要等待的線程ID* g2 B' |9 M7 i0 }
' M- Q7 f+ N1 Y* l. \
void ** status:如果不為NULL,那么線程的返回值存儲在status指向的空間中(這就是為什么status是二級指針的原因!這種才參數也稱為“值-結果”參數)。/ Z2 f1 f4 `/ L/ f0 S$ l
! f+ @3 p% [, p i
pthread_self:用于返回當前線程的ID。8 \% u- ]$ i! h/ n) V
pthread_detach:用于是指定線程變為分離狀態,就像進程脫離終端而變為后臺進程類似。成功返回0,否則返回Exxx(為正數)。變為分離狀態的線程,如果線程退出,它的所有資源將全部釋放。而如果不是分離狀態,線程必須保留它的線程ID,退出狀態直到其它線程對它調用了pthread_join。
2 i5 J) d8 }( P6 f5 `; Zpthread_exit用于終止線程,可以指定返回值,以便其他線程通過pthread_join函數獲取該線程的返回值。! Z. c. N. D5 i8 D
void *status:指針線程終止的返回值。& ]5 v# Q. |5 c
- _) ~' X. b( n4、線程間互斥
' ]- y- @5 K7 u0 }7 ?2 S 使用互斥鎖(互斥)可以使線程按順序執行。通常,互斥鎖通過確保一次只有一個線程執行代碼的臨界段來同步多個線程。互斥鎖還可以保護單線程代碼。; r F1 [2 _8 x; s4 ^/ i
int pthread_mutex_lock(pthread_mutex_t * mptr); & x5 Y# J& R0 P) `: ]
int pthread_mutex_unlock(pthread_mutex_t * mptr);# A6 k% f3 y! E4 y2 b
# U, Y3 Q0 ~: F. l* H/ Q @先聲明一個pthread_mutex_t類型的變量,用作下面兩個函數的參數。在對臨界資源進行操作之前需要pthread_mutex_lock先加鎖,操作完之后pthread_mutex_unlock再解鎖。
' Y/ _; t* u* W
7 I2 H2 |0 d2 W6 D% \- e" h* {$ [/ ?
5、線程間同步
; ?2 r9 Y, m7 W, K9 H條件變量:使用條件變量可以以原子方式阻塞線程,直到某個特定條件為真為止。條件變量始終與互斥鎖一起使用。對條件的測試是在互斥鎖(互斥)的保護下進行的。
. J9 k$ G0 S" j# d G6 W#include <pthread.h> 0 f8 w$ ^! f6 r- I
int pthread_cond_wait(pthread_cond_t *cptr, pthread_mutex_t *mptr);
: I# ~$ K" e3 y R* |7 k1 k; tint pthread_cond_signal(pthread_cond_t *cptr); % H. U6 i) a; c0 e6 r
//Both return: 0 if OK, positive Exxx value on error. [- [( | r) o# n
& V; F8 G( h* n1 _pthread_cond_wait用于等待某個特定的條件為真,pthread_cond_signal用于通知阻塞的線程某個特定的條件為真了。在調用者兩個函數之前需要聲明一個pthread_cond_t類型的變量,用于這兩個函數的參數。
. c* x& W9 ^6 P% b/*
8 l" _% c# {) @/ G是否熟悉POSIX多線程編程技術?如熟悉,編寫程序完成如下功能: # j% l5 A( w6 I: k( W! {
1)有一int型全局變量g_Flag初始值為0;
% X2 F/ n3 Y4 V. ^0 K1 B 2)在主線稱中起動線程1,打印“this is thread1”,并將g_Flag設置為1 & O& k5 w X F
3)在主線稱中啟動線程2,打印“this is thread2”,并將g_Flag設置為2
) ?6 X9 {2 B; k7 m; p% Y 4)線程序1需要在線程2退出后才能退出
( o+ m! j3 l$ [( f 5)主線程在檢測到g_Flag從1變為2,或者從2變為1的時候退出
: l" K# F) j' T: j |
|