/dev/mem可没那么简单

/dev/mem可没那么简单

这几天研究了下/dev/mem。发现功能非常奇妙,通过mmap能够将物理地址映射到用户空间的虚拟地址上。在用户空间完毕对设备寄存器的操作,于是上网搜了一些/dev/mem的资料。

网上的说法也非常统一,/dev/mem是物理内存的全映像,能够用来訪问物理内存,一般使用方法是open("/dev/mem",O_RDWR|O_SYNC),接着就能够用mmap来訪问物理内存以及外设的IO资源,这就是实现用户空间驱动的一种方法。
用户空间驱动听起来非常酷。可是对于/dev/mem,我认为没那么简单,有2个地方引起我的怀疑:
(1)网上资料都说/dev/mem是物理内存的全镜像。这个概念非常含糊,/dev/mem究竟能够完毕哪些地址的虚实映射?
(2)/dev/mem看似非常强大。可是这也太危急了,黑客全然能够利用/dev/mem对kernel代码以及IO进行一系列的非法操作,后果不可预測。难道内核开发人员们没有意识到这点吗?


网上资料说法都非常泛泛,仅仅对mem设备的使用进行说明,没有对这些问题进行深究。

要搞清这一点,我认为还是从/dev/mem驱动開始下手。



參考内核版本号:3.4.55 
參考平台:powerpc/arm

mem驱动在drivers/char/mem.c,mmap是系统调用。产生软中断进入内核后调用sys_mmap。终于会调用到mem驱动的mmap实现函数。

来看下mem.c中的mmap实现:


         
         
         
         
  1. static int mmap_mem(struct file *file, struct vm_area_struct *vma)
  2. {
  3. size_t size = vma->vm_end - vma->vm_start;
  4. if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
  5. return -EINVAL;
  6. if (!private_mapping_ok(vma))
  7. return -ENOSYS;
  8. if (!range_is_allowed(vma->vm_pgoff, size))
  9. return -EPERM;
  10. if (!phys_mem_access_prot_allowed(file, vma->vm_pgoff, size,
  11. &vma->vm_page_prot))
  12. return -EINVAL;
  13. vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
  14. size,
  15. vma->vm_page_prot);
  16. vma->vm_ops = &mmap_mem_ops;
  17. /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
  18. if (remap_pfn_range(vma,
  19. vma->vm_start,
  20. vma->vm_pgoff,
  21. size,
  22. vma->vm_page_prot)) {
  23. return -EAGAIN;
  24. }
  25. return 0;
  26. }
vma是内核内存管理非常重要的一个结构体。
其结构成员中start end代表要映射到的用户空间虚拟地址范围。用户空间的动态映射是以PAGE_SIZE也就是4K为一页,
vma_pgoff是要映射的物理地址。vma_page_prot代表该页的权限。


这些成员的赋值是在调用详细驱动的mmap实现函数之前。在sys_mmap中进行的。
在mmap_mem最后调用remap_pfn_range,该函数完毕指定物理地址与用户空间虚拟地址页表的建立。
remap_pfn_range參数中vma->vm_pgoff即代表要映射的物理地址,并没有范围限制仅能够操作内存。
mmap系统调用的函数定义例如以下:
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
addr指定要映射到的虚拟地址。写NULL则有sys_mmap来分配该虚拟地址。
mmap參数与mem_mmap參数对应关系例如以下:
prot      ===> vma->vma_page_prot
offset    ===> vma->vma_pgoff
length    ===> size


从刚才分析的mem_mmap流程来看,能够得出一个简单的结论:
mem_mmap能够映射整个处理器的地址空间。而不单单是内存。这里要说明的是,地址空间不等于内存空间。站在处理器角度看。地址空间指处理器总线上的全部可寻址空间。除了内存,还有外设的IO空间。以及其它总线映射过来的mem(如PCI)
我的理解。mem_mmap全然能够映射0-0xffffffff的全部物理地址(填TLB页表完毕映射)。但前提是保证该物理地址是真实有效的,也就是处理器訪问该总线物理地址能够获取有效数据。
所以如今看来mmap /dev/mem,仅仅要确定我们处理器的地址空间分布,就能够将我们须要的地址映射到用户空间进行操作。
假设地址不是一个有效物理地址(处理器地址空间分布中该地址没用)。mmap建立该物理地址与用户空间虚拟地址的映射。填TLB,CPU经过TLB翻译后去訪问该不存在的物理地址訪问就有可能导致CPU挂掉。


