日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OS - MMAP初探

發布時間:2025/3/21 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OS - MMAP初探 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 生猛干貨
  • What's mmap
  • mmap 函數
  • mmap() 的底層原理
    • 虛擬內存空間與物理內存空間
    • vm_area_struct 結構
    • 對文件的讀寫
  • 搞定計算機基礎內功

生猛干貨

計算機專業學生、非科班程序員必備! 90%程序員忽略的大廠招聘考點、技能進階秘訣盡在這里!


What’s mmap

https://man7.org/linux/man-pages/man2/mmap.2.html

簡單來說: mmap() 系統調用能夠將文件映射到內存空間,然后可以通過讀寫內存來讀寫文件


mmap 函數

#include <sys/mman.h>void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
  • start:指定要映射的內存地址,一般設置為 NULL 讓操作系統自動選擇合適的內存地址。
  • length:映射地址空間的字節數,它從被映射文件開頭 offset 個字節開始算起。
  • prot:指定共享內存的訪問權限。可取如下幾個值的可選:PROT_READ(可讀), PROT_WRITE(可寫), PROT_EXEC(可執行), PROT_NONE(不可訪問)。
  • flags:由以下幾個常值指定:MAP_SHARED(共享的) MAP_PRIVATE(私有的), - MAP_FIXED(表示必須使用 start 參數作為開始地址,如果失敗不進行修正),其中,MAP_SHARED , MAP_PRIVATE必選其一,而 MAP_FIXED 則不推薦使用。
  • fd:表示要映射的文件句柄。
  • offset:表示映射文件的偏移量,一般設置為 0 表示從文件頭部開始映射。

函數的返回值為最后文件映射到進程空間的地址,進程可直接操作起始地址為該值的有效地址。

舉個例子

