接下来就是建立物理页与虚拟页之间的关系,即采用函数remap_pfn_range(),具体的参数如下:

int remap_pfn_range(structvm_area_struct *vma, unsigned long addr,unsigned long pfn, unsigned long size, pgprot_t prot)

1、struct vm_area_struct是一个虚拟内存区域结构体,表示虚拟存储器中的一个内存区域。其中的元素vm_start是指虚拟存储器中的起始地址。

2、addr也就是虚拟存储器中的起始地址,通常可以选择addr = vma->vm_start。

3、pfn是指物理存储器的具体页号,通常通过物理地址得到对应的物理页号,具体采用virt_to_phys(dev->data)>>PAGE_SHIFT.首先将虚拟内存转换到物理内存,然后得到页号。>>PAGE_SHIFT通常为12,这是因为每一页的大小刚好是4K,这样右移12相当于除以4096,得到页号。

4、size区域大小

5、区域保护机制。

返回值,如果成功返回0,否则正数。

测试代码可以直接通过对虚拟内存区域操作,实现不同的操作,如下:

  1. #include<fcntl.h>
  2. #include<unistd.h>
  3. #include<stdio.h>
  4. #include<stdlib.h>
  5. #include<sys/types.h>
  6. #include<sys/stat.h>
  7. #include<sys/mman.h>
  8. #include<string.h>

  9. int main()
  10. {
  11.     int fd;
  12.     char *start;
  13.         
  14.     char buf[2048];
  15.     strcpy(buf,"This is a test!!!!");

  16.     fd = open("/dev/memdev0",O_RDWR);
  17.     
  18.     if(fd == -1)
  19.     {
  20.         printf("Error!!\n");
  21.         exit(-1);
  22.     }
  23.     /*创建映射*/
  24.     start = mmap(NULL,2048,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
  25.     /*必须检测是否成功*/
  26.     if(start == -1)
  27.     {
  28.         printf("mmap error!!!\n");
  29.         exit(-1);
  30.     }

  31.     strcpy(start,buf);

  32.     printf("start = %s,buf = %s\n",start,buf);

  33.     strcpy(start,"Test is Test!!!\n");

  34.     printf("start = %s,buf = %s\n",start,buf);
  35.     /**/
  36.     strcpy(buf,start);
  37.  
  38.     printf("start = %s,buf=%s\n",start,buf);
  39.     /*取消映射关系*/
  40.     munmap(start,2048);
  41.     /*关闭文件*/
  42.     close(fd);

  43.     exit(0);
  44. }

经过测试,成功得到了驱动。