參考書籍:
程式設計第2版
>
、系統分析和高階程式設計技術
>
、核心完全注釋
>
共享記憶體即讓兩個程序訪問同一部分邏輯記憶體。是有
ipc為乙個程序建立的特殊的位址範圍,出現在程序的位址空間中,其他程序可以把同一段共享記憶體段連線到它們自己的位址空間去。如果乙個程序向這段共享記憶體寫了資料,所做的改變立刻被其他程序看到。但是共享記憶體本身沒有同步功能,需要我們自己注意同步。
1.系統的共享記憶體段在系統核心中也有乙個內部的資料結構
shmid_ds
。描述了共享記憶體的認證,位元組大小,分離、改變時間,建立它的程序,最後操作的程序以及多少程序在使用等資訊。這些資料結構儲存在
shm_segs
向量表中,
struct shmid_ds
不是核心用來跟蹤共享記憶體區域的資料結構。取而代之的是,
struct shmid_ds
包含這種資訊的絕大部分,而剩下的資訊則位於下邊要介紹的
struct shmid_kernel
中。shmid_ds
在linux/shm.h
中有定義:
相關標頭檔案
sys/shm.h sys/ipc.h sys/types.h
。ipc/shm.c
裡有對應核心原始碼。這是
shm.h
裡關於共享記憶體函式的宣告。
共享記憶體處理函式中使用的一些巨集:
系統中共享記憶體數量是限制巨集和
共享記憶體出來函式中使用的
flag
在shm.c
檔案中定義了共享記憶體例外的幾個屬性:
struct shmid_kernel
用於分離「私有(
private
)」的共享記憶體相關資訊和「公有(
public
)」的資訊。
struct shmid_ds
裡那些對使用者應用程式可見的部分還保留在
struct shmid _ds
之內,而關係到核心的私有資訊則位於
struct shmid_kernel
之內。使用者應用程式需要能夠通過
struct shmid_ds
來進行shmctl
系統呼叫,所以它的定義必須對它們是可見的,但是核心私有實現的細節就不應該出現在
struct
的定義之中。否則,改變核心的執行可能會中斷應用程式。
3.共享記憶體函式解析
shmget()
:建立共享記憶體。程式需要乙個鍵字引數
key也就是共享記憶體段的名字,
shmget
返回乙個供後續共享記憶體函式使用的共享記憶體標識碼。首先系統是呼叫
sys_ipc
(ipc.c
內)call
值為shmget
建立乙個鍵值為
key的共享記憶體物件,或者獲得已經存在的鍵值為
key的某共享記憶體物件的引用識別符號。
size
表需要共享的記憶體量,位元組為單位。
shm***有9
個許可權標誌。
ipc_creat
和其他標誌或在一起才能建立新的共享記憶體段。使用方法和
open
函式的mode
引數類似。
sys_ipc
函式:
sys_semget
函式:
sys_semget
函式流程:
key=ipc_private
時穿件本程序的私有共享記憶體。
sys_shmget
中newseg
函式與newque
和newary
相對應的函式,主要工作是計算
size
大小,申請
shmid_kernel
資料結構,申請一塊用於建立頁表的空間並清零,填寫
shmid_kernel
資料結構並加入到
shm_segs
中,返回共享記憶體物件的引用識別符號,
struct shmid_kernel
是由kmalloc
分配的(在不可交換的核心記憶體裡)。
key有值的時候,如果在沒有在
shm_segs
中找到鍵值為
key的共享記憶體物件,檢測傳入的
shm***
,如果shm***
需要建立則建立,否則返回錯誤。如果找到,根據
shm***
判斷是否要求建立,要求建立返回錯誤,不要求建立並且檢測
shm_lock()
返回的shmid_kernel
結構體是否合法,合法返回物件的識別符號。
鍵:在ipc
的通訊模式下,不管是使用訊息佇列還是共享記憶體,甚至是訊號量,每個
ipc的物件
(object)
都有唯一的名字,稱為「鍵」
(key)
。通過「鍵」,程序能夠識別所用的物件。「鍵」與
ipc物件的關係就如同檔名稱之於檔案,通過檔名,程序能夠讀寫檔案內的資料,甚至多個程序能夠共用乙個檔案。而在
ipc的通訊模式下,通過「鍵」的使用也使得乙個
ipc物件能為多個程序所共用。
linux
系統中的所有表示
systemv
中ipc
物件的資料結構都包括乙個
ipc_perm
結構,其中包含有
ipc物件的鍵值,該鍵用於查詢
systemv
中ipc
物件的引用識別符號。如果不使用「鍵」,程序將無法訪問
ipc物件,因為
ipc物件並不存在於程序本身使用的記憶體中。
shmat()
把建立的共享記憶體段連線到某個程序的位址空間以便訪問。第乙個引數
shm_id
是shmget
返回的標識碼,
shm_addr
是共享記憶體連線到當前程序時準備放置的位址,如果是空指標表把該工作交給系統完成。
shm***
處理標識,
shm_rnd
,shm_rdonly
。返回的是程序中虛擬位址。
shmat()
函式:
kernel
中sys_shmat()
函式首先是根據
shmid
找到共享記憶體物件。根據
shmaddr
的位址座位對映的虛擬位址,當
shmaddr為0
時,隨機分配乙個。檢查虛擬位址合法性,申請一塊用來建
vm_area_struct
結構記憶體,並填寫,加入到程序的
mm結構和該共享記憶體物件的
vm_area_struct
佇列中。
shmdt
函式時把共享記憶體與當前程序脫離開。引數是
shmget
返回的位址指標。不影響其他程序和該共享記憶體物件的互動。當前程序的
vm_area_struct
結構被從
shmid_ds
中刪除釋放,程序的頁表也被更新,當該共享記憶體和最後乙個程序也分離,則共享記憶體頁和
kemid_kernel
結構也都被釋放。
sys_shmdt
函式:
shmctl
函式,共享記憶體的控制函式。引數
command
表將要採取的動作:
ipc_stat,shm_stat
把shmid_ds
結構中的資料設定為共享記憶體的當前關聯值
,ipc_set
在程序有許可權下把共享記憶體的當前關聯值設為
shmid_ds
給的值,ipc_rmid
刪除共享記憶體段,獲得共享記憶體狀態
(shm_info ipc_info)
,鎖定和釋放(
shm_locked
)等。引數
buf是指向
shmid_ds
結構體的指標。
shmctl函式:
例項(linux
程式設計原始碼):
shm_com.h
shm1.c
shm2.c
例項的共享記憶體大小為shared_use_st結構體大小,shm1.c shm2.c 通過
結構體第乙個變數wtiteen_by_you實現兩個程序對共享記憶體區域的同步操作。讀寫的內容儲存到buffer中。首先建立共享記憶體段,連線。然後shm1.c持續讀共享記憶體中內容,shm2.c持續寫共享到共享記憶體中,以字串end結束。共享記憶體從程序分離並刪除。
用兩個shh登陸分別執行1和2程式:
ipcs –m
和ipcrm shm
命令:ipcs -m 可以看我們的系統共享記憶體情況,ipcrm shm 可以刪除共享記憶體。執行1程式後直接ctrl c中止程序,我們就沒有釋放申請的共享記憶體段,我們用ipcrm shm釋放共享記憶體。
unix環境高階程式設計 程序間通訊(2)
函式popen和pclose 常見的操作是建立乙個連線到另乙個程序的管道,然後讀其輸出或向其輸入端傳送資料,這兩個函式實現的操作是 建立乙個管道,fork乙個子程序,關閉未使用的管道端,執行乙個shell執行命令,然後等待命令終止。函式popen執行fork,呼叫exec執行cmdstring,返回...
程序通訊 IPC
訊號 管道 訊息佇列 共享記憶體 定義 程序間的軟體中斷通知和處理機制 訊號的接收處理 捕獲 catch 忽略 ignore 遮蔽 mask 不足 傳遞的資訊量小,只有乙個訊號型別 程序間基於記憶體檔案的通訊機制 匿名管道只能在父子程序間進行通訊,不能再網路間進行通訊,而且資料傳輸是單向的,只能一端...
UNIX環境變數 IPC之管道通訊
無名管道是一種特殊型別的檔案,完全由作業系統管理和維護,因為其儲存位置只有親緣關係的程序知道,所以只能用於親緣關係的程序之間通訊,而且,其核心資源會在兩個通訊程序退出後自動釋放,無名管道建立函式為 from usr include unistd.h int pipe int fd 2 函式pipe ...