dev mem 原理 linux,利用/dev/mem和mmap讀寫linux內存的通用C代碼及原理

#define MMAP_MEM_PAGEALIGN (4*1024-1)

typedef struct

{

unsigned int memAddr;

unsigned int memSize;

unsigned int mmapMemAddr;

unsigned int mmapMemSize;

unsigned int memOffset;

int memDevFd;

volatile unsigned int *pMemVirtAddr;

} MMapCtrl;

MMapCtrl gMMapCtrl;

int32 common_MMap(uint32_t physAddr, uint32_t memSize , uint32_t *pMemVirtAddr){

gMMapCtrl.memDevFd = open("/dev/mem",O_RDWR|O_SYNC);

if(gMMapCtrl.memDevFd < 0)

{

printf(" ERROR: /dev/mem open failed !!!\n");

return -1;

}

gMMapCtrl.memOffset = physAddr & MMAP_MEM_PAGEALIGN;

gMMapCtrl.mmapMemAddr = physAddr - gMMapCtrl.memOffset;

gMMapCtrl.mmapMemSize = memSize + gMMapCtrl.memOffset;

gMMapCtrl.pMemVirtAddr = mmap(

(void*)gMMapCtrl.mmapMemAddr,

gMMapCtrl.mmapMemSize,

PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED,

gMMapCtrl.memDevFd,

gMMapCtrl.mmapMemAddr

);

if (gMMapCtrl.pMemVirtAddr==NULL)

{

printf(" ERROR: mmap() failed !!!\n");

return -1;

}

*pMemVirtAddr = (UInt32)((UInt32)gMMapCtrl.pMemVirtAddr + gMMapCtrl.memOffset);

return 0;

}

Int32 common_unmapMem()

{

if(gMMapCtrl.pMemVirtAddr)

munmap((void*)gMMapCtrl.pMemVirtAddr, gMMapCtrl.mmapMemSize);

if(gMMapCtrl.memDevFd >= 0)

close(gMMapCtrl.memDevFd);

return 0;

}

linux 內核為用戶提供了一個/dev/mem的驅動程序,使用戶直接訪問系統物理內存成為可能,上面的片段代碼就是利用mmap和/dev/mem建立起直接讀寫系統物理內存的渠道。搞過嵌入式開發的人應該熟悉上面的代碼,利用/dev/mem和mmap導出系統物理地址,免去了用戶虛擬地址到內核邏輯地址的繁瑣拷貝,提升效率。

1、簡單介紹下dev/mem

/dev/mem是linux下的一個字符設備,源文件是kernel/drivers/char/mem.c,有興趣的可以下載內核源碼看看,這個設備文件是專門用來讀寫物理地址用的。里面的內容是所有物理內存的地址以及內容信息。通常只有root用戶對其有讀寫權限。源引網絡資源對/dev/mem是這么評價的“/dev/mem是個好玩的東西,你竟然可以直接訪問物理內存,這在linux下簡直太神奇了,就想一個小偷想偷銀行,可是發現銀行戒備森嚴,正在小偷苦無對策的時候,突然發現銀行有個后門,而且這個后門直通銀行的金庫。”

2、mmap驅動實現時注意事項

曾經在寫某板卡的pcie驅動時,需要mmap出映射到pcie總線地址的對應的物理內存地址,代碼就不貼了,說下出的問題。在驅動加載上后,調用mmap出現了下面的錯誤,具體什么原因還是沒搞清楚,沒時間仔細研究了,工作不等人啊。

dspc868x_pcie_ep 0000:04:00.0: vma->vm_start: 0x4024a000

dspc868x_pcie_ep 0000:04:00.0: vma->vm_end: 0x4024b000

dspc868x_pcie_ep 0000:04:00.0: vma->vm_pgoff: 0x20000

dspc868x_pcie_ep 0000:04:00.0: Mapping 0x1000 bytes from address 0x20000000 success

Unhandled fault: Precise External Abort on non-linefetch (0x1018) at 0x4024a000

參考了別人寫的其他設備驅動程序,在我的驅動實現mmap代碼中添加如下的選項,禁止高速緩存選項,上面的錯誤就解決了。有對這部分特別熟悉的歡迎與我交流,指導下,謝謝。

vma->vm_flags |= VM_WRITE;

vma->vm_flags |= VM_RESERVED;

vma->vm_page_prot = (__pgprot(pgprot_val(pgprot_noncached(vma->vm_page_prot)) | (L_PTE_WRITE|L_PTE_DIRTY)));

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值