進(jìn)程共享資源信號量控制詳細(xì)實(shí)現(xiàn)源碼及解釋

上傳人:痛*** 文檔編號:46843810 上傳時(shí)間:2021-12-15 格式:DOC 頁數(shù):21 大?。?5KB
收藏 版權(quán)申訴 舉報(bào) 下載
進(jìn)程共享資源信號量控制詳細(xì)實(shí)現(xiàn)源碼及解釋_第1頁
第1頁 / 共21頁
進(jìn)程共享資源信號量控制詳細(xì)實(shí)現(xiàn)源碼及解釋_第2頁
第2頁 / 共21頁
進(jìn)程共享資源信號量控制詳細(xì)實(shí)現(xiàn)源碼及解釋_第3頁
第3頁 / 共21頁

下載文檔到電腦,查找使用更方便

0 積分

下載資源

還剩頁未讀,繼續(xù)閱讀

資源描述:

《進(jìn)程共享資源信號量控制詳細(xì)實(shí)現(xiàn)源碼及解釋》由會員分享,可在線閱讀,更多相關(guān)《進(jìn)程共享資源信號量控制詳細(xì)實(shí)現(xiàn)源碼及解釋(21頁珍藏版)》請?jiān)谘b配圖網(wǎng)上搜索。

1、信號量 信號量(Semap?hore)簡單的說就?是用來控制?多個進(jìn)程對?共享資源使?用的計(jì)數(shù)器?。它是常被用?作一種鎖定?保護(hù)機(jī)制,當(dāng)某個進(jìn)程?對資源進(jìn)行?操作時(shí)阻止?其他進(jìn)程對?該資源的訪?問。需要注意的?是,Syste?m V中的的信?號量對象實(shí)?際上是信號?量的集合(set),它可以包含?多個信號量?,控制多個共?享資源。 有關(guān)的數(shù)據(jù)?結(jié)構(gòu) 和消息隊(duì)列?一樣,我們在介紹?他的使用前?先介紹一些?相關(guān)的數(shù)據(jù)?結(jié)構(gòu): 1. sem 前提提到,信號量對象?實(shí)際是多個?信號量的集?合。在Linu?x系統(tǒng)中,這種集合是?以數(shù)組的形?式實(shí)現(xiàn)的。數(shù)組的每個?成員都是一?個單獨(dú)的信?號量,它

2、們在系統(tǒng)?中是以se?m結(jié)構(gòu)的形?式存儲的。Sem的結(jié)?構(gòu)在Lin?ux系統(tǒng)l?inux/sem.h中定義是?這樣的: /* One semap?hore struc?ture for each semap?hore in the syste?m. */ Struc?t sem{ Short? sempi?d; /*pid of last opera?tion*/ Ushor?t semva?l; /*curre?nt value?*/ Ushor?t semnc?nt;

3、 /*num procs? await?ing incre?ase in semva?l*/ Ushor?t semzc?nt; /*num procs? await?ing semva?l=0*/ }; 其中, Sem_p?id成員保?存了最近一?次操作信號?量進(jìn)程的p?id。 Sem_s?emval?成員保存著?信號量的計(jì)?數(shù)值。 Sem_s?emncn?t成員保存?著等待使用?資源的進(jìn)程?數(shù)目。 Sem_s?emzcn?t成員保存?等待資源完?全空閑的進(jìn)?程數(shù)目。 2.semun? Semun?聯(lián)合在se?

4、nctl()函數(shù)中使用?,提供sen?ctl()操作所需要?的信息。它在Lin?ux系統(tǒng)l?inux/sem.h中定義是?這樣的: /*arg for semct?l syste?m calls? */ Union? semun?{ Int val; /*value? for SETVA?L*/ Struc?t semid?_ds *buf; /*buffe?r for IPC_S?TAT&SETAL?L*/ Ushor?t *array?; /*

5、array? for GETAL?L&SETAL?L*/ Struc?t semin?fo *__buf?; /* buffe?r for IPC_I?NFO*/ Void *_pad; }; 前三個參數(shù)?在對sen?ctl()函數(shù)介紹中?會講到,這里暫時(shí)先?不管它們。后兩個參數(shù)?是Linu?x系統(tǒng)所獨(dú)?有的,只是系統(tǒng)的?內(nèi)核中使用?。 3. semuf? semuf?結(jié)構(gòu)被se?mop()函數(shù)(后面會講到?)用來定義對?信號量對象?的基本操作?。它在lin?ux/sem.h中是這樣?定義的: /*semop? syste?m c

6、alls? takes? an array? of these?.*/ Stcuc?t sembu?f{ Unsig?ned short? sem_n?um; /*semap?hore index? in array?*/ Short? sem_o?p; /*semap?hore opera?tion*/ Short? sem_f?lg; /*opera?tion flags?*/ }; 其中, Sem_n?um 成員為接受?操作的

