2012-11-21 29 views
1

我有一個從幾個服務器的進程通過udp每秒發送數據到我的本地端口2222。如何從流中寫入python中的共享內存?

我想讀取這些數據並將其寫入共享內存,以便可以有其他進程從共享內存中讀取數據並對其執行操作。

我一直在閱讀約mmap,似乎我不得不使用一個文件...我似乎無法理解爲什麼。

我有一個a.py從套接字讀取數據,但我怎樣才能將它寫入shm?

一旦寫完了,我需要編寫b.py,c.py,d.py等,來讀取相同的shm並對它進行操作。

任何幫助或代碼片段將大大幫助。

+4

如果數據共享只是在Python進程之間進行,那麼使用['multprocessing'](http://docs.python.org/2/library/multiprocessing.html)模塊可能是有意義的。它有幾個同步的數據結構供您選擇。 – Blckknght

回答

0

首先,請注意,您正在嘗試構建的內容不僅僅需要共享內存:如果a.py寫入共享內存,它會很好,但b.py如何知道內存何時準備就緒並可以從中讀取?總而言之,通過連接多個進程而不是通過共享內存來解決這個問題通常更簡單,但通過其他一些機制。

(其原因爲何mmap通常需要一個文件名是,它需要一個連接幾個過程。事實上,如果a.pyb.py兩個呼叫mmap(),如何將系統知道,這兩個過程都在問因爲它們都是mmap編輯同一個文件,還有一些特定於Linux的擴展名給出的名稱與文件的名稱不一致名稱更多黑客恕我直言。)

也許最基本的替代機制是管道:當程序啓動時,它們通常在shell的幫助下連接。這是如何工作(在Linux/Unix上):python a.py | python b.pya.py發送的任何輸出都轉到管道,而管道的另一端是b.py的輸入。你會寫a.py,以便它偵聽UDP套接字並將數據寫入stdout和b.py,以便從stdin中讀取數據以處理收到的數據。如果數據需要進入多個進程,則可以使用例如命名管道,它有一個很好的(但Bash特定的)語法:python a.py >(python b.py) >(python c.py)將啓動帶有兩個參數的a.py,這兩個參數是可以打開和寫入的僞文件的名稱。無論寫入第一個僞文件的什麼都作爲b.py的輸入,類似地,寫入第二個僞文件的內容作爲c.py的輸入。

0

mmap不採用文件名而是文件描述符。它執行所謂的內存映射,即它將進程的虛擬內存空間中的頁面與由文件描述符表示的文件類對象的各部分相關聯。這是一個非常強大的操作,因爲它允許你:

  • 訪問文件的內容,只是作爲內存中的數組;
  • 訪問特殊I/O硬件的內存,例如聲卡的緩衝區或圖形適配器的幀緩衝區(這是可能的,因爲Unix中的文件描述符是抽象的,它們也可以指代設備節點而不是常規文件)。
  • 通過執行同一對象的共享映射來在進程之間共享內存。

在Unix上使用共享內存的前POSIX舊方式是使用System V IPC共享內存。首先必須用shmget(2)創建共享內存段,然後使用shmat(2)附加到該進程。 SysV共享內存段(以及其他IPC對象)沒有名稱而是數字ID,因此提供了特殊的散列函數ftok(3),該函數將路徑名字符串和項目ID整數的組合轉換爲數字鍵ID,但碰撞是可能的。

現代POSIX的方式來使用共享存儲器是打開一個類文件的存儲器的對象與shm_open(2),它與ftruncate(2)調整到所需的尺寸,然後對mmap(2)它。在這種情況下,內存映射就像來自SysV IPC API的shmat(2)調用一樣,因爲shm_open(2)創建初始大小爲零的對象,所以截斷是必需的。

(這些是C API的一部分;什麼Python模塊提供圍繞那些呼叫或多或少薄包裝和通常具有幾乎相同的簽名)

另外,也可以通過存儲器映射來獲得共享存儲器在所有需要共享內存的進程中使用相同的常規文件。事實上,Linux通過在特殊的tmpfs文件系統上創建文件來實現POSIX共享內存操作。 tmpfs驅動程序通過將保存文件內容的頁面直接映射到執行mmap(2)的進程的地址空間來實現非常輕量級的內存映射。由於tmpfs表現爲普通文件系統,因此您可以使用ls,cat和其他shell工具檢查其內容。您甚至可以通過這種方式創建共享內存對象,或修改現有內存對象。 tmpfs中的一個文件與常規文件系統文件之間的區別在於,後者是存儲介質(硬盤,網絡存儲,閃存驅動器等)的持久存儲,偶爾會將更改刷新到此存儲介質,而前者完全存在於RAM中。 Solaris還提供了類似的基於RAM的文件系統,也稱爲tmpfs

在現代操作系統中,內存映射被廣泛使用。可執行文件是內存映射的,以便提供這些頁面的內容,這些頁面包含可執行代碼和靜態數據。共享庫也是內存映射的。由於這些映射是共享的,所以這節省了物理內存。保存可執行文件或共享庫內容的相同物理內存映射到每個進程的虛擬內存空間中。