这也就解释了我第一个疑问,可是kernel的安全机制不会同意用户这么肆无忌惮的操作。接着来看remap_pfn_range之前mmap_mem怎样进行防护。

首先是valid_mmap_phys_addr_range,检查该物理地址是否是一个有效的mmap地址。假设平台定义了ARCH_HAS_VALID_PHYS_ADDR_RANGE则会实现该函数,
arm中定义并实现了该函数,在arch/arm/mm/mmap.c中,例如以下:


         
         
         
         
  1. /*
  2. * We don't use supersection mappings for mmap() on /dev/mem, which
  3. * means that we can't map the memory area above the 4G barrier into
  4. * userspace.
  5. */
  6. int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
  7. {
  8. return !(pfn + (size >> PAGE_SHIFT) > 0x00100000);
  9. }
该函数确定mmap的范围是否超过4G,超过4G则为无效物理地址,这样的情况用户空间一般不会出现。


而对于powerpc,平台未定义ARCH_HAS_VALID_PHYS_ADDR_RANGE,所以valid_mmap_phys_addr_range在mem.c中定义为空函数,返回1 表示该物理地址一直有效。
物理地址有效。不会返回-EINVAL。继续往下走。

接下来是private_mapping_ok,对于有MMU的CPU,实现例如以下:

         
         
         
         
  1. static inline int private_mapping_ok(struct vm_area_struct *vma)
  2. {
  3. return 1;
  4. }
MMU的权限管理能够支持私有映射,所以该函数一直成功。

接下来是一个最为关键的检查函数range_is_allowed。定义例如以下:

         
         
         
         
  1. #ifdef CONFIG_STRICT_DEVMEM
  2. static inline int range_is_allowed(unsigned long pfn, unsigned long size)
  3. {
  4. u64 from = ((u64)pfn) << PAGE_SHIFT;
  5. u64 to = from + size;
  6. u64 cursor = from;
  7. while (cursor < to) {
  8. if (!devmem_is_allowed(pfn)) {
  9. printk(KERN_INFO
  10. "Program %s tried to access /dev/mem between %Lx->%Lx.\n",
  11. current->comm, from, to);
  12. return 0;
  13. }
  14. cursor += PAGE_SIZE;
  15. pfn++;
  16. }
  17. return 1;
  18. }
  19. #else
  20. static inline int range_is_allowed(unsigned long pfn, unsigned long size)
  21. {
  22. return 1;
  23. }
  24. #endif
能够看出假设不打开CONFIG_STRICT_DEVMEM,range_is_allowed是返回1,表示该物理地址范围是被同意的。查看kconfig文件(在对应平台文件夹下。如arch/arm/Kconfig.debug中)找到CONFIG_STRICT_DEVMEM说明例如以下


         
         
         
         
  1. config STRICT_DEVMEM
  2. def_bool y
  3. prompt "Filter access to /dev/mem"
  4. help
  5. This option restricts access to /dev/mem. If this option is
  6. disabled, you allow userspace access to all memory, including
  7. kernel and userspace memory. Accidental memory access is likely
  8. to be disastrous.
  9. Memory access is required for experts who want to debug the kernel.
  10. If you are unsure, say Y.
该选项menuconfig时在kernel hacking文件夹下。
依据说明能够理解。CONFIG_STRICT_DEVMEM是严格的对/dev/mem訪问检查,假设关掉该选项,用户就能够通过mem设备訪问全部地址空间(依据对我提出的第一个问题理解,这里memory应该理解为地址空间)。该选项对于调试内核有帮助。


假设打开该选项,内核就会对mem设备訪问加以检查。检查函数就是range_is_allowed。


range_is_allowed函数对要检查的物理地址范围以4K页为单位,一页一页的调用devmem_is_allowed。假设不同意,则会进行打印提示。并返回0,表示该物理地址范围不被同意



来看devmem_is_allowed.该函数是平台相关函数,只是arm跟powerpc的实现相差不大,以arm的实现为例。

在arch/arm/mm/mmap.c中。


         
         
         
         
  1. /*
  2. * devmem_is_allowed() checks to see if /dev/mem access to a certain
  3. * address is valid. The argument is a physical page number.
  4. * We mimic x86 here by disallowing access to system RAM as well as
  5. * device-exclusive MMIO regions. This effectively disable read()/write()
  6. * on /dev/mem.
  7. */
  8. int devmem_is_allowed(unsigned long pfn)
  9. {
  10. if (iomem_is_exclusive(pfn << PAGE_SHIFT))
  11. return 0;
  12. if (!page_is_ram(pfn))
  13. return 1;
  14. return 0;
  15. }
首先iomem_is_exclusive检查该物理地址是否被独占保留,实现例如以下:


         
         
         
         
  1. #ifdef CONFIG_STRICT_DEVMEM
  2. static int strict_iomem_checks = 1;
  3. #else
  4. static int strict_iomem_checks;
  5. #endif
  6. /*
  7. * check if an address is reserved in the iomem resource tree
  8. * returns 1 if reserved, 0 if not reserved.
  9. */
  10. int iomem_is_exclusive(u64 addr)
  11. {
  12. struct resource *p = &iomem_resource;
  13. int err = 0;
  14. loff_t l;
  15. int size = PAGE_SIZE;
  16. if (!strict_iomem_checks)
  17. return 0;
  18. addr = addr & PAGE_MASK;
  19. read_lock(&resource_lock);
  20. for (p = p->child; p ; p = r_next( NULL, p, &l)) {
  21. /*
  22. * We can probably skip the resources without
  23. * IORESOURCE_IO attribute?
  24. */
  25. if (p->start >= addr + size)
  26. break;
  27. if (p->end < addr)
  28. continue;
  29. if (p->flags & IORESOURCE_BUSY &&
  30. p->flags & IORESOURCE_EXCLUSIVE) {
  31. err = 1;
  32. break;
  33. }
  34. }
  35. read_unlock(&resource_lock);
  36. return err;
  37. }
假设打开了CONFIG_STRICT_DEVMEM,iomem_is_exclusive遍历iomem_resource链表,查看要检查的物理地址所在resource的flags,假设是bug或者exclusive。则返回1,表明该物理地址是独占保留的。

据我了解,iomem_resource是来表征内核iomem资源的链表。

对于外设的IO资源,kernel中使用platform device机制来注冊平台设备(platform_device_register)时调用insert_resource将该设备对应的io资源插入到iomem_resource链表中。


假设我要对某外设的IO资源进行保护。防止用户空间訪问。能够将其resource的flags置位exclusive就可以。

只是我查看我平台支持包里的全部platform device的resource。flags都没有置位exclusive或者busy。

假设我映射的物理地址范围是外设的IO。检查能够通过。

对于内存的mem资源,怎样注冊到iomem_resource链表中。内核代码中我还没找到详细的位置,只是iomem在proc下有对应的表征文件。能够cat /proc/iomem。


依据我的实际操作測试。内存资源也都没有exclusive。所以假设我映射地址是内存。检查也能够通过。




所以这里iomem_is_exclusive检查通常是通过的。接下来看page_is_ram。看devmem_is_range的逻辑,假设地址是ram地址。则该地址不被同意。page_is_ram也是平台函数,查看powerpc的实现例如以下。



         
         
         
         
  1. int page_is_ram(unsigned long pfn)
  2. {
  3. #ifndef CONFIG_PPC64 /* XXX for now */
  4. return pfn < max_pfn;
  5. #else
  6. unsigned long paddr = (pfn << PAGE_SHIFT);
  7. struct memblock_region *reg;
  8. for_each_memblock(memory, reg)
  9. if (paddr >= reg->base && paddr < (reg->base + reg->size))
  10. return 1;
  11. return 0;
  12. #endif
  13. }
  14. max_pfn赋值在在do_init_bootmem中。例如以下.
  15. void __ init do_init_bootmem(void)
  16. {
  17. unsigned long start, bootmap_pages;
  18. unsigned long total_pages;
  19. struct memblock_region *reg;
  20. int boot_mapsize;
  21. max_low_pfn = max_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT;
  22. total_pages = (memblock_end_of_DRAM() - memstart_addr) >> PAGE_SHIFT;
max_pfn代表了内核lowmem的页个数,lowmem在内核下静态线性映射。系统启动之初完毕映射之后不会修改。读写效率高。内核代码都是跑在lowmem。
lowmem大小我们能够通过cmdline的“mem=”来指定。



这里就明确了假设要映射的物理地址在lowmem范围内,也是不同意被映射的。

这样range_is_allowed就分析完了。exclusive的iomem以及lowmem范围内的物理地址是不同意被映射的。

接下来phys_mem_access_prot_allowed实现为空返回1,没有影响。

phys_mem_access_prot确定我们映射页的权限,该函数也是平台函数,以powerpc实现为例,例如以下:


         
         
         
         
  1. pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
  2. unsigned long size, pgprot_t vma_prot)
  3. {
  4. if (ppc_md.phys_mem_access_prot)
  5. return ppc_md.phys_mem_access_prot(file, pfn, size, vma_prot);
  6. if (!page_is_ram(pfn))
  7. vma_prot = pgprot_noncached(vma_prot);
  8. return vma_prot;
  9. }