7、信號?量在信號量?數(shù)組中的序?號(數(shù)組下標(biāo))。 Sem_o?p成員定義?了進(jìn)行的操?作(可以是正,負(fù)和零)。 Sem_f?lg是控制?操作行為的?標(biāo)志。 如果sem?_op是負(fù)?值,就從指定的?信號量中減?去相應(yīng)的值?。這對應(yīng)著獲?取信號量所?監(jiān)控 的資源操作?。如果沒有s?em_fl?g指定IP?C_NOW?AIT標(biāo)志?,那么,當(dāng)現(xiàn)有的信?號量數(shù)值小?于sem_?op的絕對?值(表示現(xiàn)有的?資源少于要?獲取的資源?)時(shí),調(diào)用sem?op()_函數(shù)的進(jìn)?程就會被阻?塞知道信號?量的數(shù)值大?于sem_?op的絕對?值(表示有足夠?的資源被釋?放)。 如果sem?_op是正?值,

8、就在指定的?信號量中加?上相應(yīng)的值?。這對應(yīng)著釋?放信號量所?監(jiān)控 的資源 操作。 如果sem?_op是零?,那么調(diào)用s?emop()函數(shù)的進(jìn)程?就會被阻塞?到直對應(yīng)的?信號量值為?零。 這種操作的?實(shí)質(zhì)就是等?待信號量所?監(jiān)控的資源?被全部使用?。利用這種資?源操作可以?動態(tài)監(jiān)控資?源的使用并?調(diào)整資源的?分配,避免不必要?的等待。 4. Semid?_qs 和msgq?id_ds?類似,semid?_qs結(jié)構(gòu)?被系統(tǒng)用來?存儲每個信?號量對象的?有關(guān)信息。它在Lin?ux 系統(tǒng)庫li?nux/sem.h中是這樣?定義的: /*One semid? data struc

9、?ture for each set of semap?hores? in the syste?m*/ Struc?t semid?_ds{ Struc?t ipc_p?erm sem_p?erm; /*permi?ssion?s.. see ipc.h*/ __ker?nel_t?ime_t? sem_o?time; /*tast semop? time*/ __ker?nel_t?ime_t? sem_c?time; /*last chang?e time*/

10、Struc?t sem *sem_b?ase; /*ptr to first? semap?hore in array?*/ Struc?t sem_q?ueue *sem_p?endin?g; /*pendi?ng oprat?ions to be prose?ssed*/ Struc?t sem_q?ueue **sem_p?endin?g_las?t; /*last pendi?ng oprat?ion*/ Struc?t sem_u?ndo *undo; /*und

11、o reque?sts on this array?*/ Unsig?ned short? sem_n?sems; /*no.of semap?hores? in array?*/ }; 其中 Sem_p?erm成員?保存了信號?量對象的存?取權(quán)限以及?其他一些信?息(見上面關(guān)于?ipc_p?erm結(jié)構(gòu)?的介紹)。 Sem_o?time成?員保存了最?近一次se?mop()操作的時(shí)間?。 Sem_c?time成?員保存了信?號量對象最?近一次改動?發(fā)生的時(shí)間?。 Sem_b?ase指針?保存著信號?量數(shù)組的起?始地址。 Sem_p?en

12、din?g指針保存?著還沒有進(jìn)?行的操作。 Sem_p?endin?g_las?t指針保存?著最后一個?還沒有進(jìn)行?的操作。 Sem_u?ndo成員?保存了un?do請求的?數(shù)目。 Sem_n?sems成?員保存了信?號量數(shù)組的?成員數(shù)目。 4.8.2有關(guān)的函?數(shù) 介紹完有關(guān)?的數(shù)據(jù)結(jié)構(gòu)?,接下來我們?將介紹使用?信號量要用?到的函數(shù): 1.semge?t() 使用sem?ger()函數(shù)來建立?新的信號量?對象或者獲?取已有的對?象的標(biāo)示符?。它在lin?ux/sem.h 中的函數(shù)聲?明是這樣的?: 系統(tǒng)調(diào)用:Semge?t() 函數(shù)聲明:int semge?t(k

13、ey_t? key,int nsems?,int semfl?g); 返回值:semap?hore set IPC ident?ifier? on succe?ss —1on error?:errno?=EACCE?SS(permi?ssion? denie?d)權(quán)限不足 EEXIS?T(set exist?,canno?t creat?e(IPC_E?XCL))信號量已存?在,無法創(chuàng)建 EIDRM?(set is marke?d for delet?ion)信號量待刪?

14、 ENOEN?T(set does nor exisr?,no IPC_C?REAT was usrd)信號量不存?在,無法打開 ENOME?M(Not enoug?h memor?y to creat?e new set)無足夠內(nèi)存?以創(chuàng)建新信?號量 ENOSP?C(Maxim?un set limit? excee?ded)信號量個數(shù)?已滿 函數(shù)接受三?個參數(shù)。其中第一個?參數(shù)key?和第三個參?數(shù)semf?lg和前面?講過的ms?gget()函數(shù)中的兩?個參數(shù)對應(yīng)?的,作用和取值

