最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

玩轉(zhuǎn)Linux共享內(nèi)存原理(含源代碼~)

2022-05-23 19:50 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿
  • 在Linux系統(tǒng)中,每個(gè)進(jìn)程都有獨(dú)立的虛擬內(nèi)存空間,也就是說不同的進(jìn)程訪問同一段虛擬內(nèi)存地址所得到的數(shù)據(jù)是不一樣的,這是因?yàn)椴煌M(jìn)程相同的虛擬內(nèi)存地址會映射到不同的物理內(nèi)存地址上。

  • 但有時(shí)候?yàn)榱俗尣煌M(jìn)程之間進(jìn)行通信,需要讓不同進(jìn)程共享相同的物理內(nèi)存,Linux通過 共享內(nèi)存 來實(shí)現(xiàn)這個(gè)功能。下面先來介紹一下Linux系統(tǒng)的共享內(nèi)存的使用。

共享內(nèi)存使用

1. 獲取共享內(nèi)存

  • 要使用共享內(nèi)存,首先需要使用 shmget() 函數(shù)獲取共享內(nèi)存,shmget() 函數(shù)的原型如下:

  1. 參數(shù) key 一般由 ftok() 函數(shù)生成,用于標(biāo)識系統(tǒng)的唯一IPC資源。

  2. 參數(shù) size 指定創(chuàng)建的共享內(nèi)存大小。

  3. 參數(shù) shmflg 指定 shmget() 函數(shù)的動作,比如傳入 IPC_CREAT 表示要?jiǎng)?chuàng)建新的共享內(nèi)存。

  • 函數(shù)調(diào)用成功時(shí)返回一個(gè)新建或已經(jīng)存在的的共享內(nèi)存標(biāo)識符,取決于shmflg的參數(shù)。失敗返回-1,并設(shè)置錯(cuò)誤碼。

2. 關(guān)聯(lián)共享內(nèi)存

  • shmget() 函數(shù)返回的是一個(gè)標(biāo)識符,而不是可用的內(nèi)存地址,所以還需要調(diào)用 shmat() 函數(shù)把共享內(nèi)存關(guān)聯(lián)到某個(gè)虛擬內(nèi)存地址上。shmat() 函數(shù)的原型如下:

  1. 參數(shù) shmid 是 shmget() 函數(shù)返回的標(biāo)識符。

  2. 參數(shù) shmaddr 是要關(guān)聯(lián)的虛擬內(nèi)存地址,如果傳入0,表示由系統(tǒng)自動選擇合適的虛擬內(nèi)存地址。

  3. 參數(shù) shmflg 若指定了 SHM_RDONLY 位,則以只讀方式連接此段,否則以讀寫方式連接此段。

  • 函數(shù)調(diào)用成功返回一個(gè)可用的指針(虛擬內(nèi)存地址),出錯(cuò)返回-1。

3. 取消關(guān)聯(lián)共享內(nèi)存

  • 當(dāng)一個(gè)進(jìn)程不需要共享內(nèi)存的時(shí)候,就需要取消共享內(nèi)存與虛擬內(nèi)存地址的關(guān)聯(lián)。取消關(guān)聯(lián)共享內(nèi)存通過 shmdt() 函數(shù)實(shí)現(xiàn),原型如下:

  1. 參數(shù) shmaddr 是要取消關(guān)聯(lián)的虛擬內(nèi)存地址,也就是 shmat() 函數(shù)返回的值。

  • 函數(shù)調(diào)用成功返回0,出錯(cuò)返回-1。

【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個(gè)人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!??!前100名進(jìn)群領(lǐng)取,額外贈送一份價(jià)值699的內(nèi)核資料包(含視頻教程、電子書、實(shí)戰(zhàn)項(xiàng)目及代碼)? ??

共享內(nèi)存使用例子

  • 下面通過一個(gè)例子來介紹一下共享內(nèi)存的使用方法。在這個(gè)例子中,有兩個(gè)進(jìn)程,分別為 進(jìn)程A 和 進(jìn)程B,進(jìn)程A 創(chuàng)建一塊共享內(nèi)存,然后寫入數(shù)據(jù),進(jìn)程B 獲取這塊共享內(nèi)存并且讀取其內(nèi)容。

進(jìn)程A

進(jìn)程B

  • 測試時(shí)先運(yùn)行進(jìn)程A,然后再運(yùn)行進(jìn)程B,可以看到進(jìn)程B會打印出 “Hello World”,說明共享內(nèi)存已經(jīng)創(chuàng)建成功并且讀取。

共享內(nèi)存實(shí)現(xiàn)原理

  • 我們先通過一幅圖來了解一下共享內(nèi)存的大概原理,如下圖:


  • 通過上圖可知,共享內(nèi)存是通過將不同進(jìn)程的虛擬內(nèi)存地址映射到相同的物理內(nèi)存地址來實(shí)現(xiàn)的,下面將會介紹Linux的實(shí)現(xiàn)方式。

  • 在Linux內(nèi)核中,每個(gè)共享內(nèi)存都由一個(gè)名為 struct shmid_kernel 的結(jié)構(gòu)體來管理,而且Linux限制了系統(tǒng)最大能創(chuàng)建的共享內(nèi)存為128個(gè)。通過類型為 struct shmid_kernel 結(jié)構(gòu)的數(shù)組來管理,如下:

  • 從注釋可以知道 struct shmid_kernel 結(jié)構(gòu)體各個(gè)字段的作用,比如 shm_npages 字段表示共享內(nèi)存使用了多少個(gè)內(nèi)存頁。而 shm_pages 字段指向了共享內(nèi)存映射的虛擬內(nèi)存頁表項(xiàng)數(shù)組等。

  • 另外 struct shmid_ds 結(jié)構(gòu)體用于管理共享內(nèi)存的信息,而 shm_segs數(shù)組 用于管理系統(tǒng)中所有的共享內(nèi)存。

