linux 内存映射_第1页
linux 内存映射_第2页
linux 内存映射_第3页
linux 内存映射_第4页
linux 内存映射_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Linux的内存映射在讲解内存映射之前,不得不去探讨Linux内存管理方面的知识。需要说明的是,我们并不需要深入的理解Linux虚拟内存才能去实现Linux的内存映射,所以对于Linux内存管理方面的知识也仅限于最基础的概念。一、Linux的内存管理Linux的内存管理子系统是采用请求调页式的虚拟存储器技术实现的,有关虚拟存储器方面的知识可以参考深入理解计算机系统第二版的第9章内容,在这里就不做说明。1、Linux进程的虚拟空间及其划分在32位硬件平台上,Linux的逻辑地址为32位,因此,每个进程的虚拟地址空间为4GB,在4GB的空间中,操作系统占用了高端的1GB,而低端的3GB则留给用户程

2、序使用。如下图所示:1)Linux内核虚拟存储器Linux中1GB的内核虚拟存储器空间又被划分为物理内存映射区、虚拟内存分配区、高端页面映射区、专用页面映射区和系统保留映射区这几个区域。 一般情况下,物理内存映射区最大长度为896MB,系统的物理内存被顺序映射到物理内存映射区中。当系统物理内存大于896MB时,超过系统物理内存的那部分内存称为高端内存(小于896MB的系统物理内存称为常规内存),内核在存取高端内存时必须将它们映射到高端内存映射区中。下图可以反映出Linux内核虚拟存储器与物理内存之间的映射关系。注意:物理内存中0896MB区域通常由内核使用,当然内核不用时用户程序可以使用;89

3、6MB以上的区域通常由用户程序来使用。2)Linux用户虚拟存储器Linux用户虚拟存储器总是通过页表访问内存,决不会直接访问。如下图所示:2、进程空间的描述内核为系统中的每个进程维护一个单独的任务结构task_struct。任务结构中的元素包含或者指向内核运行该进程所需要的所有信息(例如,PID、指向用户栈的指针、可执行目标文件的名字以及程序计数器)。task_struct中的一个条目指向mm_struct,它描述进程使用的地址空间,我们感兴趣的两个字段是pgd和mmap,其中pgd指向第一级页表(页全局目录)的基址,而mmap指向一个vm_area_struct(区域结构)的链表,每个vm

4、_area_struct结构描述的是进程的一个用户区。如下图所示:二、Linux的内存映射当可执行文件准备运行时,可执行文件的内容仅仅映射到了对应进程虚拟地址空间中,而并没有调入物理内存。当程序开始运行并使用到这部分时,Linux才通过缺页中断把它们从磁盘上调入内存。这种将文件连接到进程虚拟地址空间的过程称为内存映射。1、vm_area_struct结构structvm_area_structstructmm_struct*vm_mm;/*所处的地址空间*/unsignedlongvm_start;/*开始的虚拟地址*/unsignedlongvm_end;/*结束的虚拟地址*/pgprot_

5、tvm_page_prot;/*访问权限*/unsignedlongvm_flags;/*标志,VM_IO和VM_RESERVED等*/操作VMA的函数集structvm_operations_struct*vm_ops;unsignedlongvm_pgoff;/*偏移(页帧号)*/structfile*vm_file;/*指向该区域(如果存在的话)相关联的file结构指针*/void*vm_private_data;/*驱动程序用来保存自身信息的成员*/;vm_operations_struct结构的定义如下:structvm_operations_struct/打开VMA的函数void(

6、*open)(structvm_area_struct*area);/关闭VMA的函数void(*close)(structvm_area_struct*area);/访问的页不在内存时调用structpage*(*nopage)(structvm_area_struct*area,unsignedlongaddress,int*type);unsignedlong(*nopfn)(structvm_area_struct*area,unsignedlongaddress);/驱动程序不必实现populate方法int(*populate)(structvm_area_struct*area,

7、unsignedlongaddress,unsignedlonglen,pgprot_tprot,unsignedlongpgoff,intnonblock);2、内存映射一般情况下,用户空间是不可能也不应该直接访问设备的,但是,设备驱动程序中可实现mmap()函数,这个函数可使得用户空间能直接访问设备的物理地址。实际上,mmap()实现了这样的一个映射过程,它将用户空间的一段内存与设备内存关联,当用户访问用户空间的这段地址范围时,实际上会转化为对设备的访问。3、mmap设备操作mmap方法是file_operations结构的一部分,mmap设备方法所需要做到就是建立虚拟地址到物理地址的页表

8、。执行mmap系统调用时将调用该方法。使用mmap,内核在调用实际函数之前,就能完成大量的工作,因此该方法的原型与系统调用有着很大的不同。系统调用有着以下的声明:caddr_tmmap(caddr_taddr,size_tlen,intprot,intflags,intfd,off_toffset);addr:指定文件应被映射到用户空间的起始地址,这样,选择起始地址的任务将由内核完成,而函数的返回值就是映射到用户空间的地址。其类型caddr_t实际上就是void*。len:映射到调用用户空间的字节数,它从被映射文件开头offset个字节开始算起,offset参数一般设为0,表示从文件头开始映射