15、?的意義也相?同,讀者可以參?看msgg?et()的有關(guān)介紹?。函數(shù)的第二?個參數(shù)ns?ems是信?號量對象所?特有的。它指定了新?生成的信號?量對象中信?號量的數(shù)目?,也就是信號?量數(shù)組成員?的個數(shù)。在linu?x/sem.h定義了它?的上限: #defin?e SEMMS?L 32 /*<=512 max num of semap?hores? per id */ 如果函數(shù)執(zhí)?行的是打開?而不是創(chuàng)建?操作,則這個參數(shù)?被忽略。 下面我們創(chuàng)?建一個封裝?函數(shù)作為本?屆例子: Int open_?semap?hore_?set(key_t? keyva?l,int nums

16、e?ms) { Int sid; If(!numse?ms) Retur?n(-1); If(sid=semge?t(mykey?,numse?ms,IPC_C?REAT|0660))==-1) { Retur?n(-1); } Retur?n(sid) } 程序的分析?請讀者自行?完成。 2.semop?() 使用這個函?數(shù)來改變信?號量對象中?各個信號量?的狀態(tài)。它在Lin?ux系統(tǒng)庫?linux?/sem.h中的函數(shù)?聲明如下: 系統(tǒng)調(diào)用:semop?() 函數(shù)聲明:int

17、 semop?(int semid?,struc?t sembu?f*sops,unsig? 返回值:0 on succe?ss(all opera?tions? perfo?rmed) -1 on error?:errno?=E2BIG?(nsops? great?er than max numbe?r of ops allow?edato?mical?ly)系統(tǒng)允許一?次進(jìn)行的操?作數(shù)小于 nsops? EACCE?S(permi?ssion? denie?d)權(quán)限不足 EAGAI?N(IPC_N?OWALT? asser?ted,o

18、pera?tion could? not go throu?gh)操作不能進(jìn)?行(IPC_N?OWALT?標(biāo)志是使用?) EFAUL?T(inval?id addre?ss point?ed to by sops argum?ent sops)地址非法 EIDRM?(semap?hore set was remov?ed)信號量已被?刪除 EINTR?(Signa?l recei?ved while? sleep?ing)阻塞被信號?中止 EINVA?L(set doesn?’t exist?,or semid? is i

19、nval?id)信號量不存?在或sem?id非法 ENOME?M(SEM_U?NDO asser?ted,not enoug?h memor?y to creat?e the undo struc?ture neces?sary)內(nèi)存不足,無法進(jìn)行u?ndo操作?(指定SEM?_UNDO?時(shí)) ERANG?E(semap?hore value? out of range?)信號量的值?越界 函數(shù)的第一?個參數(shù)se?mid是要?操作的信號?量對象的標(biāo)?示符。第二個參數(shù)?sops是?sembu?f的數(shù)組,它定義了s?emop()函數(shù)所要進(jìn)?行的操作序?列。第三

20、個參數(shù)?nsops?保存數(shù)組的?長度,也即sem?op()函數(shù)將進(jìn)行?的操作個數(shù)?。 在前面對s?embuf?結(jié)構(gòu)的介紹?中已經(jīng)介紹?了semo?p()的各種基本?操作。下面我們將?結(jié)合例子對?這些操作作?進(jìn)一步的介?紹。首先假設(shè)已?經(jīng)通過se?mget()函數(shù)得到了?一個只包含?一個信號量?的信號量對?象,它在監(jiān)控著?某臺最多能?處理10分?作業(yè)的打印?機(jī)的使用。我們下面的?操作都將是?只針對這個?信號量的。 假設(shè)要向打?印機(jī)交付一?份作業(yè)??梢远x下?面的sem?buf變量?來完成這個?操作: Struc?t sembu?f sem_g?et={0,-1,IPC_N?OWAIT?};

21、 它告訴系統(tǒng)?,將信號量對?象中序號為?零的信號量?(第一個信號?量)減一。IPC_N?OWAIT?標(biāo)志的定義?告訴系統(tǒng),如果打印機(jī)?的作業(yè)量(10份)已滿,則不阻塞進(jìn)?程而是直接?將控制權(quán)返?回進(jìn)程并返?回失敗信息?。 定義完操作?后,我們使用下?面的代碼來?執(zhí)行它: If(semop?(sid,&sem_g?et,1)==-1) Perro?r(“semop?”); 作業(yè)打印完?成后,我們使用下?面的sem?buf變量?來定義一個?釋放資源的?操作: Struc?t sembu?f sem_r?eleas?e={0,1,IPC_N?OWAIT?}; 它告訴系統(tǒng)?將信

22、號量對?象中序號為?零的對象加?一。 然后用下面?的代碼來完?成這個操作?: Semop?(sid,&sem_r?eleas?e,1); 這樣,我們就完成?了一個完整?的作業(yè)打印?操作。 3.semct?l()函數(shù) 和消息隊(duì)列?的msgc?tl()函數(shù)類似,semct?l()函數(shù)被用來?直接對信號?量對象進(jìn)行?控制。它在lin?ux/sem.h中的函數(shù)?聲明如下: 系統(tǒng)調(diào)用:semct?l() 函數(shù)聲明:int semct?l(int semid?,int semnu?m,int cmd,union? semun? arg); 返回值:posit?ive integ?

23、er on succe?ss -1 on error?:errno?=EACCE?SS(permi?ssion? denie?d)權(quán)限不足 EFAUA?L(semap?hore set was remov?ed)信號量已被?刪除 EINVA?L(set doesn?’t exist?,or semid? is inval?id)信號量不存?在或sem?id非法 EPERM?(EUD hasno? privi?leges? for

24、 cmd in arg)無權(quán)進(jìn)行指?定的操作 ENANG?E(semap?hore value? out of range?)信號量的值?超界 比較一下這?兩個函數(shù)的?參數(shù)我們會?發(fā)現(xiàn)一些細(xì)?微的差別。首先,因?yàn)樾盘柫?對象事實(shí)上?是多個信息?量的集合而?非單一的個?體,所以在進(jìn)行?操作時(shí),不僅需要指?定對象的標(biāo)?示符。還需要用信?號量在集合?中的序號來?指定具體的?信號量個體?。 兩個函數(shù)都?有cmd參?數(shù),指定了函數(shù)?進(jìn)行的具體?操作。不過,和msgc?tl()函數(shù)相比,semct?l()函數(shù)可以盡?心的操作要?多得多: IPC_S?TAT取得?信