假设有平台实现的phys_mem_access_prot,则调用之。

假设没有。对于不是lowmem范围内的物理地址。权限设置为uncached。



以上的检查完毕,最后调用remap_pfn_range完毕页表设置。



所以假设打开CONFIG_STRICT_DEVMEM,mem驱动会对mmap要映射的物理地址进行范围和位置的检查然后才进行映射。检查条件例如以下:
(1)映射范围不能超过4G。
(2)该物理地址所在iomem不能exclusive.
(3)该物理地址不能处在lowmem中。

所以说对于网上给出的各种利用/dev/mem来操作内存以及寄存器的文章。假设操作范围在上述3个条件内,内核必须关闭CONFIG_STRICT_DEVMEM才行。

这样对于mem设备我的2个疑问算是攻克了。

查看mem.c时我还看到了另外一个有趣的设备kmem。这个设备mmap的是哪里的地址,网上的说法是内核虚拟地址。这个说法我不以为然,这里记录下我的想法。

假设内核打开CONFIG_KMEM。则会创建kmem设备。它与mem设备主要区别在mmap的实现上。kmem的mmap实现例如以下:

         
         
         
         
  1. #ifdef CONFIG_DEVKMEM
  2. static int mmap_kmem(struct file *file, struct vm_area_struct *vma)
  3. {
  4. unsigned long pfn;
  5. /* Turn a kernel-virtual address into a physical page frame */
  6. pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT;
  7. /*
  8. * RED-PEN: on some architectures there is more mapped memory than
  9. * available in mem_map which pfn_valid checks for. Perhaps should add a
  10. * new macro here.
  11. *
  12. * RED-PEN: vmalloc is not supported right now.
  13. */
  14. if (!pfn_valid(pfn))
  15. return -EIO;
  16. vma->vm_pgoff = pfn;
  17. return mmap_mem(file, vma);
  18. }
  19. #endif
引起我注意的是__pa,完毕内核虚拟地址到物理地址的转换,最后调用mmap_mem,简单一看kmem的确是映射的内核虚拟地址。
可是搞清楚__pa的实现,我就不这么认为了。

以powerpc为例。在arch/powerpc/include/asm/page.h,定义例如以下:


         
         
         
         
  1. #define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + VIRT_PHYS_OFFSET))
  2. #define __pa(x) ((unsigned long)(x) - VIRT_PHYS_OFFSET)
  3. ....
  4. #define VIRT_PHYS_OFFSET (KERNELBASE - PHYSICAL_START)
内核中定义了4个变量来表示内核一些主要的物理地址和虚拟地址,例如以下:
KERNELBASE     内核的起始虚拟地址,我的是0xc0000000
PAGE_OFFSET    低端内存的起始虚拟地址,通常是0xc0000000
PHYSICAL_START 内核的起始物理地址。我的是0x80000000
MEMORY_START   低端内存的起始物理地址。我的是0x80000000

内核在启动过程中对于lowmem的静态映射。就是以上述的物理地址和虚拟地址的差值进行线性映射的。
所以__pa __va转换的是线性映射的内存部分,也就是lowmem。
所以kmem映射的是lowmem。假设我的cmdline參数中mem=512M,这就意味着通过kmem的mmap我最多能够訪问内核地址空间開始的512M内存。


对于超过lowmem范围,訪问highmem。假设使用__pa訪问,因为highmem是动态映射的,其映射关系不是线性的那么简单了,依据__pa获取的物理地址与我们想要的内核虚拟地址是不正确应的。







发布了162 篇原创文章 · 获赞 39 · 访问量 23万+
        

笔记:linux内核内存布局以及/dev/mem

05-09 阅读数 1700

参考一下两篇文章:linux内核内存管理(zone_dmazone_normalzone_highmem)(linuxmemorylayout)/dev/mem可没那么简单学习笔记(以x86为例)li... 博文 来自: steveliu->blog

Linux应用层直接操作GPIO

