1.執行緒(Thread)概觀
執行緒到底是什麼?「執行緒」這個名詞是「控制執行緒」的縮寫,而控制執行緒,簡
單來說,就是在同一個程式之中,與其他控制執行緒間彼此獨立地執行程式碼的區域。
多緒程式的設計,主要在利用使用者的閒置時間及提昇程式的反應時間,例如對一個視
窗程式而言,沒有人會希望當程式開始執行某些動作時便失去反應,也就是說一旦程式
開始執行便得等到執行完畢才能將之關閉,這是大多數人都無法忍受的,所以通常都有
一個執行緒負責處理使用者下達的命令,另一個執行緒則負責
gui的輸出入,隨時等待使
用者的下一個動作。
另一個常見的例子就是server,
server通常有一個緒專們負責監聽來自client的請求,一但
client的
請求被接受,
server便再生出一個緒來專們處理這個client的請求,原先的緒則又
回到監聽的狀態,如此
server才有辦法同時處理來自多個client的請求,又不至於降低系
統的效能。如果用
multi-process的方式,每一個client的請求,os便執行一個server
的process來處理,相信系統撐不了多久就當機了。
2.控制執行緒
控制執行緒聽起來像是個很複雜的科技名詞,但是其實是個很簡單的概念:它是程
式在執行時的路徑。這決定了什麼程式碼會被執行:是否
if 區塊被執行?或是
else 區塊
被執行?while
迴圈執行了幾次?如果我們從待辦事項的清單上執行工作(就像是電腦執
行程式),那麼我
們做了哪些步驟,以及我們執行的順序,就是我們的執行緒。
使用多控制執行緒,就像是從兩張一模一樣的待辦事項列表中,把工作拿出來執行一樣
。我們執行工作,還是依照待辦事項列表中的正確順序來做,只是當我們做某個列表
的工作做到一半,覺得厭煩的時候,我們可以先跳到另一個列表去做,等會要回去做
原列表的工作的時候,會從剛才離開第一個列表的地方繼續做下去。
另外補充的是多緒和多工的不同,在於緒(thread)只是程式或程序(process)的一個片段,
程序之間並不享有相同的變數,但是緒之間的變數空間是一樣的(因為屬於同一個程序)
,也因此
cpu在執行多緒程式時,並不需要作記憶體的切換(context
switching),cpu的負擔
比較不會那麼重,所以也有人把緒稱為輕量程序(lightweight
process)。
所謂的多執行緒
(multithread),指的是在同一個行程裡,可以擁有一個以上的執行單元,
彼此分別獨立執行。相對的,傳統的UNIX
行程,可以視為是內部只有一個執行緒的行程。
我們先定義兩個名詞:
並行性
(Concurrency):指的是同時至少有兩個以上的執行緒在運行
(不見得這些執行緒會
同時執行)。
平行性
(Parallelism):指的是至少有兩個以上的執行緒,真的同時被執行。
3. 使用執行緒,有以下幾點好處:
a.有效率地使用多處理器硬體平台。
b.可以讓多個執行緒,在一個行程內被平行地 (in parallel)
執行
改善程式的結構。
c
如果一個程式內部,有多個彼此獨立的部份,將這些部份各用一個
thread 執行,程式在
結
構上,會比只使用一個 thread
的程式,來得容易維護,了解減少系統資源的使用因為
每個行程都會佔用一段完整的位址空間及作業系統核心裡的許多資源,相較之下,一個
執行緒所佔的系統資源,就比一個行程少的多。因此以一個多執行緒的行程,來代替多
個單執行緒的行程,可以減少系統資源的使用。
d.可以將執行緒與遠端程序呼叫機制 (RPC) 結合。
e.使實作
concurrent RPC server
的工作,變得更為簡單。
f.改善效率。
g.執行緒的產生與執行緒間的同步,都比行程的產生及行程間的同步
overhead 要來得小。
從以上的介紹,可以知道thread好處多多,且可能電腦的資源能夠完整被利用,使電腦的
效能發揮到最大,這樣才是我們所追求的目標。
舉個例子,在桌面上開 "我的電腦",可以檢視磁碟機裡的所有資料夾,與選取某個檔案,
然後複製到另一個磁碟機,會有一個小視窗開啟顯示正在複製檔案。儘管正在複製檔案,
仍然可以操作windows
explorer檢視檔案與資料夾,同樣的也可以啟動一個以上的複製工作,
而這些都是在windows
explorer這支程式的Process,同時正在進行的複製檔
案的工作就是thread
。
Thread的實作&問題:
問題1
在Server端,所拍攝下來的畫面要傳送給client端須經把影片壓縮編碼,然後在client端解
碼的動作,以供使用者監控,這就是監控系統的初步架構。
一開始助教先要求寫一個小程式,讓我們了解thread的功用和在什麼情況下可用thread,
讓程式可在同一個時間同時執行程式。之後要測試時,卻發現板子
故障了,於是助教稍
微修正我們專題的方向,在板子修復之前先
行模擬板子的動作。
板子的動作如下:
PS: Copy=監控畫面被板子壓縮的速度
我們把Server的網路程式稍做修改,模擬檔案傳送且同時壓縮,在傳送過程中為了防止傳
超過COPY的速度,並且控制它copy的速度,所以用count1和count2來比較,用來避免傳送
超過 copy造成錯誤的防呆方法。
且利用Thread當在傳送檔案時,就同時壓縮檔案,若傳送資料的速度大於壓縮資料的速
率,則使程式Sleep,等到兩邊的速度相同時才恢復。
*用此兩種方法就可以來模擬DSP板子,來測試我們的程式是否正確
(程式碼)
COPY的動作
void *gg (
void *)
{ char
block[2048];
int
in,out;
int
nread;
int
count1=0;
in=open("stream1.263",O_RDONLY);
out=open("stremsend.263",O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR);
while((nread = read(in,block,sizeof(block)))>0)
write(out,&block,nread);
count1=nread;
count1=count1++;
pthread_exit(NULL);
}
傳送的動作
pthread_t gg_thread;
pthread_create(&gg_thread,
NULL, gg, NULL);
cli_len =
sizeof(cli_address);
cli_sockfd
= accept(ser_sockfd, (struct sockaddr *)&cli_address, &cli_len);
while((nread
= read(fsend, buf, sizeof(buf))) > 0)
write(cli_sockfd, &buf, nread);
count2=nread;
if
(count1 > count2)
count2=count2+1;
else sleep(3);
close(cli_sockfd);
之後板子修復後,就把之前
所寫的模擬程式拿掉,因為不用再模擬板子的動作了。
問題2
網路程式要跟面板的程式合在一起時,會碰到許多的問題。
控制面板跟撥放面板:
在撥放的畫面時,控制面板就不能使用且不能控制撥放面板,例如我們想停止撥放影片
或預約錄影,故必須使用Thread讓2個面板可同時使用。
(圖一)
(圖二)
(圖一):若沒有使用thread,則主程式去呼叫撥放面板後,其主控權變成撥放面板,當在撥放影片
時,此時的控制面板就無法去使用它。
(圖二):當使用thread,很清楚的可以看到撥放面板和撥放面板可同時使用,這就是使用thread的好
處。
問題3
thread的傳值問題:
因為pthread_create(&client,NULL,client,(void*)char)
,在最後的(void*)char(void*)char
只能傳回一個
值,但我們所寫的程式必須傳回2個值給mainform中,故我們將其中一個變數,宣告成一個陣
列,把另一個變數包含進去。
使兩個變數合成為一個變數。如下所示 :
-------------------------------------主程序------------------------------------------
char *argv[]={NULL,"-o4","-f0","-o4","-o4",bb,"-o4"};
if(ds)
argv[3]="-x";
else
{
expand=0;
argv[3]="-o4";
}
argv[6]="6";
pthread_t
tmndec_thread;………(1)
pthread_create(&tmndec_thread,
NULL,tmndec(void*)argv);………..(2)
-------------------------------------撥放面板程式-----------------------------
void *tmndec(void *argv[])
{
int first, framenum;
int gob;
int argc;
int runtime;
getfilename(argv[6],name);
argc=name[0];
argc=argc-48;
在撥放面板程式中,本來是要傳回2個值 (argc跟argv) 給thread,但thread的指令又只能接
受一個回傳值,這是我們碰到的一個小瓶頸。
之後我們用了一個小技巧,把argc宣告成argv陣列裡面的其中一個變數,如上方綠
色字體,另外argc要減去-48,因為宣告成陣列argc變成ASII
code,所以必須減48
才能變成原來的值。
問題4:
若最後沒有把thread結束時會造成整個系統發生一些bug。當要繼續使用副程式2時會發生問
題。
(圖一)
(圖2)
當要再一次執行副程式2時,因為副程式2還沒結束,所以程式還會再開一個副程式3
(如圖2) ,造成面板
關閉。
|