25、號量對象?的semi?d_ds結(jié)?構(gòu)信息,并將其存儲?在arg參?數(shù)中buf?指針?biāo)竷?nèi)?存中返回。 IPC_S?ET用ar?g參數(shù)中b?uf的數(shù)據(jù)?來設(shè)定信號?量對象的s?emid-ds結(jié)構(gòu)信?息。和消息隊(duì)列?對象一樣,能被這個函?數(shù)設(shè)定的只?有少數(shù)幾個?參數(shù)。 IPC_R?MID從內(nèi)?存中刪除信?號量對象。 GETAL?L取得信號?量對象中所?有信號量的?值,并存儲在a?rg參數(shù)中?的arra?y數(shù)組中返?回。 GETNC?NT返回正?在等待使用?某個信號量?所控制的資?源進(jìn)程數(shù)目?。 GETPI?D返回最近?一個對某個?信號量調(diào)用?semop?()函數(shù)的進(jìn)程?的pid. GE

26、YVA?L返回信號?量的計(jì)數(shù)值?。 GETZC?NT 返回正在等?待某個信號?量所控制資?源全部使用?的進(jìn)程數(shù)目?。 SETAL?L用arg?參數(shù)中ar?ray數(shù)組?的值來設(shè)定?對象內(nèi)某個?信號量的值?。 函數(shù)的第四?個參數(shù)ar?g提供了操?作所需要的?其他信息。它的各個成?員的意義在?前面已經(jīng)有?個介紹,這里不再贅?述。需要強(qiáng)調(diào)的?是它和ms?gctl()中的參數(shù)不?一樣,是一個普通?的變量而不?是指針,初學(xué)者常常?在這個問題?上犯錯誤。 下面舉幾個?使用sem?ctl()的例子。 Int get_s?em_va?l(Int sid,int semnu?m) {

27、 retur?n(semct?l(sid,semnu?m,GETVA?L,0)); } 上面的代碼?返回到信號?量對象中某?個信號來那?個的值。注意這里s?emctl?()函數(shù)的最后?一個參數(shù)取?的是零,這是因?yàn)閳?zhí)?行GETV?AL命令時(shí)?這個參數(shù)被?自動忽略了?。 Void init_?semap?hore(int sid,int semnu?m,int initv?al) { Union? semun? semop?ts; Semop?ts.val=initv?al; Semct?l(sid,semum?,SETVA?L

28、,semop?ts); } 上面的代碼?用init?val參數(shù)?來設(shè)定信號?量對象某個?信號量的值?。 最后用一個?例子來強(qiáng)調(diào)?一個極易被?忽視的錯誤?。 在消息隊(duì)列?和信號量對?象中,都有IPC?_STAT?和IPC_?SET的操?作。但是由于傳?遞參數(shù)的類?型不同,造成了它們?在使用上的?差別。在msgc?tl()函數(shù)中,IPC_S?TAL 操作只是簡?單的將內(nèi)核?中msfq?id_ds?結(jié)構(gòu)的地址?賦予buf?參數(shù)(是一個指針?)。而在sem?ctl()函數(shù)中,IPC_S?TAT操作?是將sem?id_ds?的內(nèi)容拷貝?到arg參?數(shù)的buf?成員指針?biāo)?指的內(nèi)存中?,所以,下面

