概述
進程共享資源包括軟體資源和硬體資源。軟體資源有變數、表格、佇列;硬體資源有物理設備,例如:印表機,輸入設備等。進程共享資源有一個重要內容就是,共享CPU和記憶體。共享CPU採用進程方法實現,共享記憶體採用進程有獨立的記憶體空間,相互之間不能互相訪問。而軟體方面的共享記憶體空間則是共享記憶體,因此共享記憶體是進程共享作業系統空間資源。
主要內容
進程共享作業系統空間的目的是傳遞數據,或者進程通信。作業系統專門劃出一個區域作為共享記憶體區域。而要使用這個共享記憶體的進程,必須將這個區域連線到記憶體圖像中。而進程的訊息佇列也是在作業系統的核心空間中,但是屬於某一個進程,所以共享的色彩並不濃厚。
此外,從另一個觀念看,進程之間傳遞數據,因為進程的數據段相互獨立,所以不能通過地址訪問另一個進程的數據,只有採用共享“軟體資源”的方法處理數據。這裡顯然把共享記憶體看作共享軟體資源。進程通信的方法有:共享記憶體,訊息佇列和已分享檔案三種主要方式。此外,共享數據結構的方法,例如生產者-消費者問題的有界緩衝區;還有信箱作為中間實體的間接通信方式,也是進程通信的方法,請看參考書。
協作進程需要進程間通信機制(interprocesscommunication,IPC),進程間通信的兩種基本方式:共享記憶體和訊息佇列。
1.概念
在提供這種通信方式的系統中,作業系統在存儲器中劃出了一塊共享存儲區,多個進程間可通過對共享存儲區中的數據進行讀寫來實現通信。共享記憶體允許以最快的速度進行便捷的進程通信,僅在建立共享記憶體區域時需要系統調用,以後,所有共享記憶體訪問都處理為常規記憶體訪問。
建立的一塊共享記憶體駐留在作業系統的共享記憶體區域,進程在使用共享記憶體時,必須將共享記憶體放到進程的地址空間中,才能向共享記憶體讀寫數據。
2.共享記憶體解決生產者-消費者問題
循環緩衝池。在TCP/IP協定中,循環緩衝區的問題用滑動視窗協定解決,因此不必取余。
#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*/
}
3.共享記憶體實例
系統調用1.POSIX系統shmget()創建共享記憶體
#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。
分類
包括全程變數,訊息佇列,設備佇列,作業系統資源,例如:作業系統數據結構,text[],proc[]等。
硬體資源
進程共享硬體資源是進程互斥的範圍,作業系統的管理方法是哲學家進餐方法。
作業系統為管理進程共享資源的問題,為每一個硬體設備建立等待佇列,等待的進程送到佇列中。對有多個數量的硬體設備,根據設備無關性,進程可分配到需要的資源。對獨享設備,作業系統則用虛擬管理方法,用spooling系統建立設備緩衝區的方法,使獨享設備變成共享。
湯子瀛.計算機作業系統.西安電子科技大學.
楊宗德.Linux高級程式設計.人民郵電出版社