天天看點

mmap函數分析使用執行個體

mmap将一個檔案或者其它對象映射進記憶體。檔案被映射到多個頁上,如果檔案的大小不是所有頁的大小之和,最後一個頁不被使用的空間将會清零。mmap在使用者空間映射調用系統中作用很大。

gcc man中的描述

mmap() creates a new mapping in the virtual address space of the call‐ing process. The starting address for the new mapping is specified in addr. The length argument specifies the length of the mapping.

If addr is NULL, then the kernel chooses the address at which to create the mapping; this is the most portable method of creating a new map‐ping. If addr is not NULL, then the kernel takes it as a hint about where to place the mapping; on Linux, the mapping will be created at a nearby page boundary. The address of the new mapping is returned as the result of the call.

The prot argument describes the desired memory protection of the map‐ping (and must not conflict with the open mode of the file).

The flags argument determines whether updates to the mapping are visi‐ble to other processes mapping the same region, and whether updates are carried through to the underlying file.

使用者空間:

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

參數:

addr: 通常為0或者NULL

length:映射區的長度,如果不是一個頁大小,按一個頁算,一個頁通常為4k

prot:期望的記憶體保護标志

PROT_EXEC Pages may be executed.

PROT_READ Pages may be read.

PROT_WRITE Pages may be written.

PROT_NONE Pages may not be accessed.

flags:指定映射對象的類型

MAP_SHARED :Share this mapping. Updates to the mapping are visible to other processes that map this file, and are carried through to the underlying file. The file may not actually be updated until msync(2) or munmap() is called.

MAP_PRIVATE:Create a private copy-on-write mapping. Updates to the map‐ping are not visible to other processes mapping the same file, and are not carried through to the underlying file.It is unspecified whether changes made to the file after the mmap() call are visible in the mapped region.

MAP_32BIT

MAP_ANON

MAP_ANONYMOUS

MAP_DENYWRITE

MAP_EXECUTABLE

MAP_FILE

MAP_FIXED

MAP_GROWSDOWN

etc

fd:檔案指針

offset:偏移位置

int munmap(void *addr, size_t length);

核心空間中裝置驅動程式中也有一個mmap:

static int mmap(struct file * file,struct vm_area_struct * vma)

//

當調試uboot時,可以通過md指令檢視某些寄存器或者管腳的狀态.

當挂載linux核心後,如果想要檢視某些寄存器的值,我們可以通過mmap來實作.

使用者空間調用mmap函數,核心空間在對應的裝置驅動中實作相應的mmap函數.

int remap_pfn_range(struct vm_area_struct*vma, unsigned long addr, unsigned long pfn, unsignedlong size, pgprot_t prot)

vma:使用者層使用的vma 虛拟的記憶體指針

addr:使用者的起始位址

pfn:核心空間的實體位址所在頁幀号。通過實體位址>>PAGE_SHIFT得到

size:待映射區域大小

prot:vma頁保護标志

/

1.控制led燈的亮暗

2.讀取目前led 腳的輸出狀态的寄存器值

3.改變led的亮暗情況

4.再讀取led腳的輸出狀态

5.比較讀出的值和實際的led表現是否一緻

通過查datasheet和線路圖,我知道led的輸出寄存器為0xE0200284(PA),我們知道核心中使用的都是虛拟位址.

使用者空間想要讀取 0xE0200284的值,可以通過mmap來實作.這樣我們想要讀某個寄存器的值,将是很友善的事情.

效果:

mmap函數分析使用執行個體

首先,最開始的時候led燈4個都是關閉的,此時輸出 高電平.讀出來的管腳是0x0f

然後,依次打開4個led燈,此時輸出低電平.讀出來的管腳是0x0

這是很有用的一個功能.

繼續閱讀