29、的代碼?會產(chǎn)生錯誤?,而msgc?tl()函數(shù)的類似?代碼卻不會?: Void getmo?de(int sid) { Int rc; Union? semun? semop?s; /*下面的語句?會產(chǎn)生錯誤?*/ If (rc=semct?l(sid,0,IPC_S?TAT,semop?ts))=-1) { Perro?r(“semct?l”); Exit(1); } Print?f(“pemis?sion mode were %o\n”,semop?ts.bu

30、f->sem_p?erm.mode); Retur?n; } 為什么呢?一位現(xiàn)實(shí)沒?有給buf?指針分配內(nèi)?存,其指向是不?確定的。這種“不定向”的指針式c?程序中最危?險(xiǎn)的陷阱之?一。改正這個錯?誤,只需要前提?給buf指?針準(zhǔn)備一塊?內(nèi)存。下面是修改?過的代碼: Void getmo?de(int sid) { Int rc; Union? semun? sempo?ts; Struc?t semid?_ds mysem?ds; /*給buf指?針準(zhǔn)備一塊?內(nèi)存*/ Semop?ts.buf = &

31、mysem?ds; /*現(xiàn)在ok了?*/ If(rc=semct?l(sid,0,IPC_S?TAT,semop?ts))==-1) { Perro?r(“semct?l”) Exit(1); } Print?f(“permi?ssion? Mode were %o\n”,semop?ts.buf->sem_p?em.mode); Retur?n; } 4.8.3信號量的?實(shí)例 1.背景知識 Semto?ol工具通?過命

32、令行參?數(shù)來決定它?的行為,這樣它可以?決定它的行?為,這樣他可以?被方便的應(yīng)?用于she?ll腳本中?。Semto?ol提供了?和信號量有?關(guān)的全部功?能,包括創(chuàng)建信?號量、操作、刪除信號量?對象以及更?改信號量權(quán)?限等。使用它,我們可以在?命令行上控?制資源的共?享。 2.semto?ol的命令?行語法 建立信號量?對象: semto?ol c (numbe?r of semap?hores? in set) 鎖定信號量?: semto?ol l(semap?hore numbe?r to lock) 解鎖信號量?的鎖定: semto?ol u (semap?

33、hore numbe?r to unloc?k) 改變信號量?的權(quán)限: semto?ol m (mode) 刪除信號量?對象:semto?ol d 3. semto?ol的使用?舉例 Semto?ol c 5 Semto?ol 1 Semto?ol u Semto?ol m 660 Semto?ol d 4.semto?ol 的源代碼: Semto?ol程序的?源代碼如下?: #inclu?de #inclu?ude #inclu?de #inclu?de #in

34、clu?de #inlcl?ude #defin?e SEM_R?ESOUR?CE_MA?X 1 /*initi?al value? of all semap?hores?(所有信號量?的初始值)*/ Void opens?em(int *sid,key_t? key); Void creat?esem(int *sid,key_t? key,int membe?rs); Void locks?em(int sid,int membe?r); Void unlok?sem(int sid,int membe?r); Vo

35、id remov?esem(int sid); Unsig?ned short? get_m?ember?_coun?t(int sid); Int getva?l(int sid,int membe?r); Void dispv?al(int sid,int membe?r); Void chang?emode?(int sid,char *mode); Void usage?(void); Int main(int argc,char*argv[]) { Key_t? key; Int semse?t_id;

36、 If(argc==1) Usage?(); /*Creat?e uniqu?e key via call to ftok()(用ftok?()函數(shù)創(chuàng)建關(guān)?鍵字)*/ Key=ftok(“,”,’s’); Switc?h(tolow?er(argv[1][0])) { Case ‘c’:if(argc!=3) Usage?(); Creat?esem(&semse?t_id,key,

37、atoi(argv[2])); Break?; Case’l’:if(argc!=3) Usage?(); Opens?em(&semse?t_id,key); Locks?em(semse?t_id,atoi(argv[2])); Break?; Case ‘u’:if(argc!=3) Usage?(); Opens?em(&semse?t_id,key);

38、 Unloc?ksem(semse?t_id,atoi(arge[2])); Break?; Case’d’:opens?em(&semse?t_id,key); Remov?esem(semse?t_id); Break?; Case ‘m’:opens?em(&semse?t_id,key); Chang?emode?(semse?t_id,argv[2]); Break?;

39、Defau?lt:usage?(); } Retur?n(0); } Void opens?em(int*sid,key_t? key) { /*Open the semap?hore set-do not creat?e!(打開信號量?對象(而不是創(chuàng)建?它))*/ If((*sid=semge?t(key,0,0666))==-1) { Print?f(“Semap?hore set does not exist?!\n”); Exit(1); } } Void creat?e

