Linux中通过/dev/mem操控物理地址-阿里云开发者社区

开发者社区> binarydady> 正文

Linux中通过/dev/mem操控物理地址

简介:
+关注继续查看


/dev/mem是物理内存的全映像,可以用来访问物理内存,用mmap来访问物理内存以及外设的IO资源,是实现用户空间驱动的一种方法

我们先用hexedit来看下/dev/mem,hexedit /dev/mem 可以物理内存的信息,当然肉眼是无法看的毕竟是16进制。

00000000   53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  S...S...S...S...

00000010   53 FF 00 F0  53 FF 00 F0  CC E9 00 F0  53 FF 00 F0  S...S.......S...

00000020   A5 FE 00 F0  87 E9 00 F0  53 FF 00 F0  46 E7 00 F0  ........S...F...

00000030   46 E7 00 F0  46 E7 00 F0  57 EF 00 F0  53 FF 00 F0  F...F...W...S...

00000040   22 00 00 C0  4D F8 00 F0  41 F8 00 F0  FE E3 00 F0  "...M...A.......

00000050   39 E7 00 F0  59 F8 00 F0  2E E8 00 F0  D4 EF 00 F0  9...Y...........

00000060   A4 F0 00 F0  F2 E6 00 F0  6E FE 00 F0  53 FF 00 F0  ........n...S...

00000070   ED EF 00 F0  53 FF 00 F0  C7 EF 00 F0  EC 57 00 C0  ....S........W..

00000080   53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  S...S...S...S...

00000090   53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  S...S...S...S...

000000A0   53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  S...S...S...S...

000000B0   53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  S...S...S...S...

000000C0   53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  S...S...S...S...

000000D0   53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  S...S...S...S...

000000E0   53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  S...S...S...S...

000000F0   53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  53 FF 00 F0  S...S...S...S...

不过可以用mmap将/dev/mem 映射出来,然后可以对其读写可以实现用户空间的内核操作。先来说下mmap函数,

void *mmap(void *addr, size_t length, int prot, int flags,

                  int fd, off_t offset);

共6个参数含义分别如下:

l   addr如果为null,那么有内核选择一个映射的地址,如果不为null,那内核会把参数当做映射的提示(映射的地址就在所提示的附近,不会百分百确保的)

l   length表示映射长度

l   prot表示对映射的保护, 可以是可执行,可读,可写或不可访问,PROT_EXEC,PROT_READ,PROT_WRITE,PROT_NONE

l   flag表示是否对其他进程可见,MAP_SHARED表示其他进程可见。

l   fd需要映射的文件描述符

l   offset指向fd的编译

接下去我们用mmap来映射/dev/mem,编写代码如下:

#include<stdio.h>

#include<unistd.h>

#include<sys/mman.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<fcntl.h>

 

int

main ()

{

  unsigned char *map_base;

  FILE *f;

  int n, fd;

 

  fd = open ("/dev/mem", O_RDWR | O_SYNC);

  if (fd == -1)

    {

      printf ("open /dev/mem fail!\n");

      return (-1);

    }

 

  map_base =

    mmap (NULL, 0xff, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x20000);

  if (map_base == 0)

    {

      printf ("NULL pointer!\n");

    }

  else

    {

      printf ("map Successfull!\n");

    }

 

  unsigned long addr;

  unsigned char content;

 

  int i = 0;

  for (; i < 0xf; ++i)

    {

      addr = (unsigned long) (map_base + i);

      content = map_base[i];

      printf ("address: 0x%lx   value: 0x%x\t\t", addr,

              (unsigned int) content);

 

      map_base[i] = (unsigned char) i;

      content = map_base[i];

      printf ("address: 0x%lx   value: 0x%x\t\t", addr,

              (unsigned int) content);

 

      map_base[i] = (unsigned char) i;

      content = map_base[i];

      printf ("address: 0x%lx   new value: 0x%x\n", addr,

              (unsigned int) content);

    }

 

  close (fd);

  munmap (map_base, 0xff);

  return (1);

}

编译后,执行如下:

map Successfull!

