一、基础知识:

  1.   设备文件:

  mem是一个字符设备文件,是计算机主存的一个影象。通常只有root用户对其有读写权限。因此只有root用户能进行这些操作。

  如果要打开设备文件/dev/mem,需要系统调用open()函数,作用是打开一个文件或设备,其函数原型 为:

#include <fcntl.h>
   #include <stat,h>
   int open(const char *path, int flags);

  open 函数定义在/usr/include/fcntl.h中;如果操作成功则返回一个文件描述符,否则返回-1;其中path是被打开文件的路径即文件名描 述;flags是文件的访问模式描述,可常用的选项见下表:

  flags的取值及其含义 flags        含义

  O_RDONLY                            只读方式

  O_WRONLY                           只写方式

  O_RDWR                                可读写方式

  2.内存映像:

  内存映像其实在内存中创建一个与外存中文件完全相同的映像。用户可以将整个文件映射到内存中,也可以将文件的一部分映射到内存中。使用操作内存的方法对文 件进行操作。系统会将内存映像文件所做的改动反映到真实文件中去。

  在内存映像I/O的实现过程中需要用到一些系统调用:

  首先是创建内存映像文件的系统调用mmap()函数,其函数原型为:

#include <sys/types.h>
   #include <sys/mman.h>
   void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offset);   mmap函数定义在/usr/include/sys/mman.h中;

  此函数用于将一个文件或它的一部分映射到内存中。参数start是一个void指针,表示希望将文件映射到此指针指向的位置,通常为NULL;参数 length定义内存映像文件所占用的内存空间大小,以字节计;参数prot表示内存映像文件的安全属性,它的可使用的选项见表1,注意和open函数中 的flags属性保持一致;参数flags是内存映像的标志,相关的标志见表2;参数fd是要映射的文件的描述符;参数offset表示所映射的数据内容 距离文件头的偏移量。

  当调用成功时,返回值为指向内存映像起始地址的指针;当调用失败时,返回值为-1。

  表1 prot的取值及其含义

  prot                             含义

  PROT_EXEC       被映像内存可能含义机器码,可被执行

  PROT_NONE       映像内存不允许访问

  PROT_READ       映像内存可读

  PROT_WRITE       映像内存可写

  表2 flags的取值及其含义

  Flags                               含义

  MAP_FIXED            若无法在指定位置建立内存映像文件,则出错返回

  MAP_PRIVATE       对内存映像文件所做操作不反映到外存文件中

  MAP_SHARED       对内存映像文件所做操作都将被保存到外存文件中

  另外我们使用完内存映像文件后,要用系统调用函数munmap()函数来撤销,其函数原型为:

  

#include <sys/types.h>
   #include <sys/mman.h>
   int munmap(void *start,size_t length);

  参数start表示要撤销的内存映像文件的起始地址;参数length表示要撤销的内存映像文件的大小。调用成功时,返回值为0;调用失败时返回值为 -1,并将errno设置为相应值。

  最后,如果我们要将内存映像的改动保存到外存中,还需要系统调用msync()函数,其函数原型为:

#include <sys/types.h>
   #include <sys/mman.h>
   int msync(const void *start,size_t length,int flags);

 参数start表示要保存到外存的那些源文件的起始地址;参数length表示内存映像文件的大小;参数flags设置了函数的相应操作,其具体选项见表 3。

  表3 flags的取值及其含义

  flags                                含义

  MS_ASYNC               调用一个写操作并返回

  MS_INVALIDATE      映像到相同文件的内存映像数据更新

  MS_SYNC                  完成写操作后函数返回

  通过/dev/mem设备文件和mmap系统调用,可以将线性地址描述的物理内存映射到进程的地址空间,然后就可以直 接访问这段内存了。

  二、应用实例:

  1.   源代码:

 

/*
   file:       read.c
   function: Read the the first 5 bytes of the memory and then Write it with "HELLO"
   */
   #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]);
   }
   //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;
   }

  2.编译、运行:

  #gcc -o read read.c

http://www.qnr.cn/pc/lin/study/201008/523225.html