40、sem(int*sid,key_t? key,int membe?rs) { Int cntr; Union? semun? semop?ts; If(membe?rs>SEMMS?L){ Prinf?f(“Sorry?,max numbe?r of semap?hores? in a set is %d\n”,SEMMS?L); Exit(1); } Print?f(“Attem?pting? to cteat?e ne

41、w semap?hore set with %d membe?rs\n”,membe?rs); If((*sid=semge?t(key,membe?rs,IPC_C?REAIT?|IPC_E?XCL|0666))==-1) { Fprin?tfs(stder?r,”Semap?hore set alrea?dy exist?s!\n”); Exit(1); } Semot?s.val=SEM_R?ESOUR?CE_MA?X; /*lniti?alize? all membe?rs (Could? be done

42、 with SETAL?L)初始化對象?內(nèi)所有信號?量(該操作也可?以用SET?ALL完成?)*/ For(cntr=0;cntr(get_m?ember?_cout?(sid)-1)) { Fprin?tf(stde

43、r?r,”semap?hore membe?r%d out of rang\n”,membe?r); Retur?n; } /*Attem?pt to luck the semap?hore set 嘗試鎖定信?號量*/ If(!getva?la(sid,membe?r)) { Fprin?tf(stder?r,”semap?hore membe?r%d ouot of rang\n”,membe?r); Retur?n; } /*Attnm?pt to lock the semph?ore set嘗試?鎖定信號量?*/

44、If(!getva?l(sid,membe?r)) { Fprin?tf(stder?r,”Semap?hore resou?rces exhau?sted (no lock)!\n”); Exit(1); } Sem_l?ock.sem_n?um=membe?r; If((semop?(sid,&sem_l?ock,1))==-1)) { Fprin?tff(stder?r,”Lock faild?\n”); Exit(1); } Else Print?f(“Semap?h

45、ore resou?rces decre?memte?d by one(lockd?)\n”); Dispv?al(sid,membe?r); } Void unloc?ksem(int sid,int membe?r) { Struc?t sembu?f sem_u?nlock?={membe?r,1,IPC_N?OWALT?}; Int semva?l; } If(membe?r<0||membe?r>(get_m?ember?_coun?t(sid)-1)) { Fprin?tf(stder?r,”semap?hore mem

46、be?r%d out of rang\n”,membe?r); Retur?n; } /*Is the semap?hore set locke?d?判斷信號量?是否被鎖*/ Semva?l=getva?l(sid,membe?r); If(semva?l==SEM_R?ESOUR?CE_MA?X){ Fprin?tf(stder?r,”Semap?hore not locke?d!\n”); Exit(1); } Sem_u?nlock?,sem_n?um=membe?r; /*Attem?pt to lock the semap?hore

47、set 嘗試解除鎖?定*/ If((semop?(sid,&sem_u?nlock?,1))==-1) { Fprin?tf(stder?r,”Unloc?k faile?d\n”); Exit(1); } Else Print?f(“Semap?hore resou?rces incre?mente?d by one(unloc?ked)\n”; Dispv?al(sid,membe?r); } Void remov?esem(int sid) { Semct?l(sid,0,IPC_R?

48、MID,0); Print?f(“Semap?hore remov?ed\n”); } Unsig?ned short? ger_m?ember?_cout?(int sid) { Union? semun? semot?s; Struc?t semid?_ds mysem?ds; Semop?ts.buf=&mysem?ds; /*Retur?n numbe?r of menbe?rs in the semap?hore set(返回對象內(nèi)?的信號量個?數(shù))*/ Retur?n(semop?

49、ts.buf->sem_n?sems); } Int getva?l(int sid,int membe?r) { Int semva?l; Semva?l=semct?l(sid,membe?r,GETVA?L.0); Retur?n(semva?l); } Void chang?emode?(int sid,char*mode) { Int rc; Union? semun? semop?ts; Struc?t semid?_ds mysem?ds; /*Get curre?nt value?s

50、 for inter?nal data struc?ture(獲取對象當(dāng)?前的狀態(tài))*/ Semop?ts.buf =&mysem?ds; Rc=semct?l(sid,0,IPC_S?TAT,semop?ts); If(rc==-1){ Perro?r(“semct?l”); Exit(1); } Print?f(“Old permi?ssion?s were%o\n”,semop?ts,buf->sem_p?erm.mode); /*chang?e the permi?ssion?s on the semap?hore(讀取信號量?對象的權(quán)限?)

51、*/ Sscan?f(mode,”%ho”,&sempo?t.buf->sem_p?em.mode); /*Updat?e the inter?nal data struc?ture更?新權(quán)限*/ Semct?l(sid,0,IPC_S?ET,semop?ts); Print?f(Updat?ed…\n”); } Void dispv?al(int sid,int membe?r) { Int semva?l; Semva?l=semct?l(sid,membe?r,GETVA?L,0); Print?f(“semva?l

52、for membe?r%d\n”,membe?r,semva?l); } Void usage?(void) { Fprin?tf(“stder?r,”semto?ol-A utili?ty for thike?ring with semap?hores?\n”); Fprin?tf(“stder?r,”\Nusag?e:semto?ol4(c)reate?\n”); Fprin?tf(stder?r,” (l)ock\n”); Fprin?tf(stder?r,

53、” (u)nlock?\n”); Fprin?tf(stder?r,” (d)elete?\n”); Fprin?tf(stder?r,” (m)ode\n”); Exit(1); } 4.9共享內(nèi)存? 共享內(nèi)存(Share?d Memor?y)簡單的說就?是被多個進(jìn)?程共享的內(nèi)?存。它在各種進(jìn)?程通信方法?中是最快的?,因?yàn)樗鼘⑹?信息直接映?射到內(nèi)存中?,省去了其他?IPC方法?的中間步驟?。 4.9.1有關(guān)的數(shù)?據(jù)機(jī)構(gòu) 下面我們介?紹幾個和共

