linux 驅動mmap操作

2021-05-24 08:24:57 字數 3346 閱讀 9842

vma和page結構 和mmap函式

1.page  主要成員

atomic_t count;

//這個頁的引用數. 當這個 count 掉到 0, 這頁被返回給空閒列表.

void *virtual;

//如果頁被對映,則表示這頁的核心虛擬位址; 否則, null.

unsigned long flags;

//描述頁狀態的一套位標誌. 這些包括 pg_locked, 它指示該頁在記憶體中已被加鎖, 以及 pg_reserved,

//它防止記憶體管理系統使用該頁

2.vm_area_struct  主要成員

unsigned long vm_start;//vma 開始於

unsigned long vm_end; //vma 結束

struct file *vm_file;

//指向和這個區(如果有乙個)關聯的 struct file 結構的指標.

unsigned long vm_pgoff;

//檔案中區的偏移, 以頁計. 當乙個檔案和裝置被對映, 這是對映在這個區的第一頁的檔案位置.?????

unsigned long vm_flags;

// 裝置驅動常用的標誌是 vm_io 和 vm_reservued.

//vm_io 標誌乙個 vma 作為記憶體對映的 i/o 區,阻止這個區被包含在程序核轉儲???中.

//vm_reserved 告知記憶體管理系統不要試圖交換出這個 vma;

struct vm_operations_struct *vm_ops;

//操作

//void (*open)(struct vm_area_struct *vma);  vma剛剛產生時,此函式被呼叫來初始化vma

//void (*close)(struct vm_area_struct *vma);  當乙個區被銷毀, 核心呼叫它的關閉操作

//struct page *(*nopage)(struct vm_area_struct *vma, unsigned long address, int *type);

//如果 nopage 方法沒有定義,核心分配乙個空頁.程序訪問不在記憶體中有效 vma 的頁時,nopage 方法被呼叫(如果它被定義)

//int (*populate)(struct vm_area_struct *vm, unsigned long address, unsigned long len, pgprot_t prot, unsigned long pgoff, int

nonblock);

//在它們被使用者空間訪問之前,允許核心"預錯"頁到記憶體. 驅動通常沒有必要實現這個填充方法

void *vm_private_data;

//驅動可以用來儲存它的自身資訊的成員.

3.mmap使用者空間呼叫與核心空間呼叫

void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offset);

//start 指向欲對應的記憶體起始位址,通常設為null,代表讓系統自動選定位址,對應成功後該位址會返回

//引數length代表將檔案中多大的部分對應到記憶體。

//引數prot代表對映區域的保護方式

//fd檔案描述符

//引數offset為檔案對映的偏移量,通常設定為0,代表從檔案最前方開始對應,offset必須是分頁大小

//的整數倍,對映檔案的起動位移量受系統虛存頁長度的限制,那麼如果對映區的長度不是頁長度的整數

//倍時,將如何呢?假定檔案長12位元組,系統頁長為512位元組,則系統通常提供512位元組的對映區,其中

//後500位元組被設為0。可以修改這500位元組,但任何變動都不會在檔案中反映出來

//若對映成功則返回對映區的記憶體起始位址,否則返回map_failed(-1)

核心空間呼叫

int (*mmap) (struct file *filp, struct vm_area_struct *vma);

4.mmap執行的順序

a.在使用者程序建立乙個vma區域

b.驅動程式獲得頁

c.將獲得的頁分配給vma區域

四、如何給vma分配頁

1.一次完成全部

int remap_pfn_range(struct vm_area_struct *vma, unsigned long virt_addr, unsigned long pfn, unsigned long size, pgprot_t prot);

//vma 使用者程序建立乙個vma區域

//virt_addr 重新對映應當開始的使用者虛擬位址. 這個函式建立頁表為這個虛擬位址範圍從 virt_addr 到 virt_addr_size.

//pfn 頁幀號, 對應虛擬位址應當被對映的實體地址. 這個頁幀號簡單地是實體地址右移 page_shift 位. 對大部分使用, vma 結構的 vm_paoff 成員正好包含你需要的值. 這個函式影響實體地址從 (pfn

//返回的值常常是 0 或者乙個負的錯誤值

int io_remap_page_range(struct vm_area_struct *vma, unsigned long virt_addr, unsigned long phys_addr, unsigned long size, pgprot_t prot);

//當用在 phys_addr 指向 i/o 記憶體時返回的值常常是 0 或者乙個負的錯誤值???

2.一頁一頁的分配

struct page *(*nopage)(struct vm_area_struct *vma, unsigned long address, int *type);
//address 代表從使用者空間傳過來的使用者空間虛擬位址
//返回乙個有效對映頁
3.限制:
remap_pfn_range不能對映常規記憶體,只訪問保留頁和在物理記憶體頂之上的實體地址。因為保留頁和在物理
記憶體頂之上的實體地址記憶體管理系統的各個子模組管理不到。640 kb 和 1mb 是保留頁可能對映,裝置i/o
記憶體也可以對映。如果想把kmalloc()申請的記憶體對映到使用者空間,則可以通過mem_map_reserve()把相應
的記憶體設定為保留後就可以。
remap_pfn_range常用於裝置記憶體對映,而nopage()常用於ram對映

Linux記憶體對映 mmap

linux提供了記憶體對映函式mmap,它把檔案內容對映到一段記憶體上 準確說是虛擬記憶體上 通過對這段記憶體的讀取和修改,實現對檔案的讀取和修改,先來看一下mmap的函式宣告 原型 void mmap void addr,size t length,int prot,int flags,int f...

Linux記憶體管理 mmap

mmap munmap是常用的乙個系統呼叫,使用場景是 分配記憶體 讀寫大檔案 連線動態庫檔案 多程序間共享記憶體。mmap munmap函式宣告如下 include void mmap void addr,size t length,int prot,int flags,int fd,off t ...

mmap操作思考題

父子程序共享什麼?共享檔案,和mmap的對映區 但是要用map share 1.men 後mmap能否成功?不可以。位址必須相同 2.如果open時o rdonly,mmap時prot引數指定prot read prot write會怎樣?許可權不夠。原因 建立對映區的許可權 開啟檔案的許可權 但是...