Linux读写物理内存

来源:互联网 发布:邮箱数据迁移 编辑:程序博客网 时间:2024/04/27 23:23

一、基础知识

1.打开设备文件:    mem是一个字符设备文件,是计算机主存的一个映像。通常只有root用户对其有读写权限。因此只有root用户能进行这些操作。    如果要打开设备文件/dev/mem,需要系统调用open()函数,作用是打开一个文件或设备,其函数原型为:    int open(const char *path, int flags);    返回值:如果操作成功则返回一个文件描述符,否则返回-1    形  参:            path      被打开文件的路径即文件名描述。            flags     文件的访问模式描述,可常用的选项见下:                        O_RDONLY        只读方式                        O_WRONLY        只写方式                        O_RDWR          可读写方式    说  明:此函数用于打开文件或者设备    头文件:#include <fcntl.h> #include <stat.h>  定义在/usr/include/fcntl.h中2.读取内存映像:    内存映像其实在内存中创建一个与外存中文件完全相同的映像。用户可以将整个文件映射到内存中,也可以将文件的一部分映射到内存中。    使用操作内存的方法对文件进行操作。系统会将内存映像文件所做的改动反映到真实文件中去。    在内存映像I/O的实现过程中需要用到一些系统调用:    首先是创建内存映像文件的系统调用mmap()函数,其函数原型为:    void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);    返回值:成功时,返回值为指向内存映像起始地址的指针,当调用失败时,返回值为-1    形  参:            start      一个void指针,表示希望将文件映射到此指针指向的位置,通常为NULL。            length     定义内存映像文件所占用的内存空间大小,以字节计。            prot       内存映像文件的安全属性,注意和open函数中的flags属性保持一致。它的可使用的选项如下:                          Flags                          含义                        PROT_EXEC       被映像内存可能含义机器码,可被执行                        PROT_NONE       映像内存不允许访问                        PROT_READ       映像内存可读                        PROT_WRITE      映像内存可写            flags      内存映像的标志,选项如下:                          Flags                                   含义                        MAP_FIXED       指定映射起始地址,如果由start和len指定的内存区重叠于现存的映射空间,重叠部分将会被丢弃。                                        如果指定的起始地址不可用,操作将会失败。并且起始地址必须落在页的边界上。                        MAP_SHARED      与其它所有映射这个对象的进程共享映射空间。对共享区的写入,相当于输出到文件。                                        直到msync()或者munmap()被调用,文件实际上不会被更新。                         MAP_PRIVATE     建立一个写入时拷贝的私有映射。内存区域的写入不会影响到原文件。                                        这个标志和以上标志是互斥的,只能使用其中一个。                         MAP_NORESERVE   不要为这个映射保留交换空间。当交换空间被保留,对映射区修改的可能会得到保证。                                        当交换空间不被保留,同时内存不足,对映射区的修改会引起段违例信号。                        MAP_LOCKED      锁定映射区的页面,从而防止页面被交换出内存。                         MAP_GROWSDOWN   用于堆栈,告诉内核VM系统,映射区可以向下扩展。                        MAP_ANONYMOUS   匿名映射,映射区不与任何文件关联。                        MAP_ANON        MAP_ANONYMOUS的别称,不再被使用。                         MAP_FILE        兼容标志,被忽略。                         MAP_32BIT       将映射区放在进程地址空间的低2GB,MAP_FIXED指定时会被忽略。                                        当前这个标志只在x86-64平台上得到支持。                        MAP_POPULATE    为文件映射通过预读的方式准备好页表。随后对映射区的访问不会被页违例阻塞。                         MAP_NONBLOCK    仅和MAP_POPULATE一起使用时才有意义。不执行预读,只为已存在于内存中的页面建立页表入口。            fd         要映射的文件的描述符。            offset     所映射的数据内容 距离文件头的偏移量。    说  明:此函数用于将一个文件或它的一部分映射到内存中。    头文件:#include <sys/mman.h> #include <sys/types.h>  函数定义在/usr/include/sys/mman.h3.撤销内存映像的修改    另外我们使用完内存映像文件后,要用系统调用函数munmap()函数来撤销,其函数原型为:    int munmap(void *start, size_t length);    返回值:成功时,返回值为0;调用失败时返回值为 -1,并将errno设置为相应值。    形  参:            start      要撤销的内存映像文件的起始地址。            length     要撤销的内存映像文件的大小。    说  明:当进程结束或利用exec相关函数来执行其他程序时,映射内存会自动解除,但关闭对应的文件描述词时不会解除映射。    头文件:#include <sys/mman.h>4.将内存映像的改动保存到外存中    最后,如果我们要将内存映像的改动保存到外存中,还需要系统调用msync()函数,其函数原型为:    int msync(const void *start,size_t length,int flags);    返回值:成功时,返回值为0;调用失败时返回值为 -1,并将errno设置为相应值。    形  参:            start      要保存到外存的那些源文件的起始地址。            length     表示内存映像文件的大小。            flags      设置了函数的相应操作,其具体选项如下:                          Flags                      含义                        MS_ASYNC           调用一个写操作并返回                        MS_INVALIDATE      映像到相同文件的内存映像数据更新                        MS_SYNC            完成写操作后函数返回    说  明:进程在映射空间的对共享内容的改变并不直接写回到磁盘文件中,往往在调用munmap()后才执行该操作。            可以通过调用msync()函数来实现磁盘文件内容与共享内存区中的内容一致,即同步操作。    头文件:#include <sys/mman.h>5.通过/dev/mem设备文件和mmap系统调用,可以将线性地址描述的物理内存映射到进程的地址空间,然后就可以直接访问这段内存了。

二、一个例子

#include <stdio.h>#include <unistd.h>#include <sys/mman.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int main (int args, char* arg[]){    int i;    int fd;    char* mem;    char *buff = "HELLO";    //open /dev/mem with read and write mode    if((fd = open ("/dev/mem", O_RDWR)) < 0)    {        perror ("open error");        return -1;    }    //map physical memory 0-10 bytes    mem = mmap (0, 10, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);    if (mem == MAP_FAILED)    {        perror ("mmap error:");        return 1;    }    //Read old value    for (i = 0; i < 5; i++)    {        printf("\nold mem[%d]:%d", i, mem[i]);    }    printf(The value is 0x%x\n, *((int *)mem));    //write memory    memcpy(mem, buff, 5);    //Read new value    for (i = 0; i<5 ; i++)    {        printf("\nnew mem[%d]:%c", i, mem[i]);    }    printf("\n");    munmap (mem, 10); //destroy map memory    close (fd);   //close file    return 0;}
原创粉丝点击