54、?享內(nèi)存有關(guān)?的數(shù)據(jù)結(jié)構(gòu)?: 1.shmid?_ds 和前面介紹?的兩個IP?C對象一樣?,共享內(nèi)存也?有一個給系?統(tǒng)內(nèi)存用來?保存相關(guān)信?息的結(jié)構(gòu),就是shm?id_ds?.它在 linux?/shm.h中的定義?是這樣的: Struc?t shmid?_ds{ Struc?t ipc_p?erm shm_p?erm; /*opera?tion perms?*/ Int shm_s?egsz; /*size of segme?nt (bytes?)*/ _kern?el_ti?me_t shm_a?t

55、ime: /*last attac?h time*/ _kern?el_ti?me_t shm_d?time: /*last detac?h time*/ _kern?el_ti?me_t shm_c?time; /*last chang?e time*/ _kern?el_ip?c_pid?_t shm_c?pid; /*pid of creat?or*/ _kern?el_ip?c_pid?_t shm_l?pid; /*pid of creat?or*/ Unsig?ned short?

56、 shm_n?attch?; /*no.of curre?nt attac?hes*/ Unsig?ned short? shm_u?nused?; /.*compa?tibil?ity*/ Void *shm_u?nused?2; /*ditto?-used by DIPC*/ Void *shm_u?nused?3; /*unuse?d*/ } 其中, Shm_p?erm成員?保存了共享?內(nèi)存對象的?存取權(quán)限及?其他一些信?息。 Shm_s?egze成?員定義了共?享內(nèi)存大

57、小?(以字節(jié)胃單?位) Shm_a?time成?員保存了最?近一次進(jìn)程?連接共享內(nèi)?存的時(shí)間。 Shm_d?time成?員保存了最?近一次進(jìn)程?斷開與共享?內(nèi)容的連接?時(shí)間。 Shm_c?time成?員保存了最?近一次sh?mid_d?s結(jié)構(gòu)內(nèi)容?改變的時(shí)間? Shm_c?pid成員?保存了創(chuàng)建?共享內(nèi)容的?進(jìn)程pid? Shm_l?pid成員?保存了最近?一次連接共?享內(nèi)存的進(jìn)?程pid. Shm_n?attch?成員保存了?與共享內(nèi)存?連接的進(jìn)程?數(shù)目。 剩下的三個?成員被內(nèi)核?保留使用,這里就不介?紹了。 4.9.2有關(guān)的函?數(shù) 接下來我們?介紹和共享?內(nèi)存有關(guān)的?函數(shù)

58、: 1.Sys_s?hmgrt?()函數(shù) 使用shm?get()函數(shù)來創(chuàng)建?新的獲取得?已有的共享?內(nèi)存。它在Lin?ux 系統(tǒng)lin?ux/shm.h中的定義?是這樣的: 系統(tǒng)調(diào)用:shmge?t() 函數(shù)聲明:int shmge?t(key_t? key,int size,int shmfl?g); 返回值:share?d memor?y segme?nt ident?ifier? on succe?ss -1 on error?:errno?=EINVA?L(lnval?id segme?nt size speci?fied指?定的共享內(nèi)?存大小非法?)

59、 EEXIS?T(Segme?nt exist?s,canno?t creat?e共享內(nèi)存?已存在,無法創(chuàng)建) EIDRM?(Segme?nt is marke?d for delet?ion,or was remov?e共享內(nèi)存?待刪或已刪?) ENOEN?T(Segme?nt does not exist?共享內(nèi)存不?存在,無法打開) EACCE?S(Permi?ssion? denie?d權(quán)限不足?) ENOME?M(

60、Not enoug?h memor?y to creat?e segme?nt 內(nèi)存不足,無法創(chuàng)建共?享內(nèi)存) 和前面兩個?IPC對象?函數(shù)一樣,shmge?t()函數(shù)的第一?個參數(shù)ke?y是共享內(nèi)?存的關(guān)鍵字?;第二個參數(shù)?size是?創(chuàng)建的共享?內(nèi)存的大小?,以字節(jié)為單?位。第三個參數(shù)?shmfl?g是控制函?數(shù)行為的標(biāo)?志量,其取值的含?義與作用和?msgge?t()及semg?et()函數(shù)的對應(yīng)?參數(shù)都是相?同的,這里不再贅?述。 如果操作成?功,函數(shù)返回共?享內(nèi)存的標(biāo)?識符。 下面的代碼?示范了sh?mger()函數(shù)的使用?: Int open_?shm(key_t? ke

61、yva?l,int segsi?ze) { Int shmid?: If(shmid?=shmge?t(keyva?l,segsi?ze,IPC_C?REAT|0660))==-1) { Retur?n(-1); } Retur?n(shmid?); } 2.shmat?()函數(shù) 當(dāng)一個進(jìn)程?使用shm?get()函數(shù)得到了?共享內(nèi)存的?標(biāo)志符之后?,就可以使用?shmat?()函數(shù)將共享?內(nèi)存映射到?進(jìn)程自己的?內(nèi)存空間內(nèi)?。Shmat?()函數(shù)在li?nux系統(tǒng)?函數(shù)庫li?nux/shm.h中的函數(shù)?聲明如下: 系統(tǒng)調(diào)用:shmat?

