亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 1235 | 回復(fù): 0
打印 上一主題 下一主題

UNIX系統(tǒng)共享內(nèi)存的應(yīng)用編程技術(shù) [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2008-01-28 14:51 |只看該作者 |倒序瀏覽

UNIX系統(tǒng)共享內(nèi)存的應(yīng)用編程技術(shù)
中國工商銀行惠安縣支行(362100) 莊文祥

共享內(nèi)存(Shared Memory,下簡稱SHM)是指由一個進程創(chuàng)建并可與其他進程共享的內(nèi)存
塊,在UNIX系統(tǒng)中利用SHM可以實現(xiàn)進程間通信(IPC)。為了對系統(tǒng)共享資源(包括SHM)進行
訪問的互斥控制,就要用到信號量(Semaphore)機制。系統(tǒng)要求進程在存取共享內(nèi)存之前應(yīng)
該先獲得相應(yīng)的信號量的控制。在編程中,共享內(nèi)存常常要與信號量產(chǎn)生相應(yīng)的關(guān)系。
一,共享內(nèi)存的創(chuàng)建與控制
UNIX系統(tǒng)開發(fā)軟件包提供了一系列的函數(shù)來實現(xiàn)共享內(nèi)存的創(chuàng)建與控制。比如調(diào)用sh
mget函數(shù)用于創(chuàng)建共享內(nèi)存;調(diào)用shmctl函數(shù)用于控制共享內(nèi)存。例程如下:
#include
#include
#include
#include
#include
#include
#define SHMKEY Ox1688
#define NODENUM 20
int SHM_id;
struct shmid_ds shm_f;
if((SHM_id=shmget((ket_t)SHMKEY,NODENUM*sizeof(struct pidtos),IPC_CREAT|IPC
_EXCL|0660))有效用戶主標(biāo)識*/
shm_f.shm_perm.gid=110;/*有效用戶組標(biāo)識*/
shm_f.shm_perm.mode=0660;/*操作許可*/
if(shmctl(SHM_id,IPC_SET,&shm_f)函數(shù)shmget的調(diào)用格式如下:
int shmget(key,size,shmflg)
key_t key;/*SHM關(guān)鍵值*/
unsigned int size;/*SHM長度*/
int shmflg;/*標(biāo)志*/
作用是創(chuàng)建共享內(nèi)存或獲取已創(chuàng)建的共享內(nèi)存的標(biāo)識符。實參shmflg的值必須是一個
整數(shù),且規(guī)定下列內(nèi)容:(1)訪問權(quán)限,(2)執(zhí)行方式,(3)控制字段。在創(chuàng)建SHM時,該標(biāo)志可設(shè)
為IPC_CREAT(創(chuàng)建,值是01000)!IPC_EXCL(限制唯一創(chuàng)建,值是02000)!0660(訪問權(quán)限)。成
功時返回創(chuàng)建的共享內(nèi)存標(biāo)識符,失敗時返回-1。實參size的值應(yīng)大于SHMMIN且小于SHMMA
X,否則該系統(tǒng)調(diào)用失敗。當(dāng)shmflg=0時,用于獲取已存在的SHM的標(biāo)識符。
函數(shù)shmctl的調(diào)用格式如下:
int shmctl(shmid,cmd,sbuf)
int shmid;/*由shmget獲取的SHM的標(biāo)識符*/
int cmd;/*將對SHM進行的控制命令*/
struct shmid_ds*sbuf;/*存放操作數(shù)*/
作用是對共享內(nèi)存進行由cmd指定的控制操作。cmd的值比較有用的是下面兩個:
IPC_SET 對于規(guī)定的shmid,設(shè)置有效用戶和組標(biāo)識及操作權(quán)限。
IPC_RMID 連同其相關(guān)的SHM段數(shù)據(jù)結(jié)構(gòu)一起,刪除規(guī)定的shmid。執(zhí)行IPC_SET或IPC_R
MID的進程必須具有Owner/Creator或超級用戶的有效用戶標(biāo)識。
系統(tǒng)創(chuàng)建的SHM僅僅是內(nèi)存中一塊連續(xù)的區(qū)域,本身并沒有結(jié)構(gòu)。用戶進程對共享內(nèi)存
不能直接進行存取,需要將共享內(nèi)存附接在進程的數(shù)據(jù)段上,進程才能對其進行存取,實現(xiàn)方
法是:用戶進程可以根據(jù)需要自行定義一個數(shù)據(jù)結(jié)構(gòu)(如pidtos),然后將共享內(nèi)存的地址用
函數(shù)shmat賦值給指向結(jié)構(gòu)pidtos的指針buf,相當(dāng)于是給指針變量分配內(nèi)存,讓buf指向共享
內(nèi)存的起始處。然后就可用數(shù)組的方法,按數(shù)據(jù)結(jié)構(gòu)的長度等分共享內(nèi)存。這個過程可稱之
為共享內(nèi)存的"結(jié)構(gòu)化"。例程如下:
struct pidtos{
char rhostname[10];
long pidsc;
}*buf;
int
if((buf=(struct pidtos*)shmat(SHM_idm,(char*)0,0))如果有必要,就初始化SHM*/
shmdt((char*)buf);/*拆接SHM,釋放指針buf*/
函數(shù)shmat及shmdt的調(diào)用格式:
char*shmat(shmid,shmaddr,shmflg)
int shmid;/*SHM標(biāo)識符*/
char*shmaddr;/*相當(dāng)于偏移量*/
int shmflg;/*標(biāo)志*/
作用是將共享內(nèi)存附接到進程的數(shù)據(jù)段上。實際上是將共享內(nèi)存在主存中的地址+shm
addr后賦值給進程中的某一指針。shmaddr相當(dāng)于偏移量,相對于共享內(nèi)存在主存中的起始
地址。調(diào)用失敗時返回(char*)-1.shmflg可取值為0,或者是SHM_RND和SHM_EDONLY中的一個
或兩者的或。
int shmdt(shmaddr)
char *shmaddr;/*采用shmat函數(shù)的返回值*/
作用是拆接共享內(nèi)存段,成功時返回0,失敗時返回-1。
二,信號量的創(chuàng)建與控制
為了支持并發(fā)進程對共享內(nèi)存的互斥訪問,保證共享內(nèi)存中數(shù)據(jù)的一致性以及對共享內(nèi)
存操作的完整性(原子性)。一個進程在SHM操作之前先要將SHM加鎖,在操作完成后再將其解
鎖,為此引入了信號量機制。信號量可用來控制一個共享資源,當(dāng)然也包括共享內(nèi)存。由于
許多應(yīng)用需要使用一個以上的信號量,因此UNIX系統(tǒng)中具備有創(chuàng)建信號量組的能力。信號量
組可以含有一個或多個信號量。比如我們可以用一個信號量組中編號為0的信號量來控制一
個資源,再用編號為1的信號量來控制另一資源。當(dāng)我們在編制程序時應(yīng)該知道它們之間的
對應(yīng)關(guān)系。信號量的創(chuàng)建與控制和共享內(nèi)存的創(chuàng)建與控制很相似。如下面的例程:
#define SEMKEY 0x1680
int SEM_id;
struct semid_ds sem_f;
union semun{
int val;
struct semid_ds *buf;
ushort array[1];/*[]中的值應(yīng)根據(jù)信號量數(shù)目具體定義*/
}arg;
if((SEM_id=semget((key_t)SEMKEY,1,IPC_CREAT|IPC_EXCL;0660)信號量的值必須初始化。將編號為0的信號量的值初始化為0*/
arg.buf=&sem_f;
sem_f.sem_perm.uid=220;/*有效用戶主標(biāo)識*/
shm_f.shm_perm.gid=110;/*有效用戶組標(biāo)識*/
shm_f.shm_perm.mode=0660;/*操作許可*/
if(semctl(SEM_id,IPC_SET,arg)上述例程首先設(shè)置一個信號量組的關(guān)鍵值(SEMKEY),然后調(diào)用semgetr利用該關(guān)鍵值創(chuàng)
建只有一個信號量的信號量組。其中第三個參數(shù)的含義與函數(shù)shmget第三個參數(shù)的含義一
樣。
函數(shù)semget的調(diào)用格式:
int semget(key,nsems,semflg)
key_t key;/*信號量組的關(guān)鍵值*/
int nsems;/*信號量個數(shù)*/
int semflg;/*信號量組的創(chuàng)建標(biāo)志*/
用來創(chuàng)建一個信號量組,其中包含nsems個信號量,編號從0至nsems-1;創(chuàng)建方式及訪問
權(quán)限由semflg指定。成功時初始化相應(yīng)的控制塊信息,并返回創(chuàng)建的信號量組的標(biāo)識符,出
錯時返回-1。當(dāng)semflg=0時用于獲取已存在的信號量的標(biāo)識符。
函數(shù)semctl的調(diào)用格式:
int semctl(semid,semnum,cmd,arg)
int semid;/*信號量組的標(biāo)識符*/
int semnum;/*信號量的編號*/
int cmd;/*控制命令*/
union semun{
int val;
struct semid_ds *buf;
ushort array[nsems];/*nsems具體根據(jù)信號量的數(shù)目定義*/
}arg;/*操作數(shù)*/
作用是對指定的信號量組或組中編號為semnum的信號量進行由cmd指定的控制操作。比
較有用的cmd命令如下:
cmd 作用
SETVAL 將信號量(semid,semnm)的當(dāng)前值置為arg.val的值,常用于初始化某個信號量
IPC_SET 將信號量組的狀態(tài)信息設(shè)置成arg.buf中的內(nèi)容
IPC_RMID 刪除信號量組標(biāo)識符semid
對信號量的操作由semop函數(shù)來實現(xiàn)。當(dāng)一個進程存取某一共享內(nèi)存時,先查看相應(yīng)信
號量的值,若為0,則表示SHM目前空閑,未被其他進程占用,那么就將信號量置1,表示SHM已被
占用,然后進程就可存取SHM;若信號量不為0,表明此時SHM已被其他進程占用了,于是這個進
程開始睡眠,等待其他進程釋放SHM,即信號量為0時,才被系統(tǒng)喚醒。如下面的例程:
static struct sembuf sem_lock[2]=(0,0,0,0,1,0);
if(semop(SEM_id,&sem_lock[0],2)加鎖*/其中結(jié)構(gòu)sembuf由系統(tǒng)定義:
struct sembuf{
int sem_num;/*信號量編號*/
int sem_op;/*信號量操作數(shù)*/
int sem_flg;}/*操作標(biāo)志*/
數(shù)組sem_lock[2]可以看作是sem_lock[0]=(0,0,0)及sem_lock[1]=(0,1,0)的組合。
上面的例程實際上是兩步合為一步來做,是對同一個信號量(編號為0)做兩次不同的操作。
經(jīng)過這一步后,實際上可以看作是已經(jīng)將SHM加鎖,進程接下來就可以創(chuàng)建或存取SHM了。如
果其他進程此時想占用SHM,就必須等待。當(dāng)操作完成后,為了其他進程可以存取SHM,就要釋
放資源,將信號量的值重新清零,即一個解鎖的過程。
static struct sembuf sem_unlock[1]=(0,-1,IPC_NOWAIT);
if(semop(SEM_id,&sem_unlock[0],1)解鎖*/
在此之前,信號量的值為1,小于等于-1的絕對值,于是就將信號量減1,重置為0,表示資
源已經(jīng)釋放。如果信號量的當(dāng)前值為0,小于-1的絕對值,因為標(biāo)志設(shè)為IPC_NOWAIT,就會立
即返回,此時因為信號量的值為0,表示資源空閑,也就無所謂解鎖了。
顯然對于共享內(nèi)存的互斥控制采用的是VP算法。該算法還有另一種實現(xiàn)方式:用信號量
為1表示資源空閑,信號量為0表示資源占用,正好與上面的做法相反。在這種情況下,應(yīng)將信
號量的值初始化為1。例程如下:
static struct sembuf sem_lock[1]=(0,-1,0),
sem_unlock[1]=(0,1,0);
semop(SEM_id,&sem_lock[0],1);/*解鎖*/
加鎖時,如果信號量當(dāng)前值為1(資源空閑),那么就減1,這時信號量的值變?yōu)?,表示資源
已經(jīng)被占用。如果信號量當(dāng)前值為0(資源占用),因為0小于-1的絕對值,于是進程開始睡眠
,直到該信號量變?yōu)?時,才被系統(tǒng)喚醒。解鎖時,如果信號量當(dāng)前值為0,那么就加一,這時信
號量的值為1,表示資源空閑。這種方式更加簡單一些。
函數(shù)semop的調(diào)用格式:
int semop(semid,sops,nsops)
int semid;/*信號量組標(biāo)識符*/
struct sembuf**sops;/*指向信號操作量數(shù)緩沖區(qū)*/
unsigned nsops;/*操作的信號量信數(shù)*/
功能是完成對標(biāo)識符為semid的信號量組中若干信號量的操作,根據(jù)sopssem_flg及
操作數(shù)sops.sem_op,對編號為sops·sem_num的信號量進行操作。一共要做nsops次這
樣的操作,這個過程可稱之為信號量的"塊操作",類似批處理方法。
利用上面的三個函數(shù),可以實現(xiàn)對共享資源的互斥訪問,也可設(shè)計出具有復(fù)雜同步操作
要求的并發(fā)程序。不同進程對SHM的互斥訪問可用圖1表示:
@@46P16100.GIF;圖1@@
三,共享內(nèi)存的實際應(yīng)用
我們假設(shè)一個初始化程序(程序init)已經(jīng)完成了SHM及信號量組的創(chuàng)建過程。這時不同
的進程可用相同的關(guān)鍵值(SHMKEY)去存取共享內(nèi)存,互斥訪問也用相同的信號量去控制,關(guān)
鍵值是SEMKEY。我們假設(shè)進程(程序progl)是一個與遠(yuǎn)程主機連接的通信進程,其所要連接
的遠(yuǎn)程主機名由命令行參數(shù)argv[1]指定。進程將遠(yuǎn)程主機名和本身的進程號在SHM中登記
或更新。如:
SEM_id=semget((key_t)SEMKEY,1,0);
semop(SEM_id,&sem_lock[0],2);/*加鎖*/
SHM_id=shmget((key_t)SHMKEY,NODENUM*sizeof(struct pidtos),0);
buf=(struct pidtos*)shmat(SHM_id,(char*)0,0);
for(i=0;i
if(srcmp(buf.rhostname,argv[1]==0) break;
if(buf.pidsc==0) break;
if(i==NODENUM) return(-1);
strcpy(buf.rhostname,argv[1]);
buf.pidsc=getpid();/*操作部分結(jié)束*/
shmdt((char *)buf);/*拆接SHM*/
semop(SEM_id,&sem_unlock[0],1);/*解鎖*/
這樣相同的一批進程帶不同的命令行參數(shù)運行后,就在SHM中登記了一批遠(yuǎn)程主機名和
與之相連的通信進程的進程號。下面我們就可讓進程(程序prog2)依據(jù)遠(yuǎn)程主機名(Remote
Host)在SHM中查出與該主機相連的通信進程的進程號,以實現(xiàn)對這些通信進程的管理。只要
將上面例程中的操作部分換成下面的程序段即可。
for(i=0;i總之,不同進程通過相同的關(guān)鍵值SHMKEY及SEMKEY,來獲取共享內(nèi)存及信號量的標(biāo)識符
,然后使用標(biāo)識符分別對它們進行操作。相同的關(guān)鍵值是實現(xiàn)不同進程共享資源的基礎(chǔ)與前
提。
四,有關(guān)安全性的問題
所謂安全性問題指的是在一個進程將共享內(nèi)存加鎖以后,由于某種原因該進程停止了運
行,沒能執(zhí)行解鎖操作,從而使SHM一直處于被鎖狀態(tài),致使其他進程無法使用SHM。為了盡量
避免出現(xiàn)這種情況,我們可以將一些系統(tǒng)信號忽略掉。具體做法是先定義一些函數(shù)指針,將
原來系統(tǒng)對這些信號的處理功能暫放函數(shù)指針中,然后設(shè)置對這些信號的處理方式為SIG_I
GN(忽略)。如:
int (*f1)();
int (*f2)();
int (*f3)();
int (*f4)();
f1=signal(SIGINT,SIG_IGN);
f2=signal(SIGTERM,SIG_IGN);
f3=signal(SIGQUIT,SIG_IGN);
f4=signal(SIGHUP,SIG_IGN);
在對SHM操作后,無論成功與否都要將對這些系統(tǒng)信號原來的處理功能恢復(fù)過來。如:
signal(SIGINT,f1);
signal(SIGTERM,f2);
signal(SIGQUIT,f3);
signal(SIGHUP,f4);


本文來自ChinaUnix博客,如果查看原文請點:http://blog.chinaunix.net/u/18047/showart_472548.html
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP