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來實現.這樣我們想要讀某個寄存器的值,將是很方便的事情.

效果:

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

這是很有用的一個功能.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章