進程共享資源包括軟體資源和硬體資源。軟體資源有變數、表格、佇列;硬體資源有物理設備,例如:印表機,輸入設備等。進程共享資源有一個重要內容就是,共享CPU和記憶體。共享CPU採用進程方法實現,共享記憶體採用進程有獨立的記憶體空間,相互之間不能互相訪問。而軟體方面的共享記憶體空間則是共享記憶體,因此共享記憶體是進程共享作業系統空間資源。
概述
主要內容
協作進程需要進程間通信機制(interprocesscommunication,IPC),進程間通信的兩種基本方式:共享記憶體和訊息佇列。
建立的一塊共享記憶體駐留在作業系統的共享記憶體區域,進程在使用共享記憶體時,必須將共享記憶體放到進程的地址空間中,才能向共享記憶體讀寫數據。
#defineBUFFER_SIZE100
itemnextProduced
while(true){
/*produceaniteminnextProduced*/
while((in+1)%BUFFER_SIZE)==out)
;/*donothing*/
buffer[in]=nextProduced;
in=(in+1)%BUFFER_SIZE;
}
itemnextConsumed
while(true){
while(in==out)
;/*donothing*/
nextConsumed=buffer[out];
out=(out+1)%BUFFER_SIZE;
/*consumetheiteminnextConsumed*/
}
#includeshm.h>
segment_id=shmget(IPC_PRIVATE,size,S_IRUSR|S_IWUSR);
返回值:共享記憶體段整數標識符。錯誤,返回-1。
第一個參數指的是共享記憶體段關鍵字(標識符)。第二個參數是size是共享記憶體的大小(單位:位元組)。第三個參數是共享記憶體段的標識模式,明確如何使用共享記憶體段—讀、寫或可讀可寫。
SystemV或Linux系統
#includetypes.h>
#includeshm.h>
intshmget(key_tkey,size_tsize,intshmflg);
第一個參數為key_t類型的key值,由ftok函式產生,它表示一個進程IPC。第三個參數用來標識共享記憶體段的創建標識,包括:
IPC_CREAT:若不存在與key對應的共享記憶體段,就創建。
IPC_EXEL:若與key對應的共享記憶體段已經存在,返回錯誤。
IPC_NOWAIT:不等待直接返回
Linux系統的選項,SHM_R:可讀;SHM_W:可寫。此外,Linux還可以用開打開一個共享記憶體段。
系統調用2.shmat()(SharedMemoryAttach)
shared_memory=(char*)shmat(segment_id,NULL,0)
功能:將共享記憶體加入進程的地址空間。
返回值:共享記憶體段在進程空間的首地址,也稱為實際地址。shared_memory是一個字元指針。當多個進程共享的是計算數組,則它可以是一個結構類型指針,數組作為結構的一個成員。錯誤,返回-1。多個進程使用同一個共享記憶體,在每一個shmat()成功後,shm_nattch計數器值加1。
參數1是共享記憶體標識符,由shmget()函式產生。參數2指定共享記憶體在進程空間中的地址,若為NULL則由作業系統選擇可用地址。參數3是flag,在進程地址空間中的許可權是唯讀還是讀寫方式,應知道flag=0表示非唯讀方式,唯讀方式SHM_RDONLY的值是010000。
一旦共享記憶體段加入到進程地址空間,則進程就可採用從shmat()返回的指針,將共享記憶體作為一般的記憶體訪問。
系統調用3:shmdt()
intshmdt(void*shmaddr)
功能:將共享記憶體從進程地址空間分離。此共享記憶體仍然在作業系統共享記憶體區域,直到用shmctl()特地刪除。
返回值:成功返回0;錯誤,返回-1。shm_nattch計數器值減1。
fork()系統調用對共享記憶體的影響:使用fork創建一個子進程後,該進程繼承EP進程連線的共享記憶體,若調用exit()則進程與所有共享記憶體脫離關係。使用fork()系統調用的程式中,在EP進程中申請和初始化共享記憶體,子進程和EP進程分別連線共享記憶體並且完成不同的任務,然後子進程exit(0),任務結果由EP進程收集或者列印出來,並且。若子進程用exec()則自動卸載所有複製載入的共享記憶體。
源程式:Linux系統
#includeshm.h>
#include
#include
#include
#includeipc.h>
#include
main()
{
key_tkey;
intshm_id;
char*ptr;
key=ftok(“/”,10);
shm_id=shmget(key,100,IPC_CREAT|SHM_R);//唯讀的共享記憶體
printf(“gettheshmidis%d\n”,shm_id);
if((ptr=(char*)shmat(shm_id,NULL,SHM_RDONLY))==NULL)
{//唯讀方式連線
print(“sharedmemoryfail\n”);
exit(-1);
}
printf(“inyanqzdtheattchaddis%p\n”,ptr);//列印實際地址
printf(“now,attempttowritethememory\n”);
*ptr=’d’;
printf(“*ptr=%c\n”,*ptr);
shmdt(ptr);
}
這個程式在編譯時不能通過,編譯器輸出“段錯誤”。原因是程式試圖寫一個唯讀方式創建的共享記憶體段。只需要將程式中的兩個語句修改為:
shm_id=shmget(key,100,IPC_CREAT);//唯讀的共享記憶體
if((ptr=(char*)shmat(shm_id,NULL,0))==NULL)
則程式能得到正確結果:顯示共享記憶體標識符,顯示共享記憶體在進程中的地址,顯示字元d。