版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
內(nèi)容提要9:401/267第六章進程控制6.1進程概述6.2進程操作6.2.1進程創(chuàng)建6.2.2進程等待6.2.3進程的終止6.2.4
system函數(shù)6.2.5進程的同步?第六章進程控制9:402/267
本章首先介紹Linux下進程控制的相關(guān)內(nèi)容;然后介紹
Linux平臺下進程的操作,包括進程的創(chuàng)建、等待、終止、同步、system函數(shù)的操作;最后結(jié)合具體的項目案例,
闡述進程的相關(guān)操作的具體應(yīng)用。本節(jié)學(xué)習(xí)目標(biāo):√進程的創(chuàng)建√進程的等待√進程的終止√進程的同步√system函數(shù)6.1進程概述9:403/267
進程是操作系統(tǒng)中重要的概念。理解和掌握進程控制,是進行Linux下系統(tǒng)編程的關(guān)鍵。進程是具有一定功能的可并發(fā)執(zhí)行的程序在數(shù)據(jù)集合上的運行過程。進程和程序是與本質(zhì)的區(qū)別的。進程是動態(tài)的,是程序運行和資源分配的最小單位,包括進行的創(chuàng)建、運行、調(diào)度和消亡的整個過程;而程序是靜態(tài)的,是存儲在磁盤上的指令的集合,本身不擁有任何資源,只有用戶啟動該程序時候,它才啟動對應(yīng)的進程,程序才運行起來并占有相應(yīng)的系統(tǒng)資源。6.1進程概述9:404/267
在用戶看來,Linux是多任務(wù)的操作系統(tǒng),在同一時間內(nèi)可以同時運行多個任務(wù);對系統(tǒng)而言,Linux的多任務(wù)并不是真正的在同時間內(nèi)可以并行多個任務(wù),而是虛假的多任務(wù)同時執(zhí)行。那么Linux是如何實現(xiàn)多任務(wù)的同時執(zhí)行呢?Linux操作系統(tǒng)用時間片的方式實現(xiàn)多任務(wù)的同時執(zhí)行,每個任務(wù)輪流的占用CPU的一個時間片,而每個
任務(wù)可以頻繁的得到時間片執(zhí)行各自的任務(wù),由于單個時間片和宏觀上的時間相比很小,每個任務(wù)占用的時間片都很短,對用戶而言感覺不到多個任務(wù)的頻繁切換,如同多個任務(wù)同時在運行的情況。6.1進程概述9:405/267
一般而言,一個進程執(zhí)行一個獨立的任務(wù),也可以執(zhí)行多個任務(wù)。有時候,為了提高程序執(zhí)行的效率,一個任務(wù)可以被多個進程同時執(zhí)行,并發(fā)運行執(zhí)行任務(wù),這就是并發(fā)程序。執(zhí)行并發(fā)程序的多個進程需同步運行,進程之間相互獨立,也可以進行進程間的通信,比如不同進程使用相同的資源時候,會發(fā)生資源使用沖突。各個進程也需要相互合作,比如一個進程需要等待另一個進程運行出結(jié)果后,才會繼續(xù)運行。6.1進程概述9:406/267
在Linux操作系統(tǒng)中,進程被稱為進程控制塊(ProcessControl
Block,簡稱PCB)。進程控制塊PCB中包括了進程的描述信息、控制信息、資源信息等,這些信息供系統(tǒng)調(diào)用和進程執(zhí)行中自身使用,比如進程的ID,被稱作進程標(biāo)識符,是進程的身份證號碼,在系統(tǒng)中進程ID唯一地標(biāo)志一個進程,不會重復(fù)。多個進程可以合起來組成進程組,這樣就可以對進程批量操作,例如向進程組發(fā)送信號就可以實現(xiàn)向每個進程發(fā)送信號的功能。進程在運行過程中可以根據(jù)需要動態(tài)的產(chǎn)生子進程和結(jié)束進程。6.1進程概述9:407/267
用戶啟動程序后,系統(tǒng)就會啟動相應(yīng)的進程運行,進程在運行的過程中會處于不同的狀態(tài):運行狀態(tài)、等待調(diào)用和睡眠狀態(tài)。運行狀態(tài)是指進程占有CPU,正在執(zhí)行進程中;等待調(diào)用狀態(tài)是指進程正在等待獲得CPU;睡眠狀態(tài)是指進程等待某個事件發(fā)生,當(dāng)前不會處理任何事情。6.1進程概述9:408/267
多個程序被用戶啟動后,會啟動多個進程來完成對應(yīng)的任務(wù)。多個進程同時運行過程中會搶占資源和按照任務(wù)邏輯順序地執(zhí)行,這就要求進程間通信的同步和處理好沖突問題。解決進程間通信同步和沖突的方法有管道、信號量、共享內(nèi)存和消息隊列等。
進程運行過程都要占用一定的內(nèi)存區(qū)域,此區(qū)域用于保存進程運行過程中所用的變量和程序代碼。進程運行過程中具有獨立性,所以當(dāng)一個進程運行中出現(xiàn)錯誤時,不會影響到另外其他進程的運行過程,同時改變一個進程中的內(nèi)存中的數(shù)據(jù),只會影響本進程的內(nèi)部狀態(tài),不會對其他進程產(chǎn)生不良影響,這也是Linux系統(tǒng)穩(wěn)定性的重要原因。6.2進程操作9:409/267
在Linux系統(tǒng)中,進程操作主要是指通過系統(tǒng)函數(shù)和庫函數(shù)的調(diào)用,對進程進行創(chuàng)建、等待、終止和同步等操作,下面給出具體介紹。6.2.1進程創(chuàng)建9:4010/267
在Linux系統(tǒng)中,創(chuàng)建進程的方式有兩種:操作系統(tǒng)創(chuàng)建和父進程創(chuàng)建。操作系統(tǒng)創(chuàng)建的進程是平等關(guān)系,相互
間不存在繼承關(guān)系;父進程創(chuàng)建的子進程不是平等關(guān)系,相互間存在資源繼承關(guān)系。父進程創(chuàng)建的子進程,又可
以創(chuàng)建子進程,從而形成一個進程家族,子進程繼承了
父進程的所有資源,這類進程通常稱為用戶進程;在系
統(tǒng)啟動時,Linux操作系統(tǒng)會創(chuàng)建一些管理和分配系統(tǒng)資源的進程,這類進程稱為系統(tǒng)進程。1創(chuàng)建進程函數(shù)fork9:4011/267
系統(tǒng)創(chuàng)建進程的通用方法是使用函數(shù)fork,系統(tǒng)通過調(diào)用它來完成進程的創(chuàng)建工作。在Linux系統(tǒng)終端中使用幫助命令“man
fork”,得到函數(shù)的信息如下:#include
<unistd.h>pid_t
fork(void);1創(chuàng)建進程函數(shù)fork9:4012/267
該函數(shù)的返回類型為整型,用于創(chuàng)建一個新進程。創(chuàng)建進程后,若是父子進程會爭奪CPU,先搶到者先執(zhí)行,
另外一個進程掛起等待;若是需要父進程等待子進程執(zhí)
行完畢后繼續(xù)執(zhí)行,則需要在執(zhí)行fork操作后調(diào)用wait或waitpid,這樣父子進程會同時執(zhí)行程序。多個進程執(zhí)行同一個程序效果不大,所以子進程在fork后通過調(diào)用exec函數(shù)執(zhí)行其它程序。若不是父子進程,而是操作系統(tǒng)創(chuàng)
建的進程,那么進程之間的關(guān)系式平等關(guān)系。
若在父進程中函數(shù)成功調(diào)用后返回子進程的ID號;若在
子進程中函數(shù)成功調(diào)用后返回0;否則調(diào)用失敗則返回-1。2創(chuàng)建進程函數(shù)vfork9:4013/267
系統(tǒng)創(chuàng)建進程的另一個方法是使用函數(shù)vfork,系統(tǒng)通過調(diào)用它來完成進程的創(chuàng)建工作。在Linux系統(tǒng)終端中使用幫助命令“man
vfork”,得到函數(shù)的信息如下:#include
<unistd.h>#include
<sys/types.h>pid_t
vfork(void);2創(chuàng)建進程函數(shù)vfork9:4014/267該函數(shù)的返回類型為整型,也是用于創(chuàng)建一個新進程。與fork相比,vfork函數(shù)的功能和參數(shù)說明和fork函數(shù)類似,但也有自己的獨特之處,主要有兩點不同:第一,fork方
法創(chuàng)建的子進程,是父進程的完全拷貝,這樣的子進程獨立父進程,有良好的并發(fā)性能;而vfork方法創(chuàng)建的子進程,不是父進程的完全拷貝,而是和父進程共享地址空間,子進程需要完全運行在父進程的地址空間上,子進程對地址空間的數(shù)據(jù)修改同樣會影響到父進程。2創(chuàng)建進程函數(shù)vfork9:4015/267
第二,vfork方法創(chuàng)建的子進程會優(yōu)先運行,當(dāng)它執(zhí)行完
exit之后或調(diào)用exec后,父進程才可以運行;而fork方法創(chuàng)建的子進程是否優(yōu)先運行,取決于系統(tǒng)的調(diào)度算法。
基于這兩點不同,可以看出vfork方法不會拷貝父進程的地址空間,會節(jié)省系統(tǒng)的大量開銷,運行速度也會很快。3綜合示例9:4016/267
在本節(jié)最后,通過利用fork和vfork函數(shù)進行系統(tǒng)調(diào)用,來演示如何創(chuàng)建一個新進程,加強對進程控制的理解。如fork創(chuàng)建進程的范例6-1和vfork創(chuàng)建進程的范例6-2所示。例6-1
my_fork.c/****my_fork.c***/例6-2
my_vfork.c/****my_vfork.c***/在VIM編輯器中具體闡述代碼在eclipse集成開發(fā)環(huán)境IDE中編譯、調(diào)試、運行代碼6.2.2進程等待9:4017/267
在Linux系統(tǒng)中,當(dāng)有多個進程同時運行時,進程間需要協(xié)作工作,可能用到進程等待的操作。進程間的等待包括父子進程間的等待和進程組內(nèi)成員間的等待。1進程等待9:4018/267
進程等待有兩種方法:wait和waitpid。,系統(tǒng)通過調(diào)用它們來完成進程的等待工作。在Linux系統(tǒng)終端中使用幫助命令“man
wait”,得到函數(shù)的信息如下:#include
<sys/types.h>#include
<sys/wait.h>pid_t
wait(int
*status);pid_t
waitpid(pid_t
pid,
int
*status,
int
options);1進程等待9:4019/267
wait:該函數(shù)的返回類型為整型,專用于等待子進程。
status參數(shù)是個整型的指針,用于存放子進程的結(jié)束狀態(tài)。當(dāng)wait被調(diào)用后,父進程被掛起,直到子進程結(jié)束后返回。若wait調(diào)用的父進程沒有子進程,返回失敗。調(diào)用成功時,返回等待狀態(tài)進程的ID號;調(diào)用失敗時,返回為-1。1進程等待9:4020/267
waitpid:該函數(shù)的返回類型為整型,調(diào)用更靈活,用來等待指定的進程。status參數(shù)是個整型的指針,用于存放子進程的結(jié)束狀態(tài)。pid參數(shù)是個整型參數(shù),用于指定所等待的進程,pid大于零表示等待進程id為pid所指定值的子進程;pid等于零表示等待進程組id等于發(fā)出調(diào)用進程的進程組id的子進程;pid等于-1表示等待所有子進程,等價于wait調(diào)用;pid小于-1表示等待進程組id為pid的絕對值的子進程。options參數(shù)是個整型參數(shù),用于指定進程所做的操作,取值為0表示進程掛起等待結(jié)束;取值為
WNOHANG表示不使進程掛起而即刻返回;取值為
WUNTRACED表示進程已經(jīng)結(jié)束并返回。調(diào)用成功時,返回等待狀態(tài)進程的ID號;調(diào)用失敗時,返回為-1。2綜合示例9:4021/267
在本節(jié)最后,通過利用wait和waitpid函數(shù)進行系統(tǒng)調(diào)用,來演示如何等待一個進程,加強對進程控制的理解。如wait和waitpid進程等待的范例6-3所示。例6-3
my_wait.c/****my_wait.c***/在VIM編輯器中具體闡述代碼在eclipse集成開發(fā)環(huán)境IDE中編譯、調(diào)試、運行代碼6.2.3進程終止9:4022/267
在Linux系統(tǒng)中,進程的終止表示進程退出運行。進程的退出方法有正常退出和異常退出兩種。不管是何種方式終止進程,最終都會執(zhí)行內(nèi)核中用于關(guān)閉該進程打開的文件描述符并釋放系統(tǒng)資源的同一段代碼。1進程正常終止9:4023/267
進程正常終止的方法包括執(zhí)行exit函數(shù)、_exit函數(shù)和在主函數(shù)中執(zhí)行return。系統(tǒng)通過調(diào)用它們來完成進程的正常終止工作。在Linux系統(tǒng)終端中使用幫助命令“man
3exit”和“man
2
exit”,得到函數(shù)的信息如下:#include
<stdlib.h>void
exit(int
status);#include
<unistd.h>void
_exit(int
status);1進程正常終止9:4024/267
exit:該函數(shù)的返回類型為空,用于正常終止進程。status參數(shù)是個整型參數(shù),用于存放進程的退出狀態(tài)。
_exit:該函數(shù)和exit函數(shù)的功能和參數(shù)類似,其區(qū)別有兩點:第一,exit和_exit函數(shù)的頭文件聲明位置不同,分別為頭文件stdlib.h和unistd.h中;第二,exit函數(shù)執(zhí)行完相關(guān)操作后將控制權(quán)返回給內(nèi)核,而_exit函數(shù)執(zhí)行完操作
后將控制權(quán)即刻交給內(nèi)核。
return:該語句執(zhí)行完后正常退出進程,它和exit、_exit兩個函數(shù)的區(qū)別有兩點:第一,exit和_exit二者都是函數(shù),帶有參數(shù),而return函數(shù)體中執(zhí)行完后的一個返回語句;
第二,exit和_exit函數(shù)執(zhí)行完相關(guān)操作后將控制權(quán)交給內(nèi)
核,而return將控制權(quán)返回給調(diào)用者。2進程異常終止9:4025/267
進程異常終止的方法包括執(zhí)行abort函數(shù)和進程收到結(jié)束信號如SIGABRT等。系統(tǒng)通過調(diào)用它們來完成進程的異
常終止工作。在Linux系統(tǒng)終端中使用幫助命令“manabort”,得到函數(shù)的信息如下:#include
<stdlib.h>void
abort(void);2進程異常終止9:4026/267
abort:該函數(shù)的返回類型為空,用于異常終止進程。
abort函數(shù)和exit和_exit函數(shù)的區(qū)別是:abort異常終止進程,進程的文件描述符沒有關(guān)閉和占用的資源沒有釋放;
exit和_exit函數(shù)正常終止進程,進程的文件描述符正常關(guān)閉和占用的資源正常釋放。
進程異常終止會出現(xiàn)僵死進程。僵死進程是這樣產(chǎn)生的:父進程fork子進程后,沒有調(diào)用wait或waitpid函數(shù)等待子進程的結(jié)束,而子進程運行完后又先于父進程提前終止,如此,子進程就進入僵死狀態(tài)。僵死進程會一直占用系
統(tǒng)資源,并且一直保持下去,造成資源浪費。3綜合示例9:4027/267
在本節(jié)最后,通過利用正常和異常終止進程函數(shù)進行系統(tǒng)調(diào)用,來演示如何終止一個進程,加強對進程控制的理解。如正常和異常終止進程函數(shù)的范例6-
4所示。例6-4
my_
exit_abort.c/****my_exit_abort.c***/在VIM編輯器中具體闡述代碼在eclipse集成開發(fā)環(huán)境IDE中編譯、調(diào)試、運行代碼6.2.4
system函數(shù)9:4028/267
在Linux系統(tǒng)編程中,可以使用system函數(shù)執(zhí)行fork、exec和wait等各種系統(tǒng)命令,完成進程相關(guān)的操作。
system函數(shù)是和Linux操作系統(tǒng)緊密相關(guān)的函數(shù),用戶根據(jù)自身需要,在程序中方便的使用此函數(shù)實現(xiàn)進程操作相關(guān)的功能。1
system函數(shù)9:4029/267
執(zhí)行系統(tǒng)的命令行完成進程操作的系統(tǒng)函數(shù)是system函數(shù)。系統(tǒng)通過調(diào)用它在程序中完成進程操作的相關(guān)工作。在Linux系統(tǒng)終端中使用幫助命令“man
system”,得到函數(shù)的信息如下:#include
<stdlib.h>int
system(const
char
*command);1
system函數(shù)9:4030/267
system:該函數(shù)的返回類型為整型,用于執(zhí)行系統(tǒng)的命令。command參數(shù)是一個字符串指針,指向表示命令行的字符串。command參數(shù)值可以為NULL,可用于測試
system函數(shù)是否有效,若返回值為非空指針,表示其有效;若返回值為0,表示其無效。command參數(shù)值也可
以為fork、exec和waitpid等相關(guān)的命令行,在執(zhí)行system函數(shù)的過程中,其返回值是復(fù)雜多變的,調(diào)用fork、exec和waitpid任意一個命令行失敗將會導(dǎo)致system函數(shù)
的執(zhí)行失敗。若調(diào)用exec失敗,表示無法執(zhí)行所設(shè)命令,將返回shell操作的返回值;若調(diào)用waitpid失敗,表示等待失敗,將返回-1;若調(diào)用fork失敗,表示創(chuàng)建進程失敗,將返回-1。2綜合示例9:4031/267
在本節(jié)最后,通過利用system函數(shù)進行系統(tǒng)調(diào)用,來演示如何使用system函數(shù)執(zhí)行命令行參數(shù),加強對進程控制的理解。system函數(shù)如范例6-5所示。例6-5
my_
system.c/****my_system.c***/在VIM編輯器中具體闡述代碼在eclipse集成開發(fā)環(huán)境IDE中編譯、調(diào)試、運行代碼6.2.5進程同步9:4032/267
Linux系統(tǒng)是多任務(wù)的操作系統(tǒng),用戶可以同時運行多個進程執(zhí)行多個任務(wù),形成并發(fā)程序和并發(fā)進程,而且多個進程間通常不是相互獨立的,有時它們需要保持多個進程間的相互配合進行同步工作。因此,對多任務(wù)多進程的系統(tǒng)而言,如何協(xié)調(diào)不同進程間的同步運行,處理好它們之間的關(guān)系是十分重要的環(huán)節(jié)。6.2.5進程同步9:4033/267
進程同步的實例很多,例如,多個進程需要訪問同一個設(shè)備或調(diào)用同一個程序。多個進程訪問同一程序示例:
網(wǎng)絡(luò)上不同終端和不同的售票窗口,會調(diào)用同一段售票
程序代碼出售同一車次的火車票,如果不同的終端和售
票窗口同時調(diào)用同一段售票程序代碼出售火車票,那么
它們所讀取的余票信息是一樣的,就會賣出相同的車票,進而產(chǎn)生沖突問題,這就需要對不同的終端和售票窗口
調(diào)用的同一段售票程序代碼,進行加鎖,實現(xiàn)同一時間
內(nèi)只有一個進程終端調(diào)用,也就是說需要實現(xiàn)進程間的
同步。多個進程訪問同一設(shè)備的示例:當(dāng)有多個進程同
時對同一設(shè)備打印機進行打印操作時,會造成打印的數(shù)
據(jù)混亂,這也需要協(xié)調(diào)不同進程對打印機設(shè)備的訪問的
同步。6.2.5進程同步9:4034/267
實現(xiàn)進程間同步的方法包括文件鎖定、信號量、管道、消息、套接字和共享內(nèi)存等。其中管道、消息、套接字和共享內(nèi)存不僅用于進程間的通信,也可用于進程間的同步;文件鎖和信號量是用于進程間的同步的。這部分內(nèi)容將在第八章中詳細(xì)介紹,在此簡單介紹進程間的同步關(guān)系。
實現(xiàn)進程間同步也會存在很多問題包括死鎖,訪問設(shè)備沖突等,這部分內(nèi)容將在第八章中詳細(xì)介紹,在此只是簡單介紹進程間的同步關(guān)系。6.4本章小結(jié)9:4035/267
進程的相關(guān)操作是Linux系統(tǒng)編程的重要環(huán)節(jié)。熟悉進程控制的API的調(diào)用,對于Linux平臺下的操作系統(tǒng)編程將大有幫助。本章介紹了進程操作的理論知識,然后結(jié)合具體的案例,詳細(xì)闡述了進程的創(chuàng)建、等待、終止、同步、system函數(shù)的操作,加深了理論和實踐的結(jié)合度,達到了學(xué)以致用的目的。6.5本章習(xí)題9:4036/2676.5本章習(xí)題9:4037/2676.5本章習(xí)題9:4038/267內(nèi)容提要第七章線程控制7.1線程控制7.1.1線程的創(chuàng)建7.1.2線程的終止7.1.3線程的同步7.1.4私有數(shù)據(jù)7.3本章小結(jié)9:4039/267第七章線程控制9:4040/267
本章首先介紹Linux下線程控制的相關(guān)內(nèi)容;然后介紹
Linux平臺下線程的操作,包括線程的創(chuàng)建、終止、同步、私有數(shù)據(jù)的操作;最后結(jié)合具體示例,闡述線程的相關(guān)
操作的具體應(yīng)用。本節(jié)學(xué)習(xí)目標(biāo):√線程的創(chuàng)建√線程的終止√線程的同步√私有數(shù)據(jù)7.1線程控制9:4041/267
本節(jié)介紹線程的相關(guān)知識。在Linux操作系統(tǒng)中,進程和線程是緊密相關(guān)的,又相互有區(qū)別的。在操作系統(tǒng)中,
進程是資源分配的最小單位,而線程是任務(wù)獨立運行的
最小單位。Linux操作系統(tǒng)是支持多任務(wù)多進程的,同時在同一進程內(nèi)也支持多線程的,這是為什么呢?這是因
為多線程較多進程而言,不僅節(jié)約資源,而且節(jié)約時間,這對操作系統(tǒng)的設(shè)計和運行非常重要和關(guān)鍵,具體表現(xiàn)
在如下幾個方面。7.1線程控制9:4042/267
首先,創(chuàng)建新線程花費較少的時間,而且占用的系統(tǒng)資源也要少的多。在Linux系統(tǒng)中,每個進程都有各自獨立的地址空間,而在同一進程內(nèi)的多個線程是共享該進程的地址空間的,所以創(chuàng)建一個新進程要耗費較多時間為其分配系統(tǒng)資源,供其正常運轉(zhuǎn),而線程較少。
其次,線程間切換的速度要遠快于進程間的切換速度。具體原因是在系統(tǒng)調(diào)度過程中,線程共享地址空間而進程地址空間相互獨立。7.1線程控制9:4043/267
第三,線程間的通信省時且方便。進程間的地址空間是相互獨立的,彼此通信必須經(jīng)過操作系統(tǒng)進行專門的通
信方式進行通信;而進程內(nèi)的多個線程間地址空間共享,彼此通信不必經(jīng)過操作系統(tǒng),線程間的數(shù)據(jù)相互可以看
到。
再次,線程提高程序的響應(yīng)速度。在多任務(wù)的Linux操作系統(tǒng)中,有很多非常耗時的操作,比如從網(wǎng)絡(luò)下載很大
的圖片,它會導(dǎo)致用戶一直處于等待狀態(tài)而不能進行其
他操作,多線程環(huán)境下可以將這個耗時的操作交給一個
單獨的線程來完成,讓用戶不用等待可以進行其他工作,提高程序的響應(yīng)速度。7.1線程控制9:4044/267
最后,多線程提高CPU的處理效率,發(fā)揮硬件的全部潛力?,F(xiàn)代計算機都采用多核技術(shù),如果采用多個線程在不同的處理器上同時運行,可以較大提高程序的運行效率和速度。
鑒于線程有這么多的優(yōu)點,所以下面將從線程的創(chuàng)建、終止、同步和私有數(shù)據(jù)四個方面給出線程的具體介紹。7.1.1線程創(chuàng)建9:4045/267
在Linux系統(tǒng)編程中,可以使用pthread_create函數(shù)完成線程創(chuàng)建的相關(guān)工作。pthread_create函數(shù)是和Linux操作系統(tǒng)緊密相關(guān)的函數(shù),用戶根據(jù)自身需要,在程序中方便的使用此函數(shù)實現(xiàn)線程操作相關(guān)的功能。前面所介紹的示例都是按照固定順序執(zhí)行的單線程程序,若是在主線程中創(chuàng)建新的線程,就會同時運行兩個程序,提高程序執(zhí)行的效率。1線程創(chuàng)建函數(shù)9:4046/267
執(zhí)行線程創(chuàng)建函數(shù)是pthread_create函數(shù)。系統(tǒng)通過調(diào)用它在程序中完成線程創(chuàng)建的相關(guān)工作。在Linux系統(tǒng)終端中使用幫助命令“man
pthread_create”,得到函數(shù)的
信息如下:#include
<pthread.h>
int
pthread_create(pthread_t
*thread,
constpthread_attr_t
*attr,void
*(*start_routine)
(void
*),
void
*arg);1線程創(chuàng)建函數(shù)9:4047/267
該函數(shù)的返回類型為整型,用于執(zhí)行線程的創(chuàng)建。thread參數(shù)是一個指針,指向成功創(chuàng)建線程后所返回的線程ID號。attr參數(shù)是一個指向pthread_attr_t的結(jié)構(gòu)體指針,使用該結(jié)構(gòu)體指定所創(chuàng)建線程的各種屬性,若attr參數(shù)值為NULL,表示使用默認(rèn)屬性。start_routine參數(shù)是一個函數(shù)指針,用于指向線程創(chuàng)建成功后所要調(diào)用并執(zhí)行的函數(shù),此函數(shù)也稱為線程函數(shù)。arg參數(shù)是一個指針,指向線程函數(shù)的參數(shù)。
若線程創(chuàng)建成功,則pthread_create函數(shù)返回0;否則創(chuàng)建失敗返回非0。成功創(chuàng)建線程后,新線程開始運行線程函數(shù),原調(diào)用線程繼續(xù)運行。2線程創(chuàng)建相關(guān)函數(shù)9:4048/267
在線程創(chuàng)建成功后,還要調(diào)用線程創(chuàng)建相關(guān)的一些函數(shù),比如獲取本線程ID的函數(shù)、判斷兩個線程ID是否指向同
一個線程的函數(shù)、用來保證線程函數(shù)在進程中僅執(zhí)行一
次的函數(shù)等,這些函數(shù)可以輔助新創(chuàng)建的線程做一些有
益的功能,下面給出它們的函數(shù)聲明。2線程創(chuàng)建相關(guān)函數(shù)9:4049/267
在Linux系統(tǒng)終端中使用幫助命令“man
pthread_once”、
“man
pthread_self”和“man
pthread_equal”,得到
函數(shù)的信息如下:#include
<pthread.h>
int
pthread_once(pthread_once_t
*once_control,void(*init_routine)(void));pthread_once_t
once_control
=
PTHREAD_ONCE_INIT;#include
<pthread.h>pthread_t
pthread_self(void);#include
<pthread.h>int
pthread_equal(pthread_t
t1,
pthread_t
t2);2線程創(chuàng)建相關(guān)函數(shù)9:4050/267
pthread_once:該函數(shù)的返回類型為整型,用來保證線程函數(shù)在進程中僅執(zhí)行一次。once_control參數(shù)是一個指針,指向pthread_once_t結(jié)構(gòu)體。init_routine參數(shù)是一個函數(shù)指針,用來指向一次執(zhí)行的函數(shù)。若函數(shù)執(zhí)行成功,則返回0;否則返回非0。
pthread_self:該函數(shù)的返回類型為整型,用來獲取本線程ID號。若函數(shù)執(zhí)行成功,則返回本線程ID號;否則返
回0。
pthread_equal:該函數(shù)的返回類型為整型,用來判斷兩個線程ID是否指向同一個線程。t1是線程1的ID號,t2是線程2的ID號。若函數(shù)執(zhí)行成功,則返回非0;否則返回
0。3綜合示例9:4051/267
在本節(jié)最后,通過利用線程創(chuàng)建函數(shù)進行系統(tǒng)調(diào)用,來演示如何創(chuàng)建線程,加強對線程控制的理解。pthread_create函數(shù)如范例7-1所示。例7-1
my_
createthread.c/****my_createthread.c***/在VIM編輯器中具體闡述代碼在eclipse集成開發(fā)環(huán)境IDE中編譯、調(diào)試、運行代碼7.1.2線程終止9:4052/267
在Linux系統(tǒng)編程中,線程的終止方式有兩種:一種是使用return語句從線程函數(shù)中返回;另一種是調(diào)用
phtread_exit函數(shù)退出線程。用戶根據(jù)自身需要,在程序中方便的使用這兩種方式結(jié)束線程。
線程終止時,一般是從主線程中退出,從而結(jié)束整個進程。若是在主線程中,調(diào)用了exit函數(shù)或通過return語句返回,則整個進程中所有的線程終止,進程終止;若是
在主線程中調(diào)用了pthread_exit函數(shù),則進程不會結(jié)束,只是主線程結(jié)束,進程內(nèi)的其它線程仍可以正常運行;
若是從子線程中調(diào)用了exit函數(shù)或通過return語句返回,則子線程消亡,主線程和進程內(nèi)的其它線程不受影響。7.1.2線程終止9:4053/267
線程終止的核心問題是釋放資源的問題。如果一個線程終止后沒有及時釋放所持有的資源,則此資源會被認(rèn)為被其一直獨占,造成永遠無法釋放,會導(dǎo)致其它線程或進程無法獲得該資源,而一直處于無限的等待狀態(tài),這就是所謂的死鎖。所以線程終止時,要及時釋放所占有的各種資源,使其它進程獲得資源及時運行。
線程終止的另一個關(guān)鍵問題是線程間的同步問題。在
Linux系統(tǒng)中,運行在進程中的各個線程是相互獨立的,某個線程的終止不會影響到別的線程,并且終止的線程
也不會及時的把占用的資源歸還給系統(tǒng),而是仍歸其所
在的進程擁有。線程之間可以使用pthread_join函數(shù)調(diào)用來通知或等待其它線程的結(jié)束。1線程終止函數(shù)9:4054/267
執(zhí)行線程終止函數(shù)是pthread_exit函數(shù)。系統(tǒng)通過調(diào)用它在程序中完成線程終止的相關(guān)工作。在Linux系統(tǒng)終端中使用幫助命令“man
pthread_exit”,得到函數(shù)的信息如下:#include
<pthread.h>void
pthread_exit(void
*retval);
該函數(shù)的返回類型為空,用于完成線程的終止。retval參數(shù)是一個指針,指向本線程所設(shè)置的變量值,并返回給
調(diào)用線程。2等待線程結(jié)束函數(shù)9:4055/267
等待線程結(jié)束的函數(shù)是pthread_
join函數(shù)。系統(tǒng)通過調(diào)用它在程序中完成等待線程結(jié)束的相關(guān)工作。在Linux系統(tǒng)終端中使用幫助命令“man
pthread_join”,得到函數(shù)的信息如下:#include
<pthread.h>int
pthread_join(pthread_t
thread,
void
**retval);2等待線程結(jié)束函數(shù)9:4056/267
該函數(shù)的返回類型為空,用于等待一個線程的結(jié)束。
thread參數(shù)是整型參數(shù),表示等待線程的ID號。retval參數(shù)是個二級指針型參數(shù),用于指向等待線程所返回變量的指針。該函數(shù)的調(diào)用者將被掛起并等待thread線程終止,并且等待線程只允許一個調(diào)用線程使用pthread_join函數(shù)
等待它的結(jié)束;若是被多個調(diào)用線程等待,除了第一個收到信號的線程返回成功外,其它調(diào)用線程均返回錯誤。3綜合示例9:4057/267
在本節(jié)最后,通過利用線程終止函數(shù)進行系統(tǒng)調(diào)用,來演示如何終止線程,加強對線程控制的理解。pthread_exit函數(shù)如范例7-2所示。例7-2
my_
threadexit_join.c/****my_threadexit_join.c***/在VIM編輯器中具體闡述代碼在eclipse集成開發(fā)環(huán)境IDE中編譯、調(diào)試、運行代碼7.1.3線程同步9:4058/267
在Linux系統(tǒng)編程中,多線程最核心的問題是資源共享中的同步問題。如果一個線程終止后沒有及時釋放所持有的資源,則此資源會被認(rèn)為被其一直獨占,造成永遠無法釋放,會導(dǎo)致其它線程永遠無法獲得該資源,而一直處于無限的等待狀態(tài),這就是所謂的死鎖。所以如何解決線程間的同步問題,是實現(xiàn)多線程編程的關(guān)鍵問題。7.1.3線程同步9:4059/267
多線程編程的另一個關(guān)鍵問題是線程間的同步問題。在
Linux系統(tǒng)中,運行在進程中的各個線程是相互獨立的,某個線程的終止不會影響到別的線程,并且終止的線程也不會及時的把占用的臨界資源歸還給系統(tǒng),而是仍歸其所在的進程擁有,導(dǎo)致進程內(nèi)的其它線程沒有及時收到通知消息,不能使用臨界資源,不能實現(xiàn)彼此線程間的同步協(xié)調(diào)運行。
鑒于上述問題,Linux系統(tǒng)提供了多種方式處理線程間同步問題,目前最常用的同步技術(shù)包括互斥鎖、條件變量。下面給出具體介紹。1互斥鎖9:4060/267
互斥鎖要求同一時刻只有一個線程訪問同一個設(shè)備或同一段代碼,通過訪問前加鎖和訪問后解鎖的機制來實現(xiàn)多線程間的同步問題。
支持線程同步的互斥鎖的函數(shù)有多個,包括初始化、加鎖、解鎖、注銷等互斥鎖函數(shù)。系統(tǒng)通過調(diào)用它們在程序中完成線程同步的相關(guān)工作。在Linux系統(tǒng)終端中使用幫助命令,得到互斥鎖的函數(shù)的信息如下:1互斥鎖9:4061/267#include
<pthread
.h>
int
pthread_mutex_init(pthread_mutex_t
*mutex,
constpthread_mutexattr_t
*mutexattr);int
pthread_mutex_lock(pthread_mutex_t
*mutex);int
pthread_mutex_trylock(pthread_mutex_t
*mutex);int
pthread_mutex_unlock(pthread_mutex_t
*mutex);int
pthread_mutex_destroy(pthread_mutex_t
*mutex);1互斥鎖9:4062/267
pthread_mutex_init:該函數(shù)的返回類型為整型,用于初始化一個互斥鎖。mutex參數(shù)是一個指針,指向生成的互斥鎖。mutexattr參數(shù)是一個指針,互斥鎖的屬性,若它為NULL則表示采用系統(tǒng)默認(rèn)的屬性;若為普通鎖,則表
示當(dāng)線程加鎖后,其余申請加鎖的線程形成等待隊列,
解鎖后按照優(yōu)先級獲得鎖;若為適應(yīng)鎖,則表示解鎖后
重新競爭;若為檢錯鎖,則表示當(dāng)相同線程請求同一個
鎖時,返回EDEADLK,否則執(zhí)行的動作與普通鎖一樣;若為嵌套鎖,則表示允許同一個線程對同一個鎖多次加鎖,通過多次unlock解鎖,若不是同線程請求則在解鎖后重新競爭。1互斥鎖9:4063/267
pthread_mutex_lock:該函數(shù)的返回類型為整型,用于對一個線程加鎖,若不成功則阻塞等待。mutex參數(shù)含義同pthread_mutex_init函數(shù)中的相同。
pthread_mutex_trylock:該函數(shù)的返回類型為整型,用于對一個線程測試加鎖,若不成功則立即返回。mutex參數(shù)含義同pthread_mutex_init函數(shù)中的相同。1互斥鎖9:4064/267
pthread_mutex_unlock:該函數(shù)的返回類型為整型,用于對一個線程解鎖。mutex參數(shù)含義同
pthread_mutex_init函數(shù)中的相同。
pthread_mutex_destroy:該函數(shù)的返回類型為整型,用于注銷一個互斥鎖。mutex參數(shù)含義同
pthread_mutex_init函數(shù)中的相同。上述五個函數(shù)調(diào)用成功返回0,否則調(diào)用失敗返回錯誤碼。1互斥鎖9:4065/267
綜上所述,在Linux系統(tǒng)編程中,使用互斥鎖實現(xiàn)多線程的同步基本上需要四步來完成。首先,使用前必須對互
斥鎖進行初始化操作。初始化有靜態(tài)初始化和函數(shù)初始
化兩種方式,靜態(tài)初始化就是對互斥鎖直接賦值;函數(shù)
初始化就是通過調(diào)用pthread_mutex_init函數(shù)初始化互斥鎖。其次,調(diào)用pthread_mutex_lock或pthread_mutex_trylock函數(shù)對互斥鎖進行加鎖。然后,調(diào)用pthread_mutex_unlock函數(shù)對互斥鎖進行解鎖,解
鎖要求互斥鎖必須處于加鎖狀態(tài)和調(diào)用線程必須是加鎖
線程。最后,互斥鎖使用完后,調(diào)用
pthread_mutex_destroy函數(shù)對互斥鎖進行清除工作。2條件變量9:4066/267
條件變量是在互斥鎖的基礎(chǔ)上,通過使用線程間共享的全局變量,使用判斷語句判斷條件成立則執(zhí)行某地代碼,否則等待條件成立,來實現(xiàn)線程間的同步問題。
支持線程同步的條件變量函數(shù)有多個,包括初始化、等待、解除、清除等互斥鎖函數(shù)。系統(tǒng)通過調(diào)用它們在程序中完成線程同步的相關(guān)工作。在Linux系統(tǒng)終端中使用幫助命令,得到互斥鎖的函數(shù)的信息如下:2條件變量9:4067/267?#include
<pthread.h>
pthread_cond_t
cond
=PTHREAD_COND_INITIALIZER;
int
pthread_cond_init(pthread_cond_t
*restrict
cond,const
pthread_condattr_t
*restrict
attr);
int
pthread_cond_wait(pthread_cond_t
*restrictcond,pthread_mutex_t
*restrict
mutex);
int
pthread_cond_timedwait(pthread_cond_t
*restrictcond,pthread_mutex_t
*restrict
mutex,const
struct
timespec
*restrict
abstime);2條件變量9:4068/267int
pthread_cond_signal(pthread_cond_t
*cond);int
pthread_cond_broadcast(pthread_cond_t
*cond);int
pthread_cond_destroy(pthread_cond_t
*cond);2條件變量9:4069/267
pthread_cond_init:該函數(shù)的返回類型為整型,用于初始化條件變量。cond參數(shù)是一個指針,指向條件變量。
attr參數(shù)是一個指針,表示條件變量的屬性。
pthread_cond_wait:該函數(shù)的返回類型為整型,表示基
于條件變量阻塞并無條件等待。cond參數(shù)含義同
pthread_cond_init函數(shù)中的相同。mutex參數(shù)是一個指針,指向互斥鎖。
pthread_cond_timedwait:該函數(shù)的返回類型為整型,功能同pthread_cond_wait函數(shù)一樣,用于對條件變量的限時等待,超時后將無條件返回。cond參數(shù)和mutex參數(shù)
含義同pthread_cond_wait函數(shù)中的相同。abstime參數(shù)
表示等待的時間。2條件變量9:4070/267
pthread_cond_signal:該函數(shù)的返回類型為整型,用于解除特定線程的阻塞或從等待隊列中激活第一個入隊的線程。cond參數(shù)含義同pthread_cond_init函數(shù)中的相同。
pthread_cond_broadcast:該函數(shù)的返回類型為整型,用于解除所有線程的阻塞。cond參數(shù)含義同
pthread_cond_init函數(shù)中的相同。
pthread_cond_destroy:該函數(shù)的返回類型為整型,用于清除條件變量。cond參數(shù)含義同pthread_cond_init函數(shù)中的相同。上述六個函數(shù)調(diào)用成功返回0,否則調(diào)用失敗返回錯誤碼。2條件變量9:4071/267
綜上所述,在Linux系統(tǒng)編程中,使用條件變量實現(xiàn)多線程的同步基本上需要四步來完成。首先,使用前必須對
條件變量進行初始化操作。初始化有靜態(tài)初始化和函數(shù)
初始化兩種方式,靜態(tài)初始化就是對條件變量直接賦值;函數(shù)初始化就是通過調(diào)用pthread_cond_init函數(shù)初始化條件變量。其次,調(diào)用pthread_cond_wait或pthread_cond_timedwait函數(shù)對條件變量進行等待。然后,調(diào)用pthread_cond_signal或pthread_cond_broadcast函
數(shù)解除特定或所有線程的阻塞。最后,條件變量使用完后,調(diào)用pthread_cond_destroy函數(shù)對條件變量進行清除工作,只有在沒有等待線程等待該條件變量的時候,才可以清除它。3綜合示例9:4072/267
在本節(jié)最后,通過利用線程同步函數(shù)進行系統(tǒng)調(diào)用,來演示如何進行線程的同步,加強對線程控制的理解。pthread_mutex_cond函數(shù)如范例7-3所示。例7-3
my_pthread_mutex_cond.c/****my_pthread_mutex_cond.c***/在VIM編輯器中具體闡述代碼在eclipse集成開發(fā)環(huán)境IDE中編譯、調(diào)試、運行代碼7.1.4私有數(shù)據(jù)9:4073/267
在Linux系統(tǒng)多線程的編程中,同一進程內(nèi)的各個線程可以共享進程的數(shù)據(jù)空間,包括全局變量,但是線程也需要保存自己的全局變量,而且又要求這種全局變量只供本線程所私有。例如標(biāo)準(zhǔn)的出錯代碼變量ERRNO,系統(tǒng)要求它是個全局變量,每個函數(shù)出錯后,都可以訪問到它,并且返回本線程所要求的出錯代碼值。這種為線程所私有的全局變量就是線程的私有數(shù)據(jù)(Thread-specific
Data簡稱TSD),它可以被本線程內(nèi)的各個函數(shù)訪問,但是其它線程函數(shù)無法訪問它的值。1線程私有數(shù)據(jù)函數(shù)9:4074/267
線程私有數(shù)據(jù)采樣了一鍵多值技術(shù)。進程內(nèi)的各個線程都可以通過公共的鍵名來訪問它的值,但是各個線程所訪問的值是不一樣的。
支持線程私有數(shù)據(jù)的函數(shù)有多個,包括創(chuàng)建、設(shè)置、讀取、刪除等函數(shù)。系統(tǒng)通過調(diào)用它們在程序中完成線程私有數(shù)據(jù)相關(guān)工作。在Linux系統(tǒng)終端中使用幫助命令,得到線程私有數(shù)據(jù)的函數(shù)信息如下:1線程私有數(shù)據(jù)函數(shù)9:4075/267#include
<pthread.h>
int
pthread_key_create(pthread_key_t
*key,
void(*destructor)(void*));int
pthread_setspecific(pthread_key_t
key,
const
void*value);void
*pthread_getspecific(pthread_key_t
key);int
pthread_key_delete(pthread_key_t
key);1線程私有數(shù)據(jù)函數(shù)9:4076/267
pthread_key_create:該函數(shù)的返回類型為整型,用于創(chuàng)建一個鍵。key參數(shù)是一個指針,指向生成的鍵值。
destructor參數(shù)是一個函數(shù)指針,指向線程退出時所要執(zhí)行的以key關(guān)聯(lián)的數(shù)據(jù)為參數(shù)的釋放資源的函數(shù)。key值創(chuàng)建成功后,進程內(nèi)的所有線程都可以訪問它,并且各
個線程可以往key中注入自己的值,實現(xiàn)一鍵多值的線程私有數(shù)據(jù)功能。函數(shù)調(diào)用成功返回0,否則調(diào)用失敗返回錯誤碼。1線程私有數(shù)據(jù)函數(shù)9:4077/267
pthread_setspecific:該函數(shù)的返回類型為整型,用于為一個鍵設(shè)置新線程的私有數(shù)據(jù)。key參數(shù)是一個類型為
pthread_key_t的參數(shù),表示具體的鍵名。value參數(shù)是一個指針,指向所設(shè)置鍵的具體值。函數(shù)調(diào)用成功返回0,否則調(diào)用失敗返回錯誤碼。
pthread_getspecific:該函數(shù)的返回類型為指針,用于從一個鍵中讀取本線程的私有數(shù)據(jù)。key參數(shù)含義同
pthread_setspecific函數(shù)中的相同。函數(shù)調(diào)用成功返回與
key關(guān)聯(lián)的值,否則調(diào)用失敗返回NULL。1線程私有數(shù)據(jù)函數(shù)9:4078/267
pthread_key_delete:該函數(shù)的返回類型為整型,用于刪除指定的鍵。key參數(shù)含義同pthread_setspecific函數(shù)中的相同。鍵刪除成功后,其所占用的內(nèi)存也被釋放。函
數(shù)調(diào)用成功返回0,否則調(diào)用失敗返回錯誤碼。
綜上所述,在Linux系統(tǒng)編程中,使用線程私有數(shù)據(jù)進行多線程編程基本上需要四步來完成。首先,使用前必須
通過調(diào)用pthread_key_create函數(shù)創(chuàng)建一個鍵。其次,調(diào)用pthread_setspecific函數(shù)為一個鍵設(shè)置新線程的私有數(shù)據(jù)。然后,調(diào)用pthread_getspecific函數(shù)從一個鍵中讀取本線程的私有數(shù)據(jù)。最后,私有數(shù)據(jù)使用完后,調(diào)用
pthread_key_delete函數(shù)刪除指定的鍵。2綜合示例9:4079/267
在本節(jié)最后,通過利用線程私有數(shù)據(jù)函數(shù)進行系統(tǒng)調(diào)用,來演示如何創(chuàng)建和使用線程的私有數(shù)據(jù),加強對線程控制的理解。pthread_key_value函如范例
7-4所示。例7-4
my_
pthread_key_value.c/****my_pthread_key_value.c***/在VIM編輯器中具體闡述代碼在eclipse集成開發(fā)環(huán)境IDE中編譯、調(diào)試、運行代碼7.3本章小結(jié)9:4080/267
線程的相關(guān)操作是Linux編程的重要環(huán)節(jié)。熟悉線程控制的API的調(diào)用,對于
Linux平臺下的操作系統(tǒng)編程將大有幫助。本章介紹了線程操作的理論知識,然后結(jié)合具體的項目案例,詳細(xì)闡述了線程的創(chuàng)建、終止、同步、私有數(shù)據(jù)的操作,在具體的項目案例中的具體應(yīng)用,加深了理論和實踐的結(jié)合度,達到了學(xué)以致用的目的。7.4本章習(xí)題9:4081/2677.4本章習(xí)題9:4082/2677.4本章習(xí)題9:4083/267內(nèi)容提要9:4084/267第八章進程間通信8.1概述8.2共享內(nèi)存8.3信號量8.4管道通信8.4.1管道的創(chuàng)建和關(guān)閉8.4.2管道的讀寫操作8.5命名管道8.5.1命名管道的創(chuàng)建內(nèi)容提要9:4085/2678.5.2命名管道的使用8.6消息隊列8.6.1消息隊列的創(chuàng)建與打開8.6.2向消息隊列中發(fā)送消息8.6.3從消息隊列中接收消息8.6.4消息隊列的控制8.6.5綜合示例8.8本章小結(jié)8.9本章習(xí)題第八章進程間通信9:4086/267
本章首先介紹Linux下進程間通信的相關(guān)內(nèi)容;然后介紹
Linux平臺下進程間通信相互通信的方法,包括共享內(nèi)存、信號量、管道通信、命名管道、消息隊列;最后結(jié)合具
體的項目案例,闡述進程間通信的相關(guān)操作的具體應(yīng)用。本節(jié)學(xué)習(xí)目標(biāo):√共享內(nèi)存√信號量√管道通信√命名管道√消息隊列8.1進程間通信概述
Linux系統(tǒng)是多任務(wù)多進程的操作系統(tǒng),對于大型的應(yīng)用系統(tǒng)而言,通常需要多個任務(wù)多個進程相互協(xié)作共同完成,而進程的地址空間又是各自獨立的,所以需要進程間進行通信。進程間的通信(Internet
ProcessConnection簡稱IPC)是指多個進程間相互協(xié)調(diào),進行信息交換,相互交流的方法。Linux下進程間進行相互通信的方法包括共享內(nèi)存、信號量、管道、命名管道、消息隊列等。下面對Linux下的進程間的通信方法做個簡單介紹。
共享內(nèi)存:共享內(nèi)存是指由一個進程創(chuàng)建并且能夠被其它進程訪問的內(nèi)存段。共享內(nèi)存是進程間通信方式最快的IPC方式,經(jīng)常與信號量等通信機制配合使用,通信速度最快、運行效率最高。9:40in87/2678.1進程間通信概述9:4088/267
信號量:信號量在形式上是一個計數(shù)器,主要用來協(xié)調(diào)進程間或同一個進程內(nèi)不同線程間同時訪問共享資源的問題。所以,信號量也稱為一種信號鎖,保證同一時刻只有一個進程或線程訪問共享資源,其余進程或線程無法訪問該共享資源;信號量也是一種同步機制,同一時刻可以有多個進程訪問共享資源。
管道:管道在形式上是一種文件,主要用在具有親緣關(guān)系的進程間的通信。管道是一種半雙工的通信方式,它的顯著特點是管道有讀入端和寫入端,數(shù)據(jù)只能單向流動。和共享內(nèi)存相比,管道通信相對慢些,但是它用起來方便很多,系統(tǒng)開銷也小。8.1進程間通信概述9:4089/267
命名管道:命名管道是管道中的一種,具有管道的所有功能和特點。命名管道是一個設(shè)備文件,不僅可用在具有親緣關(guān)系的進程間的通信,而且也可用在不具有親緣關(guān)系的進程間。命名管道要求提供一個路徑名與它關(guān)聯(lián)的文件,只要可以訪問這個路徑文件的進程,都可以進程間的相互通信。
消息隊列:消息隊列是存放在操作系統(tǒng)內(nèi)核中的消息鏈表,每個消息隊列由消息隊列標(biāo)識符標(biāo)示。消息隊列存放在內(nèi)核中,所以只有重啟操作系統(tǒng)或主動刪除一個消息隊列,消息隊列才會消除。消息隊列具有傳遞信息量大、可以承載各種格式的字節(jié)流和可以動態(tài)設(shè)置緩沖區(qū)大小的優(yōu)點。8.2共享內(nèi)存9:4090/267
在Linux系統(tǒng)中,共享內(nèi)存是由一個進程創(chuàng)建并且能夠被其它進程訪問的內(nèi)存段。每個進程所創(chuàng)建的共享內(nèi)存在操作系統(tǒng)內(nèi)核中維護著一個與之相應(yīng)的數(shù)據(jù)結(jié)構(gòu)
shmid_ds,它的具體定義如下所示:8.2共享內(nèi)存9:4091/2678.2共享內(nèi)存9:4092/267???????
這個結(jié)構(gòu)詳細(xì)描述了共享內(nèi)存的各種屬性,它們的具體含義如下所示:shm_perm:表示共享內(nèi)存的用戶ID、組ID等信息;shm_segsz:以字節(jié)為單位表示共享內(nèi)存的大?。籹hm_lkcnt:表示共享內(nèi)存段鎖定的時間大??;shm_cpid:表示創(chuàng)建共享內(nèi)存的進程ID;shm_lpid:表示最后一次操作共享內(nèi)存的進程ID;shm_nattch:表示當(dāng)前使用共享內(nèi)存的進程數(shù);shm_atime:表示最后一次附加共享內(nèi)存的時間;8.2共享內(nèi)存9:4093/267shm_dtime:表示最后一次分離共享內(nèi)存的時間;shm_ctime:表示最后一次修改共享內(nèi)存的時間;下面給出基于上述共享內(nèi)存數(shù)據(jù)結(jié)構(gòu)的函數(shù)調(diào)用。1共享內(nèi)存的創(chuàng)建9:4094/267
創(chuàng)建共享內(nèi)存的函數(shù)是shmget。系統(tǒng)通過調(diào)用它在程序中完成共享內(nèi)存的創(chuàng)建工作。在Linux系統(tǒng)終端中使用幫助命令“man
shmget”,得到共享內(nèi)存的創(chuàng)建函數(shù)信息如下:#include
<sys/ipc.h>#include
<sys/shm.h>int
shmget(key_t
key,
size_t
size,
int
shmflg);1共享內(nèi)存的創(chuàng)建9:4095/267
shmget:該函數(shù)的返回類型為整型,用于創(chuàng)建進程的共享內(nèi)存。key參數(shù)表示由ftok生成的共享內(nèi)存鍵。size參數(shù)表示共享內(nèi)存的大小,若是新創(chuàng)建一個共享內(nèi)存則size須大于0;若是訪問已經(jīng)存在的共享內(nèi)存則size為0。
shmflg參數(shù)表示共享內(nèi)存的操作標(biāo)志位,用于設(shè)置共享內(nèi)存的訪問權(quán)限,若shmflg參數(shù)取值為IPC_CREATE,則表示系統(tǒng)將參數(shù)key與其它的共享內(nèi)存key進行比較,如果相同則返回已經(jīng)存在的共享內(nèi)存區(qū)的標(biāo)識符,如果不同則新建一個共享內(nèi)存區(qū)并返回其標(biāo)識符;若shmflg參數(shù)取值為IPC_EXCL,則表示無意義;若shmflg參數(shù)取值為IPC_CREATE
|
IPC_EXCL,表示如果發(fā)現(xiàn)信號集已經(jīng)存在,則返回-1。1共享內(nèi)存的創(chuàng)建9:4096/267
函數(shù)shmget調(diào)用成功返回共享內(nèi)存的引用標(biāo)示符,同時該共享內(nèi)存的shmid_ds結(jié)構(gòu)被初始化;否則調(diào)用失敗返回-1。2共享內(nèi)存的附加9:4097/267
共享內(nèi)存的附加函數(shù)是shmat。系統(tǒng)通過調(diào)用它在程序中完成共享內(nèi)存的附加工作。在Linux系統(tǒng)終端中使用幫助命令“man
shmat”,得到共享內(nèi)存的附加函數(shù)信息如
下:#include
<sys/types.h>#include
<sys/shm.h>void
*shmat(int
shmid,
const
void
*shmaddr,
int
shmflg);2共享內(nèi)存的附加9:4098/267
shmat:該函數(shù)的返回類型為指針,指向共享內(nèi)存的地址,用于附加進程的共享內(nèi)存。shmid參數(shù)表示附加的共享內(nèi)
存的引用標(biāo)示符。shmflg參數(shù)表示共享內(nèi)存的讀寫操作方式。shmaddr參數(shù)表示共享內(nèi)存的附加地址空間,若
shmaddr參數(shù)取值為空,則表示由內(nèi)核選擇一個空閑的內(nèi)存區(qū);若shmaddr參數(shù)取值為非空,并且shmflg參數(shù)指定為SHM_RND值則附加地址為共享內(nèi)存的低端邊界地址后的地址,否則附加地址為shmaddr指定的地址。通常shmaddr參數(shù)設(shè)置為NULL。
函數(shù)shmat調(diào)用成功返回共享內(nèi)存的附加地址;否則調(diào)用失敗返回-1。3共享內(nèi)存的分離9:4099/267
共享內(nèi)存的分離函數(shù)是shmdt。系統(tǒng)通過調(diào)用它在程序中完成共享內(nèi)存的分離工作。在Linux系統(tǒng)終端中使用幫助命令“man
shmdt”,得到共享內(nèi)存的分離函數(shù)信息如
下:#include
<sys/types.h>#include
<sys/shm.h>int
shmdt(const
void
*shmaddr);3共享內(nèi)存的分離9:40100/267
shmdt:該函數(shù)的返回類型為整型,用于分離進程的共享內(nèi)存。shmaddr參數(shù)為函數(shù)shmat的返回值。進程與共享內(nèi)存分離后,shmid_ds中的shm_nattch會自動減1。若
shm_nattch的值減為0后,表示沒有任何進程使用此共享內(nèi)存,該共享內(nèi)存將被系統(tǒng)刪除。函數(shù)shmdt調(diào)用成功返回0;否則調(diào)用失敗返回-1。4共享內(nèi)存的控制9:40101/267
共享內(nèi)存的控制函數(shù)是shmctl。系統(tǒng)通過調(diào)用它在程序中完成共享內(nèi)存的控制工作。在Linux系統(tǒng)終端中使用幫助命令“man
shmctl”,得到共享內(nèi)存的控制函數(shù)信息如
下:#include
<sys/ipc.h>#include
<sys/shm.h>int
shmctl(int
shmid,
int
cmd,
struct
shmid_ds
*buf);4共享內(nèi)存的控制9:40102/267
shmctl:該函數(shù)的返回類型為整型,用于對共享內(nèi)存的控制。shmid參數(shù)表示附加的共享內(nèi)存的引用標(biāo)示符。buf參數(shù)為指向shmid_ds結(jié)構(gòu)體的指針。cmd參數(shù)為操作標(biāo)志位,若cmd參數(shù)取值為IPC_RMID則表示刪除由shmid標(biāo)示的共享內(nèi)存區(qū);若cmd參數(shù)取值為IPC_SET則表示設(shè)置共享內(nèi)存區(qū)shmid_ds結(jié)構(gòu);cmd參數(shù)取值為IPC_STAT則表示將共享內(nèi)存區(qū)shmid_ds結(jié)構(gòu)存儲到buf指向的地址中。函數(shù)shmdt調(diào)用成功返回0;否則調(diào)用失敗返回-1。5綜合示例9:40103/267
本節(jié)最后,通過利用共享內(nèi)存的相關(guān)函數(shù)進行系統(tǒng)調(diào)用,來演示如何創(chuàng)建和使用共享內(nèi)存,加強對進程通信的理解。共享內(nèi)存的讀函數(shù)
my_shmget_reader如范例8-1a所示,共享內(nèi)存的寫函數(shù)my_shmget_writer如范例8-1b所示。例8-1a
my_shmget_reader.c/****my_shmget_reader.c***/例8-1b
my_shmget_writer.c/****
my_shmget_writer.c***/在VIM編輯器中具體闡述代碼在eclipse集成開發(fā)環(huán)境IDE中編譯、調(diào)試、運行代碼8.3信號量9:40104/267
在Linux系統(tǒng)中,信號量實質(zhì)是整數(shù)計數(shù)器,常用于處理進程或線程的對共享資源的同步和互斥問題。同步共享資源要求同一時刻允許多個進程或線程訪問該資源;互斥共享資源要求同一時刻只允許一個進程或線程訪問該資源。這里的資源可以是某種硬件資源、一段代碼或一個變量等。當(dāng)信號量的值大于或等于0時,表示并發(fā)進程或線程可使用的資源實體數(shù);信號量小于0表示正在等待使用共享資源的進程數(shù)。8.3信號量
每個進程所創(chuàng)建的信號量在操作系統(tǒng)內(nèi)核中維護著一個與之相應(yīng)的數(shù)據(jù)結(jié)構(gòu)semid_ds實例,它的具體定義如下所示:9:40105/2678.3信號量9:40106/267
每個進程所創(chuàng)建的信號量在操作系統(tǒng)內(nèi)核中維護著一個與之相應(yīng)的數(shù)據(jù)結(jié)構(gòu)semid_ds實例,它的具體定義如下:struct
semid_ds
{
struct
ipc_perm
sem_perm;
/*
Ownership
andpermissions
*/*sem_base;
/*
Pointer
of
first
sem
*/sem_otime;
/*
Last
semop
time
*/sem_ctime;
/*
Last
change
time
*/struct
semtime_ttime_t?unsigned
short
sem_nsems;
/*
No.
of
semaphoresin
set
*/};8.3信號量9:40107/267
這個結(jié)構(gòu)詳細(xì)描述了信號集的各種屬性,它們的具體含義如下所示:sem_perm:表示信號集的用戶ID、組ID、權(quán)限等信息;
sem_base:表示信號量的基地址,指向信號集中第一個信號量的地址;sem_otime:表示最后一次調(diào)用semop函數(shù)的時間;sem_ctime:表示最后一次改變該信號集的時間;sem_nsems:表示信號集中信號量的個數(shù);8.3信號量9:40108/267
這個結(jié)構(gòu)詳細(xì)描述了信號集中信號量的各種屬性,它們的具體含義如下所示:struct
sem{ushort
semval;pid_t
sempid;ushort
semncnt;ushort
semzcnt;};8.3信號量9:40109/267
這個struct
sem結(jié)構(gòu)詳細(xì)描述了它的各種屬性,它們的具體含義如下所示:semval:表示信號量的值;sempid:表示最近一次訪問共享資源的進程ID號;semncnt:表示等待利用資源的進程數(shù);semzcnt:表示全部資源被獨占的進程數(shù);下面給出基于上述信號集和信號量數(shù)據(jù)結(jié)構(gòu)的函數(shù)調(diào)用。1信號集的創(chuàng)建9:40110/267
信號集的創(chuàng)建函數(shù)是semget。系統(tǒng)通過調(diào)用它在程序中完成信號集的創(chuàng)建工作。在Linux系統(tǒng)終端中使用幫助命令“man
semget”,得到信號集的創(chuàng)建函數(shù)信息如下:#include
<sys/types.h>#include
<sys/ipc.h>#include
<sys/sem.h>int
semget(key_t
key,
int
nsems,
int
semflg);1信號集的創(chuàng)建9:40111/267
semget:該函數(shù)的返回類型為整型,用于創(chuàng)建或打開一個信號集。key參數(shù)表示由ftok生成的信號集鍵。nsems參數(shù)表示創(chuàng)建信號集中信號量的個數(shù),若是新創(chuàng)建一個信號集則nsems須大于0;若是訪問已經(jīng)存在的信號集則
nsems為0。semflg參數(shù)表示信號集的操作標(biāo)志位,用于設(shè)置信號集的訪問權(quán)限,若semflg參數(shù)取值為
IPC_CREATE,則表示系統(tǒng)將參數(shù)key與其它的信號集key進行比較,如果相同則返回已經(jīng)存在的信號集標(biāo)識符,如果不同則新建一個信號集并返回其標(biāo)識符;若semflg
參數(shù)取值為IPC_EXCL,則表示無意義;若semflg參數(shù)取
值為IPC_CREATE
|
IPC_EXCL,表示如果發(fā)現(xiàn)信號集已經(jīng)存在,則返回-1。1
ftok函數(shù)深度解析9:40112/267
關(guān)于ftok函數(shù),先不去了解它的作用來先說說為什么要用它,共享內(nèi)存,消息隊列,信號量它們?nèi)齻€都是找一個
中間介質(zhì),來進行通信的,這種介質(zhì)多的是。就是怎么
區(qū)分出來,就像唯一一個身份證來區(qū)分人一樣。你隨便
來一個就行,就是因為這。只要唯一就行,就想起來了
文件的設(shè)備編號和節(jié)點,它是唯一的,但是直接用它來
作識別好像不太好,不過可以用它來產(chǎn)生一個號。ftok()就出場了。ftok函數(shù)具體形式如下:1
ftok函數(shù)深度解析9:40113/267key_t
ftok(const
char
*pathname,
int
proj_id);
其中參數(shù)fname是指定的文件名,這個文件必須是存在的而且可以訪問的。id是子序號,它是一個8bit的整數(shù)。即范圍是0~255。當(dāng)函數(shù)執(zhí)行成功,則會返回key_t鍵值,
否則返回-1。在一般的UNIX中,通常是將文件的索引節(jié)
點取出,然后在前面加上子序號就得到key_t的值。有關(guān)該函數(shù)的三個常見問題:
1.pathname是目錄還是文件的具體路徑,是否可以隨便設(shè)置2.pathname指定的目錄或文件的權(quán)限是否有要求
3.proj_id是否可以隨便設(shè)定,有什么限制條件1
ftok函數(shù)深度解析9:40114/267解答:
1、ftok根據(jù)路徑名,提取文件信息,再根據(jù)這些文件信息及project
ID合成key,該路徑可以隨便設(shè)置。
2、該路徑是必須存在的,ftok只是根據(jù)文件inode在系統(tǒng)內(nèi)的唯一性來取一個數(shù)值,和文件的權(quán)限無關(guān)。
3、proj_id是可以根據(jù)自己的約定,隨意設(shè)置。這個數(shù)字,有的稱之為project
ID;在UNIX系統(tǒng)上,它的取值是1到255;ftok()函數(shù)深度解析
/u013485792/article/details/5076422
41
ftok函數(shù)深度解析9:40115/2671
ftok函數(shù)深度解析9:40116/2671信號集的創(chuàng)建9:40117/267
函數(shù)調(diào)用成功返回信號集的引用標(biāo)示符,同時該共享內(nèi)存的shmid_ds結(jié)構(gòu)被初始化;否則調(diào)用失敗返回-1。2信號集的操作9:40118/267
信號量的值和資源使用情況有關(guān)系,當(dāng)信號量的值大于或等于0時,表示并發(fā)進程或線程可使用的資源實體數(shù);信號量小于0表示正在等待使用共享資源的進程數(shù)。信號量值的改變通過在PV操作中調(diào)用信號量的操作函數(shù)
semop,來實現(xiàn)信號量的改變。2信號集的操作9:40119/267
信號量的操作函數(shù)是semop。系統(tǒng)通過調(diào)用它在程序中完成信號量的操作工作。在Linux系統(tǒng)終端中使用幫助命令“man
semop”,得到信號量的操作函數(shù)信息如下:#include
<sys/types.h>#include
<sys/ipc.h>#include
<sys/sem.h>
int
semop(int
semid,
struct
sembuf
*sops,
unsignednsops);2信號集的操作9:40120/267sem_op;
/*
semap
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026年揚州中瑞酒店職業(yè)學(xué)院單招職業(yè)技能考試備考題庫含詳細(xì)答案解析
- 初中九年級地理(上冊)期末試題及答案
- 新學(xué)員職業(yè)指南
- 中國消防安全視頻課程
- 2026秋招:攜程商務(wù)面試題及答案
- 2026秋招:甘肅能化股份公司筆試題及答案
- 2025年食品加工與安全管理手冊
- 保密協(xié)議2026年采購保密條款
- 2026年車載充電樁安裝服務(wù)協(xié)議
- 2026年春季學(xué)期XX市第二中學(xué)-學(xué)生社團活動-年度計劃:興趣社團與學(xué)科輔導(dǎo)課程安排
- 2026年哈爾濱五常市廣源農(nóng)林綜合開發(fā)有限公司招聘工作人員5人筆試備考題庫及答案解析
- 2025年農(nóng)村人居環(huán)境五年評估報告
- 《開學(xué)第一課:龍馬精神·夢想起航》課件 2025-2026學(xué)年統(tǒng)編版語文七年級下冊
- 2026年洪湖市事業(yè)單位人才引進100人參考考試題庫及答案解析
- 2026年中好建造(安徽)科技有限公司第一次社會招聘42人筆試參考題庫及答案解析
- 北京市海淀區(qū)2025一2026學(xué)年度第一學(xué)期期末統(tǒng)一檢測歷史(含答案)
- 2026年科研儀器預(yù)約使用平臺服務(wù)協(xié)議
- 浙江省杭州市拱墅區(qū)2024-2025學(xué)年四年級上冊期末考試數(shù)學(xué)試卷(含答案)
- 三亞市海棠灣椰子洲島土地價格咨詢報告樣本及三洲工程造價咨詢有限公司管理制度
- 常見磁性礦物的比磁化系數(shù)一覽表
- 高中心理健康教育-給自己點個贊教學(xué)課件設(shè)計
評論
0/150
提交評論