共用記憶體(Shared Memory)是最簡單的處理序間通訊方式,它允許多個進程訪問相同的記憶體,一個進程改變其中的資料後,其他的進程都可以看到資料的變化。
共用記憶體是進程間最快速的通訊方式:
`進程共用同一塊記憶體空間。
`訪問共用記憶體和訪問私人記憶體一樣快。
`不需要系統調用和核心入口。
`不造成不必要的記憶體複製。
核心不對共用記憶體的訪問進行同步,因此程式員必須自己提供同步。
使用共用記憶體:
`某個進程分配記憶體段。
`使用這個記憶體段的進程要串連(attach)這個記憶體段。
`每個進程使用完共用記憶體段後,要分離(detach)這個記憶體段。
`在某個地方,必須有一個進程來銷毀這個記憶體段。
Linux的記憶體模型:
`每個進程的虛擬記憶體被分為頁(page)。
`每個進程維護自己的記憶體位址到虛擬記憶體頁之間的映射。
`實際的資料存在於進程的記憶體位址上。
`儘管每個進程有自己的地址空間,多個進程的映射還是可以指向相同的頁。
所有的共用記憶體段的大小,都是Linux記憶體頁大小的整數倍。
Linux的頁大小是4KB,不過程式員應該使用getpagesize函數來獲得這個值。
分配:shmget
`第一個參數是一個整型的鍵,用於指定要建立的段。無關的進程可以通過指定同一個鍵來訪問同一段共用記憶體。
`使用常量IPC_PRIVATE作為第一個參數,可以避免鍵的衝突。
`第二個參數是分配的段的大小(位元組數)。實際分配的位元組數會捨棄多餘部分到頁大小的整數倍。
`第三個參數是位標誌,用來表示建立的選項。
``IPC_CREATE:表明要建立新的共用記憶體空間。
``IPC_EXCL:總是和上一個標誌一起使用。如果指定鍵的共用記憶體段已經存在,這個標誌會導致調用失敗;如果沒有指定這個標誌,調用會返回已經佔用這個鍵的共用記憶體段。
``模式標誌:9個bit的標誌,和系統的檔案許可權使用相同的標誌,不過執行標誌無效。這些標誌定義在<sys/stat.h>中。
`傳回值是新建立的或者取得的記憶體段的標誌符(SHMID)。
串連:shmat
`第一個參數是由shmget得到的標誌符(SHMID)。
`第二個參數是指向你想要映射到的本進程的地址空間的指標。如果指定NULL,Linux負責選擇一個可用的地址。
===================================================
python的共用記憶體
python的multiprocessing模組提供兩種共用記憶體,sharedctypes與Manager,Manager效率較低,但支援遠程共用記憶體。sharedctypes效率較高,快Manager兩個數量級,在多進程訪問時與普通記憶體訪問相當
結果比較如下:test arrayelapsed 0:00:00.119707test dictelapsed 0:00:00.152856test shared manager listelapsed 0:00:37.87666test sharedctypes list in main processelapsed 0:00:00.154170test sharedctypes list in subprocesselapsed 0:00:00.303328elapsed 0:00:00.327261elapsed 0:00:00.349312elapsed 0:00:00.318946elapsed 0:00:00.364301elapsed 0:00:00.370176elapsed 0:00:00.343588elapsed 0:00:00.348737
代碼如下:
import array from datetime import datetime, timedelta
size = 1000000 def tranverse(a): t = datetime.now() for i in range(size): a[i] print 'elapsed %s'% (datetime.now()- t)
a = array.array('i', [i for i in range(size)]) print 'test array' tranverse(a)
a = {} for i in range(size): a[i] = i print 'test dict' tranverse(a)
from multiprocessing import Manager manager = Manager() a = manager.list([i for i in range(size)]) print 'test shared manager list' tranverse(a)
from multiprocessing.sharedctypes import RawArray a = RawArray( 'i', [i for i in range(size)] ) print 'test sharedctypes list in main process' tranverse(a)
from multiprocessing import Process ps = [Process(target=tranverse, args=(a, )) for i in range(8)] print 'test sharedctypes list in subprocess' for p in ps: p.start() for p in ps: p.join()
|
參考:
http://hi.baidu.com/%B1%D8%BC%C7%CE%B4%B6%C1/blog/item/f47e99d5cf0edfc051da4b8b.html
http://blogold.chinaunix.net/u3/108641/showart_2267237.html
http://www.rainsts.net/article.asp?id=1018