9、。prot:指定访问权限,PROT_READ(可读)、PROT_WRITE(可写)、PROT_EXEC(可执行)和PROT_NONE(不可访问)。flags:MAP_SHARED,MAP_PRIVATE,MAP_FIXED,其中,MAP_SHARED,MAP_PRIVATE必选其一,而MAP_FIXED则不推荐使用。fd:为文件描述符,一般由open()返回,fd也可以指定为-1,此时需指定flags参数中的MAP_ANON,表明进行的是匿名映射。但是文件操作声明如下:int(*mmap)(structfile*,structvm_area_struct*);vma包含了用于访问设备的虚拟地址

10、的信息,因此大量的工作由内核完成。为了执行mmap,驱动程序只需要为该地址返回建立合适的页表,并将vma-vm_ops替换为一系列的新操作就可以了。注意:当用户调用mmap()的时候,内核会进行如下的处理:在进程的虚拟空间查找一块VMA。将这块VMA进行映射。如果设备驱动程序或者文件系统的file_operations定义了mmap()操作,则调用它。将这个VMA插入进程的VMA链表中。有两种建立页表的方法:使用remap_pfn_range函数一次全部建立;或者通过nopageVMA方法每次建立一个页表。本文只考虑第一种情况。使用remap_pfn_rangeremap_pfn_range负

11、责为一段物理地址建立新的页表,它有如下的原型:intremap_pfn_range(structvm_area_struct*vma,unsignedlongfrom,unsignedlongto,unsignedlongsize,pgprot_tprot)vma:虚拟内存区域,在一定范围内的页将被映射到该区域内。from:表示内存映射开始处的虚拟地址。to:虚拟地址应该映射到的物理地址的页帧号。size:以字节为单位,被重新映射的区域大小。prot:新页所要求的保护属性。三、驱动程序代码#include#include#include/*MKDEV*/#include/*printk*/#i

12、nclude/*file_operations*/#include/*cdev*/#include/*vm_area_struct*/#include/*PAGE_SHIFT*/#defineMAX_SIMPLE_DEV1staticintsimple_major=0;/*定义主设备号*/打开设备文件时被调用staticintsimple_open(structinode*inode,structfile*filp)return0;/关闭设备文件时被调用staticintsimple_release(structinode*inode,structfile*filp)return0;/VMA打

13、开函数voidsimple_vma_open(structvm_area_struct*vma)printk(KERN_NOTICESimpleVMAopen,virt%lx,phys%lxn,vma-vm_start,vma-vm_pgoffvm_start,vma-vm_pgoff,vma-vm_end-vma-vm_start,vma-vm_page_prot)return-EAGAIN;/填充VMA结构体中的vm_operations_struct指针vma-vm_ops=&simple_remap_vm_ops;/*对simple_vma_open函数的显示调用,*/simple_v

14、ma_open(vma);return0;/定义文件操作结构体staticstructfile_operationssimple_remap_ops=.owner=THIS_MODULE,.open=simple_open,.release=simple_release,.mmap=simple_remap_mmap,;staticvoidsimple_setup_cdev(structcdev*dev,intminor,structfile_operations*fops)interr,devno=MKDEV(simple_major,minor);/静态初始化cdevcdev_init(d

15、ev,fops);dev-owner=THIS_MODULE;/注册设备err=cdev_add(dev,devno,1);if(err)printk(KERN_NOTICEError%daddingsimple%d,err,minor);staticstructcdevSimpleDevsMAX_SIMPLE_DEV;/*静态的定义两个设备*/staticintsimple_init(void)intresult;dev_tdev=MKDEV(simple_major,0);/*得到设备号*/if(simple_major)result=register_chrdev_region(dev,

16、2,simple);/*静态的分配设备号*/elseresult=alloc_chrdev_region(&dev,0,2,simple);/*动态的分配设备号*/simple_major=MAJOR(dev);/*得到主设备号*/if(result0)printk(KERN_NOTICEsimple:unabletogetmajor%dn,simple_major);returnresult;/设置两个设备simple_setup_cdev(SimpleDevs,0,&simple_remap_ops);return0;staticvoidsimple_cleanup(void)cdev_d

17、el(SimpleDevs);/*注销字符设备*/unregister_chrdev_region(MKDEV(simple_major,0),2);/*释放设备号*/module_init(simple_init);module_exit(simple_cleanup);MODULE_AUTHOR(chenqi);MODULE_LICENSE(GPL);四、测试程序代码#include#include/*mmap*/#include/*stderr*/intmain(intargc,char*argv)char*fname;FILE*f;unsignedlongoffset,len;void*address;/用于判断输入的方式是否正确if(argc!=4|sscanf(argv2,%li,&offset)!=1|sscanf(argv3,%li,&len)!=1)fprintf(stderr,%s:Usage%sn,argv0,argv0);exit(1);fname=argv1;/*表示设备名*/if(!(f=fopen(fname,r)/*打开设备文件*/fprintf(stderr,%s:%s:%sn,argv0,fname,strerror(errno);exit(1);/将设备地址映射到用户空间address=mmap(0,len,PROT_READ,MAP

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论