03-22 阅读数 1万+

Linux用户层直接操作GPIO在一个老手的指导下,应用层可以直接操作GPIO,具体指设置GPIO的输入输出以及输出电平高或者低。这个大大地提高了灵活性,官方的文档有GPIO Sysfs Interf... 博文 来自: Android/Linux的专栏

		
Hello_Linux_001关注
Hello_Linux_001

46篇文章

排名:千里之外

阳光柠檬_关注
阳光柠檬_

239篇文章

排名:2000+

gydtep关注
gydtep

144篇文章

排名:千里之外

kerneler_关注
kerneler_

223篇文章

排名:1000+

linux驱动实践(四)--linux下读写寄存器

12-23 阅读数 1万+

arm裸机下读写寄存器很容易,各个寄存器和内存的地址是单一地址空间,他们是用相同的指令进行读写操作的.而在linux下就要复杂很多,因为linux支持多个体系架构的CPU。比如arm和x86就不一样,... 博文 来自: BaikalHU

请教下:Linux下对IIC总线的从设备的寄存器进行读写操作。

05-17

需要在应用层写一个工具,它能对IIC总线上的从设备的寄存器进行读写操作,比如说: ./demo addr reg :读取从设备地址为addr上的地址为reg的寄存器内的数据 ./demo addr r 论坛

linux环境下执行DD命令把内存中的内容读到磁盘上,提示读取"/dev/mem" 时出错: 不允许的操作!

07-09

在linux环境下,执行dd命令如下,想把内存中的内容保存到硬盘上的某个文件中。但是提示“读取 /dev/mem 出错 ,不允许操作” root@xxxx# dd if=/dev/mem of=mem 论坛

在Linux 中的应用层操作gpio的方法

09-01 阅读数 5302

背景:    由于在调试WiFi驱动模块的时候需要增加一个功能:就是用户按下一个按键就可以,将WiFi的ssid和psk恢复到出场模式。所以这里就需要开辟一个线程去检测按键的状态。第一步首先是用户按下... 博文 来自: 仗劍走天涯


用户空间 mdio 访问

03-21

cpu通过mdio控制bcm phy芯片,怎么从用户空间来对phy芯片进行读写寄存器控制? 在网上搜索的都是通过SIOCGMIIREG这种方式的ioctl来访问的,但是这需要传递interface的n 论坛

Linux PCI/PCI-E设备配置空间读取与修改

03-31 阅读数 9163

Linux PCI/PCI-E设备配置空间读取与修改1 前言 PCI和PCI Express,是计算机常使用的一种高速总线。操作系统中的PCI/PCI-E设备驱动以及操作系统内核,都需要访问PCI及P... 博文 来自: gx19862005的专栏

用户层操作硬件寄存器等(通过/dev/mem)

04-17 阅读数 2275

直接贴代码:#include #include #include #include #include #include #include #define AMLOGIC_NORMAL_BOOT 0x0... 博文 来自: haomcu的专栏

解决Linux内核问题实用技巧之-dev/mem的新玩法

11-20 阅读数 784

/dev/mem里有什么简单来讲,/dev/mem是系统物理内存的映像文件,这里的 “物理内存” 需要进一步解释。物理内存是指我们插在内存槽上的内存条吗?当然是,但物理内...... 博文 来自: 宋宝华

linux板子用户态通过/dev/mem访问物理内存(寄存器,GPIO)

05-10 阅读数 1783

从datasheet中查到IO口寄存器基地址Base Address:0x01C20800PE口的寄存器PE Data Register 偏移offset: 0xA0,那么PE_DAT地址就是0x01... 博文 来自: zmlovelx(帅得不敢出门 程序员群31843264)

linux驱动中读写硬件寄存器(例如__raw_writel)

10-15 阅读数 2018

设备通常会提供一组寄存器来控制设备、读写设备和获取设备状态,即控制寄存器、数据寄存器和状态寄存器。这些寄存器可能位于I/O空间,也可能位于内存空间。当位于I/O空间时,通常被称为I/O端口,位于内存空... 博文 来自: 夏天Alex

ZYNQ7000 #3 - Linux环境下在用户空间使用AXI-DMA进行传输

05-15 阅读数 1533

本文使用Petalinux搭建相关linux环境,在vivado中搭建了一个简单的PS->AXI-DMA->AXI-FIFO->AXI-DMA->PS的测试环路。使用了国外开源... 博文 来自: 里先森

