Unix環境程式設計 程序通訊 IPC共享記憶體學習

2021-05-24 22:43:21 字數 4467 閱讀 7480

參考書籍:

程式設計第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 ...