進程共享資源信號量控制詳細實現(xiàn)源碼及解釋
《進程共享資源信號量控制詳細實現(xiàn)源碼及解釋》由會員分享,可在線閱讀,更多相關(guān)《進程共享資源信號量控制詳細實現(xiàn)源碼及解釋(21頁珍藏版)》請在裝配圖網(wǎng)上搜索。
1、信號量 信號量(Semap?hore)簡單的說就?是用來控制?多個進程對?共享資源使?用的計數(shù)器?。它是常被用?作一種鎖定?保護機制,當某個進程?對資源進行?操作時阻止?其他進程對?該資源的訪?問。需要注意的?是,Syste?m V中的的信?號量對象實?際上是信號?量的集合(set),它可以包含?多個信號量?,控制多個共?享資源。 有關(guān)的數(shù)據(jù)?結(jié)構(gòu) 和消息隊列?一樣,我們在介紹?他的使用前?先介紹一些?相關(guān)的數(shù)據(jù)?結(jié)構(gòu): 1. sem 前提提到,信號量對象?實際是多個?信號量的集?合。在Linu?x系統(tǒng)中,這種集合是?以數(shù)組的形?式實現(xiàn)的。數(shù)組的每個?成員都是一?個單獨的信?號量,它
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成員保?存了最近一?次操作信號?量進程的p?id。 Sem_s?emval?成員保存著?信號量的計?數(shù)值。 Sem_s?emncn?t成員保存?著等待使用?資源的進程?數(shù)目。 Sem_s?emzcn?t成員保存?等待資源完?全空閑的進?程數(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ù)?是Linu?x系統(tǒng)所獨?有的,只是系統(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ù)組下標)。 Sem_o?p成員定義?了進行的操?作(可以是正,負和零)。 Sem_f?lg是控制?操作行為的?標志。 如果sem?_op是負?值,就從指定的?信號量中減?去相應(yīng)的值?。這對應(yīng)著獲?取信號量所?監(jiān)控 的資源操作?。如果沒有s?em_fl?g指定IP?C_NOW?AIT標志?,那么,當現(xiàn)有的信?號量數(shù)值小?于sem_?op的絕對?值(表示現(xiàn)有的?資源少于要?獲取的資源?)時,調(diào)用sem?op()_函數(shù)的進?程就會被阻?塞知道信號?量的數(shù)值大?于sem_?op的絕對?值(表示有足夠?的資源被釋?放)。 如果sem?_op是正?值,
8、就在指定的?信號量中加?上相應(yīng)的值?。這對應(yīng)著釋?放信號量所?監(jiān)控 的資源 操作。 如果sem?_op是零?,那么調(diào)用s?emop()函數(shù)的進程?就會被阻塞?到直對應(yīng)的?信號量值為?零。 這種操作的?實質(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()操作的時間?。 Sem_c?time成?員保存了信?號量對象最?近一次改動?發(fā)生的時間?。 Sem_b?ase指針?保存著信號?量數(shù)組的起?始地址。 Sem_p?en
12、din?g指針保存?著還沒有進?行的操作。 Sem_p?endin?g_las?t指針保存?著最后一個?還沒有進行?的操作。 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ù)來建立?新的信號量?對象或者獲?取已有的對?象的標示符?。它在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)允許一?次進行的操?作數(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)操作不能進?行(IPC_N?OWALT?標志是使用?) 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)存不足,無法進行u?ndo操作?(指定SEM?_UNDO?時) ERANG?E(semap?hore value? out of range?)信號量的值?越界 函數(shù)的第一?個參數(shù)se?mid是要?操作的信號?量對象的標?示符。第二個參數(shù)?sops是?sembu?f的數(shù)組,它定義了s?emop()函數(shù)所要進?行的操作序?列。第三
20、個參數(shù)?nsops?保存數(shù)組的?長度,也即sem?op()函數(shù)將進行?的操作個數(shù)?。 在前面對s?embuf?結(jié)構(gòu)的介紹?中已經(jīng)介紹?了semo?p()的各種基本?操作。下面我們將?結(jié)合例子對?這些操作作?進一步的介?紹。首先假設(shè)已?經(jīng)通過se?mget()函數(shù)得到了?一個只包含?一個信號量?的信號量對?象,它在監(jiān)控著?某臺最多能?處理10分?作業(yè)的打印?機的使用。我們下面的?操作都將是?只針對這個?信號量的。 假設(shè)要向打?印機交付一?份作業(yè)??梢远x下?面的sem?buf變量?來完成這個?操作: Struc?t sembu?f sem_g?et={0,-1,IPC_N?OWAIT?};
21、 它告訴系統(tǒng)?,將信號量對?象中序號為?零的信號量?(第一個信號?量)減一。IPC_N?OWAIT?標志的定義?告訴系統(tǒng),如果打印機?的作業(yè)量(10份)已滿,則不阻塞進?程而是直接?將控制權(quá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ù) 和消息隊列?的msgc?tl()函數(shù)類似,semct?l()函數(shù)被用來?直接對信號?量對象進行?控制。它在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)進行指?定的操作 ENANG?E(semap?hore value? out of range?)信號量的值?超界 比較一下這?兩個函數(shù)的?參數(shù)我們會?發(fā)現(xiàn)一些細?微的差別。首先,因為信號量?對象事實上?是多個信息?量的集合而?非單一的個?體,所以在進行?操作時,不僅需要指?定對象的標?示符。還需要用信?號量在集合?中的序號來?指定具體的?信號量個體?。 兩個函數(shù)都?有cmd參?數(shù),指定了函數(shù)?進行的具體?操作。不過,和msgc?tl()函數(shù)相比,semct?l()函數(shù)可以盡?心的操作要?多得多: IPC_S?TAT取得?信
25、號量對象?的semi?d_ds結(jié)?構(gòu)信息,并將其存儲?在arg參?數(shù)中buf?指針所指內(nèi)?存中返回。 IPC_S?ET用ar?g參數(shù)中b?uf的數(shù)據(jù)?來設(shè)定信號?量對象的s?emid-ds結(jié)構(gòu)信?息。和消息隊列?對象一樣,能被這個函?數(shù)設(shè)定的只?有少數(shù)幾個?參數(shù)。 IPC_R?MID從內(nèi)?存中刪除信?號量對象。 GETAL?L取得信號?量對象中所?有信號量的?值,并存儲在a?rg參數(shù)中?的arra?y數(shù)組中返?回。 GETNC?NT返回正?在等待使用?某個信號量?所控制的資?源進程數(shù)目?。 GETPI?D返回最近?一個對某個?信號量調(diào)用?semop?()函數(shù)的進程?的pid. GE
26、YVA?L返回信號?量的計數(shù)值?。 GETZC?NT 返回正在等?待某個信號?量所控制資?源全部使用?的進程數(shù)目?。 SETAL?L用arg?參數(shù)中ar?ray數(shù)組?的值來設(shè)定?對象內(nèi)某個?信號量的值?。 函數(shù)的第四?個參數(shù)ar?g提供了操?作所需要的?其他信息。它的各個成?員的意義在?前面已經(jīng)有?個介紹,這里不再贅?述。需要強調(diào)的?是它和ms?gctl()中的參數(shù)不?一樣,是一個普通?的變量而不?是指針,初學者常常?在這個問題?上犯錯誤。 下面舉幾個?使用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ù)取?的是零,這是因為執(zhí)?行GETV?AL命令時?這個參數(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è)定信號?量對象某個?信號量的值?。 最后用一個?例子來強調(diào)?一個極易被?忽視的錯誤?。 在消息隊列?和信號量對?象中,都有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?成員指針所?指的內(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)實沒?有給buf?指針分配內(nèi)?存,其指向是不?確定的。這種“不定向”的指針式c?程序中最危?險的陷阱之?一。改正這個錯?誤,只需要前提?給buf指?針準備一塊?內(nèi)存。下面是修改?過的代碼: Void getmo?de(int sid) { Int rc; Union? semun? sempo?ts; Struc?t semid?_ds mysem?ds; /*給buf指?針準備一塊?內(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信號量的?實例 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
34、clu?de
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
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(獲取對象當?前的狀態(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?
53、” (u)nlock?
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成?員保存了最?近一次進程?連接共享內(nèi)?存的時間。 Shm_d?time成?員保存了最?近一次進程?斷開與共享?內(nèi)容的連接?時間。 Shm_c?time成?員保存了最?近一次sh?mid_d?s結(jié)構(gòu)內(nèi)容?改變的時間? Shm_c?pid成員?保存了創(chuàng)建?共享內(nèi)容的?進程pid? Shm_l?pid成員?保存了最近?一次連接共?享內(nèi)存的進?程pid. Shm_n?attch?成員保存了?與共享內(nèi)存?連接的進程?數(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ù)行為的標?志量,其取值的含?義與作用和?msgge?t()及semg?et()函數(shù)的對應(yīng)?參數(shù)都是相?同的,這里不再贅?述。 如果操作成?功,函數(shù)返回共?享內(nèi)存的標?識符。 下面的代碼?示范了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ù) 當一個進程?使用shm?get()函數(shù)得到了?共享內(nèi)存的?標志符之后?,就可以使用?shmat?()函數(shù)將共享?內(nèi)存映射到?進程自己的?內(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標識符或?內(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)存?的標識符。 第二個參數(shù)?shmad?ar指定了?共享內(nèi)存映?射的地址。因為這樣必?須要預先分?配內(nèi)存,十分不便,所以我們在?使用時常常?將這個參數(shù)?置零,這樣系統(tǒng)會?自動為映射?分配一塊未?使用的內(nèi)存?。如果指定了?地址,可以給第三?個參數(shù)sh?mflg指?定SHM_?RND標志?來強迫將內(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)存進?行讀寫了。 3.shmct?l()函數(shù) 和前兩個I?PC對象一?樣,共享內(nèi)存也?有一個直接?對其進行操?作的函數(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進行?IPC_S?TAT)操作時無讀?權(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)進程無寫全? 這個函數(shù)和?msgge?r()函數(shù)十分相?似,用法也相同?。它支持的操?作有: IPC_S?TAT 獲得共享內(nèi)?存的信息。 IPC_S?ET 設(shè)定共享內(nèi)?存的信息。 IPC_R?MID 刪除共享內(nèi)?存。 需要說明的?是,當執(zhí)行IP?C-RMID操?作時,系統(tǒng)并不是?立即將其刪?除,而只是將其?標為待刪,然后等待與?其連接的進?程斷開連接?。只有當所有?的連接都斷?開以后系統(tǒng)?才執(zhí)行真正?的刪除操作?。當然,如果執(zhí)行I?PC_RM?ID的時候?沒有任何連?接,刪除將是立?即執(zhí)行的。 4.shmdt?()函數(shù) 當一個進程?不再需要某?個共享內(nèi)存?的映射時,就應(yīng)該使用
- 溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 6.煤礦安全生產(chǎn)科普知識競賽題含答案
- 2.煤礦爆破工技能鑒定試題含答案
- 3.爆破工培訓考試試題含答案
- 2.煤礦安全監(jiān)察人員模擬考試題庫試卷含答案
- 3.金屬非金屬礦山安全管理人員(地下礦山)安全生產(chǎn)模擬考試題庫試卷含答案
- 4.煤礦特種作業(yè)人員井下電鉗工模擬考試題庫試卷含答案
- 1 煤礦安全生產(chǎn)及管理知識測試題庫及答案
- 2 各種煤礦安全考試試題含答案
- 1 煤礦安全檢查考試題
- 1 井下放炮員練習題含答案
- 2煤礦安全監(jiān)測工種技術(shù)比武題庫含解析
- 1 礦山應(yīng)急救援安全知識競賽試題
- 1 礦井泵工考試練習題含答案
- 2煤礦爆破工考試復習題含答案
- 1 各種煤礦安全考試試題含答案