宏CONFIG_STRICT_DEVMEM的作用

06-09 阅读数 1976

/dev/mem的实现在drivers/char/mem.c 中,影响/dev/mem使用的有一个宏CONFIG_STRICT_DEVMEM,如果打开这个宏的话,user space就只能访问rese... 博文 来自: jason的笔记


/dev/mem 的 mmap 分析

03-31 阅读数 908

当用户空间需要实现驱动程序时, 需要操作底层的寄存器. 使用/dev/mem就是一种常用的方式. /dev/mem 一般都是使用其 mmap 函数. 讲底层的寄存器映射到用户空间地址. 下面对 /de... 博文 来自: gngshn - linux fresher

linux 内核读写寄存器操作demo实例

08-22 阅读数 105

void __iomem *mmio; mmio = ioremap_nocache(0xFEB00000, 0x4); if (mmio) { printk("[%s] -------------... 博文 来自: zgp2917的专栏

linux 读取物理寄存器

02-16 阅读数 143

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#i... 博文 来自: weixin_34321977的博客

Linux下读写寄存器

02-15 阅读数 116

arm裸机下读写寄存器很容易,各个寄存器和内存的地址是单一地址空间,他们是用相同的指令进行读写操作的.而在linux下就要复杂很多,因为linux支持多个体系架构的CPU。比如arm和x86就不一样,... 博文 来自: weixin_33947521的博客

中断按键驱动程序

06-01 阅读数 362

#include #include #include #include #include #include #include #include #include #include #include s... 博文 来自: qlexcel的专栏

通过/dev/mem访问物理内存问题!

03-14 阅读数 117

2019独角兽企业重金招聘Python工程师标准>>> ...... 博文 来自: weixin_33738555的博客

linux下有没有工具能看到内存和寄存器的值?

07-12

以前做嵌入式的时候有这样的工具: 例如,d 0x00001000, 就会把这段地址对应的内存值或者寄存器值打印出来 论坛

求大神解答!arm处理器嵌入linux,没有/dev/mem

09-19

如图,在运行spiload的时候报出这样的错误 /dev/mem是制作文件系统时候生成的还是linux内核uImage生成的呢? 求解答~ 论坛

Linux调试备忘录1-- Linux kernel启动后,如何在用户命令行查看和修改寄存器值

04-17 阅读数 2613

Linux kernel启动后,如何在用户命令行查看和修改寄存器值?我们知道Linux kernel启动后,由于memory map的管理,我们是无法... 博文 来自: swallow71701的专栏

linux读写cpu寄存器linux寄存器读linux操作cpu寄存器实例

01-20 阅读数 1784

linux读写cpu寄存器linux寄存器读写linux操作cpu寄存器实例linux应用层读写寄存器代码 QString Mcu::get_cpu_serial_number() { ... 博文 来自: Done Lin的专栏

open("/dev/mem ",O_RDWR | O_SYNC)

07-25 阅读数 6849

【摘要】open(“/dev/mem”,O_RDWR|O_SYNC) 中/dev/mem是物理内存的全映像,可以用来访问物理内存。然后mmap,接着就可以用mmap的地址来访问物理内存,这实际上就是实... 博文 来自: ZP1015

dev/mem

08-10 阅读数 652

之前有一个需求是uboot 将一段key写到memory中,然后要求kernel reserve 这段memory,最后user space 通过打开/dev/mem 来映射这段memory,这样就可... 博文 来自: jason的笔记

SecureCRT的下载、安装( 过程非常详细!!值得查看)

03-03 阅读数 1万+

SecureCRT的下载、安装和破解( 过程非常详细!!值得查看)简单介绍下SecureCRT一、SecureCRT的下载二、SecureCRT的安装简单介绍下SecureCRTSecureCRT是一... 博文 来自: 超Ren专属

Java学习的正确打开方式

01-08 阅读数 28万+

在博主认为,对于入门级学习java的最佳学习方法莫过于视频+博客+书籍+总结,前三者博主将淋漓尽致地挥毫于这篇博客文章中,至于总结在于个人,实际上越到后面你会发现学习的最好方式就是阅读参考官方文档其次... 博文 来自: 程序员宜春的博客

程序员必须掌握的核心算法有哪些?

12-26 阅读数 39万+

由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不知道要怎么回答你,主要取决于你想学习到哪些程度,不过针对这个问题,... 博文 来自: 帅地

                
                                

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

你可能感兴趣的:(/dev/mem可没那么简单)