address: 0x7fbaafb5e000   value: 0x0         address: 0x7fbaafb5e000   new value: 0x0

address: 0x7fbaafb5e001   value: 0x0         address: 0x7fbaafb5e001   new value: 0x1

address: 0x7fbaafb5e002   value: 0x0         address: 0x7fbaafb5e002   new value: 0x2

address: 0x7fbaafb5e003   value: 0x0         address: 0x7fbaafb5e003   new value: 0x3

address: 0x7fbaafb5e004   value: 0x0         address: 0x7fbaafb5e004   new value: 0x4

address: 0x7fbaafb5e005   value: 0x0         address: 0x7fbaafb5e005   new value: 0x5

address: 0x7fbaafb5e006   value: 0x0         address: 0x7fbaafb5e006   new value: 0x6

address: 0x7fbaafb5e007   value: 0x0         address: 0x7fbaafb5e007   new value: 0x7

address: 0x7fbaafb5e008   value: 0x0         address: 0x7fbaafb5e008   new value: 0x8

address: 0x7fbaafb5e009   value: 0x0         address: 0x7fbaafb5e009   new value: 0x9

address: 0x7fbaafb5e00a   value: 0x0         address: 0x7fbaafb5e00a   new value: 0xa

address: 0x7fbaafb5e00b   value: 0x0         address: 0x7fbaafb5e00b   new value: 0xb

address: 0x7fbaafb5e00c   value: 0x0         address: 0x7fbaafb5e00c   new value: 0xc

address: 0x7fbaafb5e00d   value: 0x0         address: 0x7fbaafb5e00d   new value: 0xd

address: 0x7fbaafb5e00e   value: 0x0       address: 0x7fbaafb5e00e   new value: 0xe

例子将物理地址起始地址0x20000, 长度为0xf映射出来了,然后进行了读写操作。这里0x7fbaafb5e000是mmap函数返回的映射地址。第二次执行的时候,会发现内存中的值已经是上次修改过的值了并非全0.。

       大家可以把0x20000地址改成0x000地址(3G)地址,然后长度改成0xffffff,会出现段错误。系统的内存是段保护的,可以随便修改内存中的值系统是要崩溃的。

       /dev/mem还可以用来检测系统甚至给系统打补丁,为了防止/dev/mem被注入代码,可以设置系统配置选项CONFIG_STRICT_DEVMEM=y

此外还有port和kmem,/dev/port同/dev/mem,不过访问的是I/O端口。

/dev/kmem也同/dev/mem,不过其访问的是虚拟内存而不是物理内存。

 

 


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
从 DevOps 到 Serverless:通过“不用做”的方式解决“如何更高效做”的问题
作者 | 徐进茂(罗离) JAVA 开发工程师  > **导读**:近年来,Serverless 一词越来越热,它已经逐渐成为了一种新型的软件设计架构。和 DevOps 概念提倡的是通过一系列工具和自动化的技术来降低运维的难度,促进研发运维一体化不同, Serverless 更像是一种 NoOps,即通过“不用做”的方式来解决“如何更高效做”的问题。
1186 0
[转]了解如何通过reverse_iterator的base得到iterator
转自:http://blog.csdn.net/shuchao/article/details/3705252 调用reverse_iterator的base成员函数可以产生“对应的”iterator,但这句话有些辞不达意。
543 0
怎么设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程
8466 0
全志 A64 linux 通过设备树写LED驱动(附参考代码)
开发平台 芯灵思Sinlinx A64 内存: 1GB 存储: 4GB详细参数 https://m.tb.cn/h.3wMaSKm开发板交流群 641395230 全志A64设备树结构体 #include <linux/of.
2575 0
嵌入式Linux上通过boa服务器实现cgi/html的web上网【转】
转自:http://blog.csdn.net/tianmohust/article/details/6595996 版权声明:本文为博主原创文章,未经博主允许不得转载。   嵌入式Linux上通过boa服务器实现cgi/html的web上网简介: 第一步 Boa程序的移植 1.下...
1307 0
+关注
binarydady
深入底层,挖掘应用 Problem Shooter/Performance Analyzer
99
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载