共享記憶體的特殊檔案系統

2021-07-11 02:39:56 字數 3988 閱讀 5125

posix的共享記憶體是通過shm_open來建立的,mmap來對映到程序的位址空間的。 shm_open的檔案是存在於/dev/shm下的。假如要是對映的檔案是/tmp/testfie(/是相對於/dev/shm而言的), 則需要在/dev/shm目錄下建立乙個tmp目錄。

這個特殊的檔案系統是基於ram的。 shmget會在這個特殊的檔案系統上建立乙個檔案,shmat會呼叫mmap把這個檔案對映到程序的位址空間中。

3、程序呼叫mmap()時,只是在程序空間內新增了一塊相應大小的緩衝區,並設定了相應的訪問標識,但並沒有建立程序空間到物理頁面的對映。因此,第一次訪問該空間時,會引發乙個缺頁異常。

4、對於共享記憶體對映情況,缺頁異常處理程式首先在swap cache中尋找目標頁(符合address_space以及偏移量的物理頁),如果找到,則直接返回位址;如果沒有找到,則判斷該頁是否在交換區(swap area),如果在,則執行乙個換入操作;如果上述兩種情況都不滿足,處理程式將分配新的物理頁面,並把它插入到page cache中。程序最終將更新程序頁表。

注:對於對映普通檔案情況(非共享對映),缺頁異常處理程式首先會在page cache中根據address_space以及資料偏移量尋找相應的頁面。如果沒有找到,則說明檔案資料還沒有讀入記憶體,處理程式會從磁碟讀入相應的頁面,並返回相應位址,同時,程序頁表也會更新。

5、所有程序在對映同乙個共享記憶體區域時,情況都一樣,在建立線性位址與實體地址之間的對映之後,不論程序各自的返回位址如何,實際訪問的必然是同乙個共享記憶體區域對應的物理頁面。

注:乙個共享記憶體區域可以看作是特殊檔案系統shm中的乙個檔案,shm的安裝點在交換區上。 

mmap()系統呼叫使得程序之間通過對映同乙個普通檔案實現共享記憶體。普通檔案被對映到程序位址空間後,程序可以向訪問普通記憶體一樣對檔案進行訪問,不必再呼叫read(),write()等操作。

注:實際上,mmap()系統呼叫並不是完全為了用於共享記憶體而設計的。它本身提供了不同於一般對普通檔案的訪問方式,程序可以像讀寫記憶體一樣對普通檔案的操作。而posix或系統v的共享記憶體ipc則純粹用於共享目的,當然mmap()實現共享記憶體也是其主要應用之一。

(1)使用普通檔案提供的記憶體對映:適用於任何程序之間;此時,需要開啟或建立乙個檔案,然後再呼叫mmap();典型呼叫**如下:

fd=open(name, flag, mode);

if(fd<0)

...

ptr=mmap(null, len , prot_read|prot_write, map_shared , fd , 0);通過mmap()實現共享記憶體的通訊方式有許多特點和要注意的地方,我們將在範例中進行具體說明。

(2)使用特殊檔案提供匿名記憶體對映:適用於具有親緣關係的程序之間;由於父子程序特殊的親緣關係,在父程序中先呼叫mmap(),然後呼叫fork()。那麼在呼叫fork()之後,子程序繼承父程序匿名對映後的位址空間,同樣也繼承mmap()返回的位址,這樣,父子程序就可以通過對映區域進行通訊了。注意,這裡不是一般的繼承關係。一般來說,子程序單獨維護從父程序繼承下來的一些變數。而mmap()返回的位址,卻由父子程序共同維護。 

對於具有親緣關係的程序實現共享記憶體最好的方式應該是採用匿名記憶體對映的方式。此時,不必指定具體的檔案,只要設定相應的標誌即可

說起共享記憶體,一般來說會讓人想起下面一些方法:

1、多執行緒。執行緒之間的記憶體都是共享的。更確切的說,屬於同一程序的執行緒使用的是同乙個位址空間,而不是在不同位址空間之間進行記憶體共享;

2、父子程序間的記憶體共享。父程序以map_shared|map_anonymous選項mmap一塊匿名記憶體,fork之後,其子孫程序之間就能共享這塊記憶體。這種共享記憶體由於受到程序父子關係的限制,一般較少使用;

3、mmap檔案。多個程序mmap到同乙個檔案,實際上就是大家在共享檔案page cache中的記憶體。不過檔案牽涉到磁碟的讀寫,用來做共享記憶體顯然十分笨重,所以就有了不跟磁碟扯上關係的記憶體檔案,也就是我們這裡要討論的tmpfs和shmem;

tmpfs是一套虛擬的檔案系統,在其中建立的檔案都是基於記憶體的,機器重啟即消失。

