進(jìn)程共享資源信號(hào)量控制詳細(xì)實(shí)現(xiàn)源碼及解釋
《進(jìn)程共享資源信號(hào)量控制詳細(xì)實(shí)現(xiàn)源碼及解釋》由會(huì)員分享,可在線閱讀,更多相關(guān)《進(jìn)程共享資源信號(hào)量控制詳細(xì)實(shí)現(xiàn)源碼及解釋(21頁(yè)珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。
1、信號(hào)量 信號(hào)量(Semap?hore)簡(jiǎn)單的說(shuō)就?是用來(lái)控制?多個(gè)進(jìn)程對(duì)?共享資源使?用的計(jì)數(shù)器?。它是常被用?作一種鎖定?保護(hù)機(jī)制,當(dāng)某個(gè)進(jìn)程?對(duì)資源進(jìn)行?操作時(shí)阻止?其他進(jìn)程對(duì)?該資源的訪?問(wèn)。需要注意的?是,Syste?m V中的的信?號(hào)量對(duì)象實(shí)?際上是信號(hào)?量的集合(set),它可以包含?多個(gè)信號(hào)量?,控制多個(gè)共?享資源。 有關(guān)的數(shù)據(jù)?結(jié)構(gòu) 和消息隊(duì)列?一樣,我們?cè)诮榻B?他的使用前?先介紹一些?相關(guān)的數(shù)據(jù)?結(jié)構(gòu): 1. sem 前提提到,信號(hào)量對(duì)象?實(shí)際是多個(gè)?信號(hào)量的集?合。在Linu?x系統(tǒng)中,這種集合是?以數(shù)組的形?式實(shí)現(xiàn)的。數(shù)組的每個(gè)?成員都是一?個(gè)單獨(dú)的信?號(hào)量,它
2、們?cè)谙到y(tǒng)?中是以se?m結(jié)構(gòu)的形?式存儲(chǔ)的。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成員保?存了最近一?次操作信號(hào)?量進(jìn)程的p?id。 Sem_s?emval?成員保存著?信號(hào)量的計(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; }; 前三個(gè)參數(shù)?在對(duì)sen?ctl()函數(shù)介紹中?會(huì)講到,這里暫時(shí)先?不管它們。后兩個(gè)參數(shù)?是Linu?x系統(tǒng)所獨(dú)?有的,只是系統(tǒng)的?內(nèi)核中使用?。 3. semuf? semuf?結(jié)構(gòu)被se?mop()函數(shù)(后面會(huì)講到?)用來(lái)定義對(duì)?信號(hào)量對(duì)象?的基本操作?。它在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、信號(hào)?量在信號(hào)量?數(shù)組中的序?號(hào)(數(shù)組下標(biāo))。 Sem_o?p成員定義?了進(jìn)行的操?作(可以是正,負(fù)和零)。 Sem_f?lg是控制?操作行為的?標(biāo)志。 如果sem?_op是負(fù)?值,就從指定的?信號(hào)量中減?去相應(yīng)的值?。這對(duì)應(yīng)著獲?取信號(hào)量所?監(jiān)控 的資源操作?。如果沒(méi)有s?em_fl?g指定IP?C_NOW?AIT標(biāo)志?,那么,當(dāng)現(xiàn)有的信?號(hào)量數(shù)值小?于sem_?op的絕對(duì)?值(表示現(xiàn)有的?資源少于要?獲取的資源?)時(shí),調(diào)用sem?op()_函數(shù)的進(jìn)?程就會(huì)被阻?塞知道信號(hào)?量的數(shù)值大?于sem_?op的絕對(duì)?值(表示有足夠?的資源被釋?放)。 如果sem?_op是正?值,
8、就在指定的?信號(hào)量中加?上相應(yīng)的值?。這對(duì)應(yīng)著釋?放信號(hào)量所?監(jiān)控 的資源 操作。 如果sem?_op是零?,那么調(diào)用s?emop()函數(shù)的進(jìn)程?就會(huì)被阻塞?到直對(duì)應(yīng)的?信號(hào)量值為?零。 這種操作的?實(shí)質(zhì)就是等?待信號(hào)量所?監(jiān)控的資源?被全部使用?。利用這種資?源操作可以?動(dòng)態(tài)監(jiān)控資?源的使用并?調(diào)整資源的?分配,避免不必要?的等待。 4. Semid?_qs 和msgq?id_ds?類似,semid?_qs結(jié)構(gòu)?被系統(tǒng)用來(lái)?存儲(chǔ)每個(gè)信?號(hào)量對(duì)象的?有關(guān)信息。它在Lin?ux 系統(tǒng)庫(kù)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成員?保存了信號(hào)?量對(duì)象的存?取權(quán)限以及?其他一些信?息(見(jiàn)上面關(guān)于?ipc_p?erm結(jié)構(gòu)?的介紹)。 Sem_o?time成?員保存了最?近一次se?mop()操作的時(shí)間?。 Sem_c?time成?員保存了信?號(hào)量對(duì)象最?近一次改動(dòng)?發(fā)生的時(shí)間?。 Sem_b?ase指針?保存著信號(hào)?量數(shù)組的起?始地址。 Sem_p?en
12、din?g指針保存?著還沒(méi)有進(jìn)?行的操作。 Sem_p?endin?g_las?t指針保存?著最后一個(gè)?還沒(méi)有進(jìn)行?的操作。 Sem_u?ndo成員?保存了un?do請(qǐng)求的?數(shù)目。 Sem_n?sems成?員保存了信?號(hào)量數(shù)組的?成員數(shù)目。 4.8.2有關(guān)的函?數(shù) 介紹完有關(guān)?的數(shù)據(jù)結(jié)構(gòu)?,接下來(lái)我們?將介紹使用?信號(hào)量要用?到的函數(shù): 1.semge?t() 使用sem?ger()函數(shù)來(lái)建立?新的信號(hào)量?對(duì)象或者獲?取已有的對(duì)?象的標(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))信號(hào)量已存?在,無(wú)法創(chuàng)建 EIDRM?(set is marke?d for delet?ion)信號(hào)量待刪?
14、 ENOEN?T(set does nor exisr?,no IPC_C?REAT was usrd)信號(hào)量不存?在,無(wú)法打開(kāi) ENOME?M(Not enoug?h memor?y to creat?e new set)無(wú)足夠內(nèi)存?以創(chuàng)建新信?號(hào)量 ENOSP?C(Maxim?un set limit? excee?ded)信號(hào)量個(gè)數(shù)?已滿 函數(shù)接受三?個(gè)參數(shù)。其中第一個(gè)?參數(shù)key?和第三個(gè)參?數(shù)semf?lg和前面?講過(guò)的ms?gget()函數(shù)中的兩?個(gè)參數(shù)對(duì)應(yīng)?的,作用和取值
15、?的意義也相?同,讀者可以參?看msgg?et()的有關(guān)介紹?。函數(shù)的第二?個(gè)參數(shù)ns?ems是信?號(hào)量對(duì)象所?特有的。它指定了新?生成的信號(hào)?量對(duì)象中信?號(hào)量的數(shù)目?,也就是信號(hào)?量數(shù)組成員?的個(gè)數(shù)。在linu?x/sem.h定義了它?的上限: #defin?e SEMMS?L 32 /*<=512 max num of semap?hores? per id */ 如果函數(shù)執(zhí)?行的是打開(kāi)?而不是創(chuàng)建?操作,則這個(gè)參數(shù)?被忽略。 下面我們創(chuàng)?建一個(gè)封裝?函數(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) } 程序的分析?請(qǐng)讀者自行?完成。 2.semop?() 使用這個(gè)函?數(shù)來(lái)改變信?號(hào)量對(duì)象中?各個(gè)信號(hào)量?的狀態(tài)。它在Lin?ux系統(tǒng)庫(kù)?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)信號(hào)量已被?刪除 EINTR?(Signa?l recei?ved while? sleep?ing)阻塞被信號(hào)?中止 EINVA?L(set doesn?’t exist?,or semid? is i
19、nval?id)信號(hào)量不存?在或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)存不足,無(wú)法進(jìn)行u?ndo操作?(指定SEM?_UNDO?時(shí)) ERANG?E(semap?hore value? out of range?)信號(hào)量的值?越界 函數(shù)的第一?個(gè)參數(shù)se?mid是要?操作的信號(hào)?量對(duì)象的標(biāo)?示符。第二個(gè)參數(shù)?sops是?sembu?f的數(shù)組,它定義了s?emop()函數(shù)所要進(jìn)?行的操作序?列。第三
20、個(gè)參數(shù)?nsops?保存數(shù)組的?長(zhǎng)度,也即sem?op()函數(shù)將進(jìn)行?的操作個(gè)數(shù)?。 在前面對(duì)s?embuf?結(jié)構(gòu)的介紹?中已經(jīng)介紹?了semo?p()的各種基本?操作。下面我們將?結(jié)合例子對(duì)?這些操作作?進(jìn)一步的介?紹。首先假設(shè)已?經(jīng)通過(guò)se?mget()函數(shù)得到了?一個(gè)只包含?一個(gè)信號(hào)量?的信號(hào)量對(duì)?象,它在監(jiān)控著?某臺(tái)最多能?處理10分?作業(yè)的打印?機(jī)的使用。我們下面的?操作都將是?只針對(duì)這個(gè)?信號(hào)量的。 假設(shè)要向打?印機(jī)交付一?份作業(yè)??梢远x下?面的sem?buf變量?來(lái)完成這個(gè)?操作: Struc?t sembu?f sem_g?et={0,-1,IPC_N?OWAIT?};
21、 它告訴系統(tǒng)?,將信號(hào)量對(duì)?象中序號(hào)為?零的信號(hào)量?(第一個(gè)信號(hào)?量)減一。IPC_N?OWAIT?標(biāo)志的定義?告訴系統(tǒng),如果打印機(jī)?的作業(yè)量(10份)已滿,則不阻塞進(jìn)?程而是直接?將控制權(quán)返?回進(jìn)程并返?回失敗信息?。 定義完操作?后,我們使用下?面的代碼來(lái)?執(zhí)行它: If(semop?(sid,&sem_g?et,1)==-1) Perro?r(“semop?”); 作業(yè)打印完?成后,我們使用下?面的sem?buf變量?來(lái)定義一個(gè)?釋放資源的?操作: Struc?t sembu?f sem_r?eleas?e={0,1,IPC_N?OWAIT?}; 它告訴系統(tǒng)?將信
22、號(hào)量對(duì)?象中序號(hào)為?零的對(duì)象加?一。 然后用下面?的代碼來(lái)完?成這個(gè)操作?: Semop?(sid,&sem_r?eleas?e,1); 這樣,我們就完成?了一個(gè)完整?的作業(yè)打印?操作。 3.semct?l()函數(shù) 和消息隊(duì)列?的msgc?tl()函數(shù)類似,semct?l()函數(shù)被用來(lái)?直接對(duì)信號(hào)?量對(duì)象進(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)信號(hào)量已被?刪除 EINVA?L(set doesn?’t exist?,or semid? is inval?id)信號(hào)量不存?在或sem?id非法 EPERM?(EUD hasno? privi?leges? for
24、 cmd in arg)無(wú)權(quán)進(jìn)行指?定的操作 ENANG?E(semap?hore value? out of range?)信號(hào)量的值?超界 比較一下這?兩個(gè)函數(shù)的?參數(shù)我們會(huì)?發(fā)現(xiàn)一些細(xì)?微的差別。首先,因?yàn)樾盘?hào)量?對(duì)象事實(shí)上?是多個(gè)信息?量的集合而?非單一的個(gè)?體,所以在進(jìn)行?操作時(shí),不僅需要指?定對(duì)象的標(biāo)?示符。還需要用信?號(hào)量在集合?中的序號(hào)來(lái)?指定具體的?信號(hào)量個(gè)體?。 兩個(gè)函數(shù)都?有cmd參?數(shù),指定了函數(shù)?進(jìn)行的具體?操作。不過(guò),和msgc?tl()函數(shù)相比,semct?l()函數(shù)可以盡?心的操作要?多得多: IPC_S?TAT取得?信
25、號(hào)量對(duì)象?的semi?d_ds結(jié)?構(gòu)信息,并將其存儲(chǔ)?在arg參?數(shù)中buf?指針?biāo)竷?nèi)?存中返回。 IPC_S?ET用ar?g參數(shù)中b?uf的數(shù)據(jù)?來(lái)設(shè)定信號(hào)?量對(duì)象的s?emid-ds結(jié)構(gòu)信?息。和消息隊(duì)列?對(duì)象一樣,能被這個(gè)函?數(shù)設(shè)定的只?有少數(shù)幾個(gè)?參數(shù)。 IPC_R?MID從內(nèi)?存中刪除信?號(hào)量對(duì)象。 GETAL?L取得信號(hào)?量對(duì)象中所?有信號(hào)量的?值,并存儲(chǔ)在a?rg參數(shù)中?的arra?y數(shù)組中返?回。 GETNC?NT返回正?在等待使用?某個(gè)信號(hào)量?所控制的資?源進(jìn)程數(shù)目?。 GETPI?D返回最近?一個(gè)對(duì)某個(gè)?信號(hào)量調(diào)用?semop?()函數(shù)的進(jìn)程?的pid. GE
26、YVA?L返回信號(hào)?量的計(jì)數(shù)值?。 GETZC?NT 返回正在等?待某個(gè)信號(hào)?量所控制資?源全部使用?的進(jìn)程數(shù)目?。 SETAL?L用arg?參數(shù)中ar?ray數(shù)組?的值來(lái)設(shè)定?對(duì)象內(nèi)某個(gè)?信號(hào)量的值?。 函數(shù)的第四?個(gè)參數(shù)ar?g提供了操?作所需要的?其他信息。它的各個(gè)成?員的意義在?前面已經(jīng)有?個(gè)介紹,這里不再贅?述。需要強(qiáng)調(diào)的?是它和ms?gctl()中的參數(shù)不?一樣,是一個(gè)普通?的變量而不?是指針,初學(xué)者常常?在這個(gè)問(wèn)題?上犯錯(cuò)誤。 下面舉幾個(gè)?使用sem?ctl()的例子。 Int get_s?em_va?l(Int sid,int semnu?m) {
27、 retur?n(semct?l(sid,semnu?m,GETVA?L,0)); } 上面的代碼?返回到信號(hào)?量對(duì)象中某?個(gè)信號(hào)來(lái)那?個(gè)的值。注意這里s?emctl?()函數(shù)的最后?一個(gè)參數(shù)取?的是零,這是因?yàn)閳?zhí)?行GETV?AL命令時(shí)?這個(gè)參數(shù)被?自動(dòng)忽略了?。 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ù)?來(lái)設(shè)定信號(hào)?量對(duì)象某個(gè)?信號(hào)量的值?。 最后用一個(gè)?例子來(lái)強(qiáng)調(diào)?一個(gè)極易被?忽視的錯(cuò)誤?。 在消息隊(duì)列?和信號(hào)量對(duì)?象中,都有IPC?_STAT?和IPC_?SET的操?作。但是由于傳?遞參數(shù)的類?型不同,造成了它們?在使用上的?差別。在msgc?tl()函數(shù)中,IPC_S?TAL 操作只是簡(jiǎn)?單的將內(nèi)核?中msfq?id_ds?結(jié)構(gòu)的地址?賦予buf?參數(shù)(是一個(gè)指針?)。而在sem?ctl()函數(shù)中,IPC_S?TAT操作?是將sem?id_ds?的內(nèi)容拷貝?到arg參?數(shù)的buf?成員指針?biāo)?指的內(nèi)存中?,所以,下面
29、的代碼?會(huì)產(chǎn)生錯(cuò)誤?,而msgc?tl()函數(shù)的類似?代碼卻不會(huì)?: Void getmo?de(int sid) { Int rc; Union? semun? semop?s; /*下面的語(yǔ)句?會(huì)產(chǎn)生錯(cuò)誤?*/ 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í)沒(méi)?有給buf?指針?lè)峙鋬?nèi)?存,其指向是不?確定的。這種“不定向”的指針式c?程序中最危?險(xiǎn)的陷阱之?一。改正這個(gè)錯(cuò)?誤,只需要前提?給buf指?針準(zhǔn)備一塊?內(nèi)存。下面是修改?過(guò)的代碼: 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信號(hào)量的?實(shí)例 1.背景知識(shí) Semto?ol工具通?過(guò)命
32、令行參?數(shù)來(lái)決定它?的行為,這樣它可以?決定它的行?為,這樣他可以?被方便的應(yīng)?用于she?ll腳本中?。Semto?ol提供了?和信號(hào)量有?關(guān)的全部功?能,包括創(chuàng)建信?號(hào)量、操作、刪除信號(hào)量?對(duì)象以及更?改信號(hào)量權(quán)?限等。使用它,我們可以在?命令行上控?制資源的共?享。 2.semto?ol的命令?行語(yǔ)法 建立信號(hào)量?對(duì)象: semto?ol c (numbe?r of semap?hores? in set) 鎖定信號(hào)量?: semto?ol l(semap?hore numbe?r to lock) 解鎖信號(hào)量?的鎖定: semto?ol u (semap?
33、hore numbe?r to unloc?k)
改變信號(hào)量?的權(quán)限: semto?ol m (mode)
刪除信號(hào)量?對(duì)象: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!(打開(kāi)信號(hào)量?對(duì)象(而不是創(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)初始化對(duì)象?內(nèi)所有信號(hào)?量(該操作也可?以用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 嘗試鎖定信?號(hào)量*/ 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嘗試?鎖定信號(hào)量?*/
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?判斷信號(hào)量?是否被鎖*/ 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(返回對(duì)象內(nèi)?的信號(hào)量個(gè)?數(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(獲取對(duì)象當(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(讀取信號(hào)量?對(duì)象的權(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 和前面介紹?的兩個(gè)IP?C對(duì)象一樣?,共享內(nèi)存也?有一個(gè)給系?統(tǒng)內(nèi)存用來(lá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)存對(duì)象的?存取權(quán)限及?其他一些信?息。 Shm_s?egze成?員定義了共?享內(nèi)存大
57、小?(以字節(jié)胃單?位) Shm_a?time成?員保存了最?近一次進(jìn)程?連接共享內(nèi)?存的時(shí)間。 Shm_d?time成?員保存了最?近一次進(jìn)程?斷開(kāi)與共享?內(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ù)目。 剩下的三個(gè)?成員被內(nèi)核?保留使用,這里就不介?紹了。 4.9.2有關(guān)的函?數(shù) 接下來(lái)我們?介紹和共享?內(nèi)存有關(guān)的?函數(shù)
58、: 1.Sys_s?hmgrt?()函數(shù) 使用shm?get()函數(shù)來(lái)創(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)存?已存在,無(wú)法創(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)存不?存在,無(wú)法打開(kāi)) EACCE?S(Permi?ssion? denie?d權(quán)限不足?) ENOME?M(
60、Not enoug?h memor?y to creat?e segme?nt 內(nèi)存不足,無(wú)法創(chuàng)建共?享內(nèi)存) 和前面兩個(gè)?IPC對(duì)象?函數(shù)一樣,shmge?t()函數(shù)的第一?個(gè)參數(shù)ke?y是共享內(nèi)?存的關(guān)鍵字?;第二個(gè)參數(shù)?size是?創(chuàng)建的共享?內(nèi)存的大小?,以字節(jié)為單?位。第三個(gè)參數(shù)?shmfl?g是控制函?數(shù)行為的標(biāo)?志量,其取值的含?義與作用和?msgge?t()及semg?et()函數(shù)的對(duì)應(yīng)?參數(shù)都是相?同的,這里不再贅?述。 如果操作成?功,函數(shù)返回共?享內(nèi)存的標(biāo)?識(shí)符。 下面的代碼?示范了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)一個(gè)進(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ù)庫(kù)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)識(shí)符或?內(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)限不足 第一個(gè)參數(shù)?是共享內(nèi)存?的標(biāo)識(shí)符。 第二個(gè)參數(shù)?shmad?ar指定了?共享內(nèi)存映?射的地址。因?yàn)檫@樣必?須要預(yù)先分?配內(nèi)存,十分不便,所以我們?cè)?使用時(shí)常常?將這個(gè)參數(shù)?置零,這樣系統(tǒng)會(huì)?自動(dòng)為映射?分配一塊未?使用的內(nèi)存?。如果指定了?地址,可以給第三?個(gè)參數(shù)sh?mflg指?定SHM_?RND標(biāo)志?來(lái)強(qiáng)迫將內(nèi)?存大小設(shè)定?為頁(yè)面的尺?寸.。 如果指定了?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)存一樣對(duì)?共享內(nèi)存進(jìn)?行讀寫了。 3.shmct?l()函數(shù) 和前兩個(gè)I?PC對(duì)象一?樣,共享內(nèi)存也?有一個(gè)直接?對(duì)其進(jìn)行操?作的函數(shù),就是shm?ctl()函數(shù)。它在Lin?ux系統(tǒng)函?數(shù)庫(kù)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í)無(wú)讀?權(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)操作過(guò)程中?共享內(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)程無(wú)寫全? 這個(gè)函數(shù)和?msgge?r()函數(shù)十分相?似,用法也相同?。它支持的操?作有: IPC_S?TAT 獲得共享內(nèi)?存的信息。 IPC_S?ET 設(shè)定共享內(nèi)?存的信息。 IPC_R?MID 刪除共享內(nèi)?存。 需要說(shuō)明的?是,當(dāng)執(zhí)行IP?C-RMID操?作時(shí),系統(tǒng)并不是?立即將其刪?除,而只是將其?標(biāo)為待刪,然后等待與?其連接的進(jìn)?程斷開(kāi)連接?。只有當(dāng)所有?的連接都斷?開(kāi)以后系統(tǒng)?才執(zhí)行真正?的刪除操作?。當(dāng)然,如果執(zhí)行I?PC_RM?ID的時(shí)候?沒(méi)有任何連?接,刪除將是立?即執(zhí)行的。 4.shmdt?()函數(shù) 當(dāng)一個(gè)進(jìn)程?不再需要某?個(gè)共享內(nèi)存?的映射時(shí),就應(yīng)該使用
- 溫馨提示:
1: 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年銀行業(yè)年終工作總結(jié)8篇
- 電工年度工作總結(jié)11篇
- 鄉(xiāng)鎮(zhèn)衛(wèi)生院護(hù)士述職報(bào)告6篇
- 中專期末總結(jié)個(gè)人總結(jié)7篇
- 醫(yī)技科個(gè)人總結(jié)范文6篇
- 展望未來(lái)年終總結(jié)8篇
- 品質(zhì)年度工作總結(jié)報(bào)告4篇
- 市場(chǎng)月總結(jié)5篇
- 年終個(gè)人工作總結(jié)
- 檔案管理工作的自查報(bào)告8篇
- 護(hù)士近五年工作總結(jié)6篇
- 部門助理個(gè)人總結(jié)7篇
- 專項(xiàng)資金使用自查報(bào)告5篇
- 教師教研教學(xué)工作總結(jié)7篇
- 迎新晚會(huì)個(gè)人總結(jié)10篇