int main() {...fd = open(name, flag, mode);if (fd < 0) {// error process...exit(1);}addr = mmap(NULL, len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, fd, 0);if (addr < 0) {// error process...exit(1);}memset(addr, 0, len);...exit(0); }

首先通過 open() 系統調用打開一個文件,然后通過調用 mmap() 把文件映射到內存空間,映射成功后就可以通過操作函數返回的內存地址來對文件進行讀寫操作


mmap() 的底層原理

虛擬內存空間與物理內存空間

我們先來看下 操作系統的虛擬內存空間物理內存空間的概念 。

在 32位的 Linux 內核中,每個進程都獨有 4GB 的虛擬內存空間,但所有進程卻共用相同的物理內存空間。

物理內存空間就是安裝在電腦上的內存條,如果內存條只有 1GB,那么物理內存空間就只有 1GB。但虛擬內存空間是邏輯上的內存空間,虛擬內存空間必須映射到物理內存空間才能使用

虛擬內存空間與物理內存空間映射關系如下:

映射是按內存頁進行的,一個內存頁為 4KB 大小。

在上圖中,P1 是進程1,P2 是進程2。

  • 進程1的虛擬內存頁A映射到物理內存頁A
  • 進程2的虛擬內存頁A映射到物理內存頁B
  • 進程1的虛擬內存頁B和進程2的虛擬內存頁B同時映射到物理內存頁C,也就是說進程1和進程2共享了物理內存頁C

vm_area_struct 結構

在Linux內核中,虛擬內存是用過結構體 vm_area_struct 來管理的,通過 vm_area_struct 結構體可以把虛擬內存劃分為多個用途不相同的內存區,比如可以劃分為數據段區、代碼段區等等.

vm_area_struct

struct vm_area_struct { struct mm_struct * vm_mm; /* The address space we belong to. */ unsigned long vm_start; /* Our start address within vm_mm. */ unsigned long vm_end; /* The first byte after our end addresswithin vm_mm. *//* linked list of VM areas per task, sorted by address */ struct vm_area_struct *vm_next;pgprot_t vm_page_prot; /* Access permissions of this VMA. */ unsigned long vm_flags; /* Flags, listed below. */rb_node_t vm_rb;struct vm_area_struct *vm_next_share; struct vm_area_struct **vm_pprev_share;/* Function pointers to deal with this struct. */ struct vm_operations_struct * vm_ops; ... struct file * vm_file; /* File we map to (can be NULL). */ ... };

vm_area_struct 結構各個字段作用:

  • vm_mm:指向進程內存空間管理對象。
  • vm_start:內存區的開始地址。
  • vm_end:內存區的結束地址。
  • vm_next:用于連接進程的所有內存區。
  • vm_page_prot:指定內存區的訪問權限。
  • vm_flags:內存區的一些標志。
  • vm_file:指向映射的文件對象。
  • vm_ops:內存區的一些操作函數。

vm_area_struct 結構與虛擬內存地址的關系如下圖:


每個進程都由 task_struct 結構進行管理,task_struct 結構中的 mm 成員指向了每個進程的內存管理結構 mm_struct,而 mm_struct 結構的 mmap 成員記錄了進程虛擬內存空間各個內存區的 vm_area_struct 結構鏈表。

當調用 mmap() 時,內核會創建一個 vm_area_struct 結構,并且把 vm_start 和 vm_end 指向虛擬內存空間的某個內存區,并且把 vm_file 字段指向映射的文件對象。然后調用文件對象的 mmap 接口來對 vm_area_struct 結構的 vm_ops 成員進行初始化,如 ext2 文件系統的文件對象會調用 generic_file_mmap() 函數進行初始化,代碼如下:

static struct vm_operations_struct generic_file_vm_ops = { nopage: filemap_nopage, };int generic_file_mmap(struct file * file, struct vm_area_struct * vma) { struct address_space *mapping = file->f_dentry->d_inode->i_mapping; struct inode *inode = mapping->host;if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) { if (!mapping->a_ops->writepage) return -EINVAL; } if (!mapping->a_ops->readpage) return -ENOEXEC; UPDATE_ATIME(inode); vma->vm_ops = &generic_file_vm_ops; return 0; }

vm_operations_struct 結構的 nopage 接口會在訪問內存發生異常時被調用,上面指向的是 filemap_nopage() 函數,filemap_nopage() 函數的主要工作是:

  • 把映射到虛擬內存區的文件內容讀入到物理內存頁中。
  • 對訪問發生異常的虛擬內存地址與物理內存地址進行映射。
  • 處理過程如下


    如上圖所示,虛擬內存頁m 映射到 物理內存頁x,并且把映射的文件的內容讀入到物理內存中,這樣就把內存與文件的映射關系建立起來,對映射的內存區進行讀寫操作實際上就是對文件的讀寫操作。

    一般來說,對映射的內存空間進行讀寫并不會實時寫入到文件中,所以要對內存與文件進行同步時需要調用 msync() 函數來實現。


    對文件的讀寫

    像 read()/write() 這些系統調用,首先需要進行內核空間,然后把文件內容讀入到緩存中,然后再對緩存進行讀寫操作,最后由內核定時同步到文件中。過程如下圖:


    而調用 mmap() 系統調用對文件進行映射后,用戶對映射后的內存進行讀寫實際上是對文件緩存的讀寫,所以減少了一次系統調用,從而加速了對文件讀寫的效率。如下圖:


    搞定計算機基礎內功

    總結

    以上是生活随笔為你收集整理的OS - MMAP初探的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 丰满少妇影院 | 国产一区二区久久久 | 香蕉精品视频在线观看 | 骚虎tv| 美女扒开内裤让男人桶 | 久久久久无码国产精品 | 亚洲毛片精品 | 久操伊人网 | 伊人365影院 | 性一交一乱一区二区洋洋av | 爱情岛论坛成人av | 国产一区成人 | 香蕉av一区二区 | 四虎精品一区 | 高跟鞋av| 亚洲欧美视频二区 | 亚洲麻豆精品 | 日韩毛片高清在线播放 | 中文字幕日韩三级片 | 亚洲日本不卡 | 亚洲专区区免费 | 猫咪av网 | 久操视频在线播放 | 人人妻一区二区三区 | 久久wwww | 亚洲视频在线一区 | 一边吃奶一边摸做爽视频 | 欧美a√ | 国产伦精品一区二区三区千人斩 | 亚洲精品一区二区三区不卡 | 超碰在线观看91 | 中文av在线播放 | 在线观看免费国产视频 | 青青草草视频 | 国产蜜臀在线 | 国产精品扒开腿做爽爽爽男男 | 这里只有精品视频 | 精品人妻一区二区三区视频 | 国产又猛又粗 | 久久精品免费看 | 中国1级毛片 | 流白浆视频 | 国产精品100 | 91久久精品一区二区别 | 91丨porny丨中文 | 性生活免费网站 | 精品免费国产 | 欧美精品人妻一区二区 | 中国毛片网 | 久久成人网18网站 | 亚洲国产成人在线 | xxxwww国产| 97视频在线免费 | 依人综合网 | 日韩精品一区二区三区视频 | 九九色播 | 粗大黑人巨茎大战欧美成人 | a一级黄色片 | 国产网红无码精品视频 | 每日更新在线观看av | 免费在线观看成年人视频 | 日本内谢少妇xxxxx少交 | 国产婷婷在线观看 | 亚洲porn | 波多野结衣 久久 | 99综合视频 | 伊人五月天 | 欧美黄色免费 | 日韩欧美精品在线 | 国产自产精品 | 午夜一区二区三区在线观看 | 中文字幕网站在线观看 | 玖玖视频国产 | 国产ts在线 | www.rihan| 美国黄色a级片 | 欧美人妻精品一区二区 | 午夜激情视频在线播放 | 中文字幕一区二区三区四区欧美 | 久久久久久一级片 | 人人插人人 | 国产精品1页 | 亚洲经典视频在线观看 | 大胸美女网站 | 精品自拍偷拍 | 欧美人喂奶吃大乳 | 中国少妇av | 性色av蜜臀av浪潮av老女人 | 成人激情小说网站 | 捆绑调教sm束缚网站 | 自拍偷拍第3页 | 老女人毛片50一60岁 | 中文字幕日韩一区二区三区 | 久久久久久在线观看 | 亚洲经典视频在线观看 | 91中文字幕在线播放 | 欧美乱码精品 | 永久免费未满蜜桃 | 亚洲a一区 |