shmget() 函數(shù)實(shí)現(xiàn)

  • 通過前面的例子可知,要使用共享內(nèi)存,首先需要調(diào)用 shmget() 函數(shù)來創(chuàng)建或者獲取一塊共享內(nèi)存。shmget() 函數(shù)的實(shí)現(xiàn)如下:

  • shmget() 函數(shù)的實(shí)現(xiàn)比較簡單,首先調(diào)用 findkey() 函數(shù)查找值為key的共享內(nèi)存是否已經(jīng)被創(chuàng)建,findkey() 函數(shù)返回共享內(nèi)存在 shm_segs數(shù)組 的索引。如果找到,那么直接返回共享內(nèi)存的標(biāo)識符即可。否則就調(diào)用 newseg() 函數(shù)創(chuàng)建新的共享內(nèi)存。newseg() 函數(shù)的實(shí)現(xiàn)也比較簡單,就是創(chuàng)建一個(gè)新的 struct shmid_kernel 結(jié)構(gòu)體,然后設(shè)置其各個(gè)字段的值,并且保存到 shm_segs數(shù)組 中。

shmat() 函數(shù)實(shí)現(xiàn)

  • shmat() 函數(shù)用于將共享內(nèi)存映射到本地虛擬內(nèi)存地址,由于 shmat() 函數(shù)的實(shí)現(xiàn)比較復(fù)雜,所以我們分段來分析這個(gè)函數(shù):

上面這段代碼主要通過 shmid 標(biāo)識符來找到共享內(nèi)存描述符,上面說過系統(tǒng)中所有的共享內(nèi)存到保存在 shm_segs 數(shù)組中。

上面的代碼主要找到一個(gè)可用的虛擬內(nèi)存地址,如果在調(diào)用 shmat() 函數(shù)時(shí)沒有指定了虛擬內(nèi)存地址,那么就通過 get_unmapped_area() 函數(shù)來獲取一個(gè)可用的虛擬內(nèi)存地址。

上面的代碼主要通過調(diào)用 kmem_cache_alloc() 函數(shù)創(chuàng)建一個(gè) vm_area_struct 結(jié)構(gòu),在內(nèi)存管理一章知道,vm_area_struct 結(jié)構(gòu)用于管理進(jìn)程的虛擬內(nèi)存空間。

上面的代碼主要是設(shè)置剛創(chuàng)建的 vm_area_struct 結(jié)構(gòu)的各個(gè)字段,比較重要的是設(shè)置其 vm_ops 字段為 shm_vm_ops,shm_vm_ops 定義如下:

  • shm_vm_ops 的 nopage 回調(diào)為 shm_nopage() 函數(shù),也就是說,當(dāng)發(fā)生頁缺失異常時(shí)將會調(diào)用此函數(shù)來恢復(fù)內(nèi)存的映射。

  • 從上面的代碼可看出,shmat() 函數(shù)只是申請了進(jìn)程的虛擬內(nèi)存空間,而共享內(nèi)存的物理空間并沒有申請,那么在什么時(shí)候申請物理內(nèi)存呢?答案就是當(dāng)進(jìn)程發(fā)生缺頁異常的時(shí)候會調(diào)用 shm_nopage() 函數(shù)來恢復(fù)進(jìn)程的虛擬內(nèi)存地址到物理內(nèi)存地址的映射。

shm_nopage() 函數(shù)實(shí)現(xiàn)

  • shm_nopage() 函數(shù)是當(dāng)發(fā)生內(nèi)存缺頁異常時(shí)被調(diào)用的,代碼如下:

shm_nopage() 函數(shù)的主要功能是當(dāng)發(fā)生內(nèi)存缺頁時(shí),申請新的物理內(nèi)存頁,并映射到共享內(nèi)存中。由于使用共享內(nèi)存時(shí)會映射到相同的物理內(nèi)存頁上,從而不同進(jìn)程可以共用此塊內(nèi)存。


玩轉(zhuǎn)Linux共享內(nèi)存原理(含源代碼~)的評論 (共 條)

分享到微博請遵守國家法律
衡山县| 庐江县| 高密市| 从化市| 正阳县| 高邑县| 新竹市| 九江县| 荆州市| 岐山县| 南木林县| 安仁县| 武山县| 庄河市| 青州市| 彝良县| 新绛县| 阿鲁科尔沁旗| 房山区| 商水县| 德格县| 东乌珠穆沁旗| 邵阳县| 丹棱县| 西安市| 屏边| 定州市| 商都县| 云龙县| 三原县| 冕宁县| 永胜县| 瑞丽市| 新龙县| 乐业县| 广饶县| 射阳县| 博野县| 万山特区| 汶川县| 鹿邑县|