shmem是一套ipc,通過相應的ipc系統呼叫shmget能夠以指定key建立一塊的共享記憶體。需要使用這塊記憶體的程序可以通過shmat系統呼叫來獲得它。

雖然是兩套不同的介面,但是在核心裡面的實現卻是同一套。shmem內部掛載了乙個tmpfs分割槽(使用者不可見),shmget就是在該分割槽下獲取名為"sysv$"的檔案。然後shmat就相當於mmap這個檔案。

所以我們接下來就把tmpfs和shmem當作同乙個東西來討論了。

tmpfs/shmem是乙個介於檔案和匿名記憶體之間的東西。

一方面,它具有檔案的屬性,能夠像操作檔案一樣去操作它。它有自己inode、有自己的page cache;

另一方面,它也有匿名記憶體的屬性。由於沒有像磁碟這樣的外部儲存介質,核心在記憶體緊缺時不能簡單的將page從它們的page cache中丟棄,而需要swap-out;(參閱《linux頁面****》)

對tmpfs/shmem記憶體的讀寫,就是對page cache中相應位置的page所代表的記憶體進行讀寫,這一點跟普通的檔案對映沒有什麼不同。

如果程序位址空間的相應位置尚未對映,則會建立到page cache中相應page的對映;

如果page cache中的相應位置還沒有分配page,則會分配乙個。當然,由於不存在磁碟上的源資料,新分配的page總是空的(特別的,通過read系統呼叫去讀乙個尚未分配page的位置時,並不會分配新的page,而是共享zero_page);

如果page cache中相應位置的page被**了,則會先將其恢復;

對於第三個「如果」,tmpfs/shmem和普通檔案的page**及其恢復方式是不同的:

page**時,跟普通檔案的情況一樣,核心會通過prio_tree反向對映找到對映這個page的每乙個page table,然後將其中對應的pte清空。

不同之處是普通檔案的page在確保與磁碟同步(如果page為臟的話需要刷回磁碟)之後就可以丟棄了,而對於tmpfs/shmem的page則需要進行swap-out。

注意,匿名page在被swap-out時,並不是將對映它的pte清空,而是得在pte上填寫相應的swap_entry,以便知道page被換出到**去,否則再需要這個page的時候就沒法swap-in了。

而tmpfs/shmem的page呢?page table中對應的pte被清空,swap_entry會被存放在page cache的radix_tree的對應slot上。

等下一次訪問觸發page fault時,page需要恢復。

普通檔案的page恢復跟page未分配時的情形一樣,需要新分配page、然後根據對映的位置重新從磁碟讀出相應的資料;

而tmpfs/shmem則是通過對映的位置找到radix_tree上對應的slot,從中得到swap_entry,從而進行swap-in,並將新的page放回page cache;

這裡就有個問題了,在page cache的radix_tree的某個slot上,怎麼知道裡面存放著的是正常的page?還是swap-out後留下的swap_entry?

如果是swap_entry,那麼slot上的值將被加上radix_tree_exceptional_entry標記(值為2)。swap_entry的值被左移兩位後or上radix_tree_exceptional_entry,填入slot。

也就是說,如果$ & radix_tree_exceptional_entry != 0,則它代表swap_entry,且swap_entry的值是$ >> 2;否則它代表page,$就是指向page的指標,當然其值可能是null,說明page尚未分配。

那麼顯然,page的位址值其末兩位肯定是0,否則就可能跟radix_tree_exceptional_entry標記衝突了;而swap_entry的值最大只能是30bit或62bit(對應32位或64位機器),否則左移兩位就溢位了。

最後以一張圖說明一下匿名page、檔案對映page、tmpfs/shmem page的**及恢復過程:

Linux系統中特殊檔案許可權

檔案許可權的機制是linux系統中的一大特色,除了我們現在所熟知的du r 寫 w 執行 x 許可權外,還有三個比較特殊的許可權,分別為setuid setgid和stick bit 粘滯位 看一下系統中用到它的地方,以 etc passwd和 usr bin passwd為例 分析一下,etc p...

Linux的特殊檔案許可權

一般檔案許可權讀 r 寫 w 執行 x 許可權比較簡單。一般材料上面都有介紹。這裡介紹一下一些特殊的檔案許可權 suid,sgid,stick bit。如果你檢查一下 usr bin passwd和 tmp 的檔案許可權你就會發現和普通的檔案許可權有少許不同,如下圖所示 這裡就涉及到suid和sti...

Linux的特殊檔案許可權

一般檔案許可權讀 r 寫 w 執行 x 許可權比較簡單。一般材料上面都有介紹。這裡介紹一下一些特殊的檔案許可權 suid,sgid,stick bit。如果你檢查一下 usr bin passwd和 tmp 的檔案許可權你就會發現和普通的檔案許可權有少許不同,如下圖所示 這裡就涉及到suid和sti...