62、() 函數(shù)聲明:int shmat? (int shmid?,char *shmad?dr,int shmfl?g); 返回值:addre?ss at which? segme?nt was attac?hed to the proce?ss,or -1 on error?:ereno? =EINVA?L(inval?id IPC ID value? or attac?h addre?ss passe?d)指定的IP?C標(biāo)識符或?內(nèi)存地址非?法 ENODM?EM(Not enoug?h memor?y to attac?h segme?nt)內(nèi)存不足 EACC

63、E?S(permi?ssion? denie?d)權(quán)限不足 第一個參數(shù)?是共享內(nèi)存?的標(biāo)識符。 第二個參數(shù)?shmad?ar指定了?共享內(nèi)存映?射的地址。因?yàn)檫@樣必?須要預(yù)先分?配內(nèi)存,十分不便,所以我們在?使用時(shí)常常?將這個參數(shù)?置零,這樣系統(tǒng)會?自動為映射?分配一塊未?使用的內(nèi)存?。如果指定了?地址,可以給第三?個參數(shù)sh?mflg指?定SHM_?RND標(biāo)志?來強(qiáng)迫將內(nèi)?存大小設(shè)定?為頁面的尺?寸.。 如果指定了?SHM_R?DONLY?參數(shù),共享內(nèi)存將?被映射成只?讀。 映射成功后?,函數(shù)返回指?向映射內(nèi)存?的指針。 下面的這段?代碼演示了?shmat?()函數(shù)的

64、使用?: Char*attac?h_seg?ment(int shmid?) { Retur?n(shmat?(shmid?,0,0)); } 得到了映射?內(nèi)存的指針?之后,我們就可以?像讀寫普通?內(nèi)存一樣對?共享內(nèi)存進(jìn)?行讀寫了。 3.shmct?l()函數(shù) 和前兩個I?PC對象一?樣,共享內(nèi)存也?有一個直接?對其進(jìn)行操?作的函數(shù),就是shm?ctl()函數(shù)。它在Lin?ux系統(tǒng)函?數(shù)庫lin?ux/shm.h中的函數(shù)?聲明是這樣?的: 系統(tǒng)調(diào)用:shmct?l() 函數(shù)聲明:int shmct?l(int shmqi?d,int cmd,struc?t shm

65、id?_ds*buf); 返回值:0 on succe?ss -1 on error?;errno?=EACCE?S(No read permi?ssion? and cmd is IPC_S?TAT進(jìn)行?IPC_S?TAT)操作時(shí)無讀?權(quán) EFAUL?T(Addre?ss point?ed to by buf is inval?id with IPC_S?ETand?IPC_S?TAT comma?nds buf)指定的地址?非法 EIDRM?(segme?nt was remov?ed durin?g retri?eva

66、l)操作過程中?共享內(nèi)存被?刪除 EINVA?L(shmqi?d inval?id shmqi?d)非法 EPERM?(IPC_S?ET or IPC_R?MID comma?nd was issue?d,but calli?ng proce?ss does not have write?(alter?)acces?s to the segme?nt)進(jìn)程無寫全? 這個函數(shù)和?msgge?r()函數(shù)十分相?似,用法也相同?。它支持的操?作有: IPC_S?TAT 獲得共享內(nèi)?存的信息。 IPC_S?ET 設(shè)定共享內(nèi)?存的信息。 IPC_R?MID 刪除共享內(nèi)?存。 需要說明的?是,當(dāng)執(zhí)行IP?C-RMID操?作時(shí),系統(tǒng)并不是?立即將其刪?除,而只是將其?標(biāo)為待刪,然后等待與?其連接的進(jìn)?程斷開連接?。只有當(dāng)所有?的連接都斷?開以后系統(tǒng)?才執(zhí)行真正?的刪除操作?。當(dāng)然,如果執(zhí)行I?PC_RM?ID的時(shí)候?沒有任何連?接,刪除將是立?即執(zhí)行的。 4.shmdt?()函數(shù) 當(dāng)一個進(jìn)程?不再需要某?個共享內(nèi)存?的映射時(shí),就應(yīng)該使用

展開閱讀全文
溫馨提示:
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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

相關(guān)資源

更多
正為您匹配相似的精品文檔
關(guān)于我們 - 網(wǎng)站聲明 - 網(wǎng)站地圖 - 資源地圖 - 友情鏈接 - 網(wǎng)站客服 - 聯(lián)系我們

copyright@ 2023-2025  zhuangpeitu.com 裝配圖網(wǎng)版權(quán)所有   聯(lián)系電話:18123376007

備案號:ICP2024067431-1 川公網(wǎng)安備51140202000466號


本站為文檔C2C交易模式,即用戶上傳的文檔直接被用戶下載,本站只是中間服務(wù)平臺,本站所有文檔下載所得的收益歸上傳人(含作者)所有。裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對上載內(nèi)容本身不做任何修改或編輯。若文檔所含內(nèi)容侵犯了您的版權(quán)或隱私,請立即通知裝配圖網(wǎng),我們立即給予刪除!