博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux设备驱动工程师之路——Linux内存管理机制及mmap方法
阅读量:5942 次
发布时间:2019-06-19

本文共 2273 字,大约阅读时间需要 7 分钟。

Linux设备驱动工程师之路——Linux内存管理机制及mmap方法

K-Style

转载请注明来自于衡阳师范学院08电2  Y-Kee ,QQ:843308498

 

一、重点知识

 

    1. Linux内存管理机制

    Linux 2.6.29内核为每种CPU提供统一的界面,采用四级页面管理构架。来兼容二级、三级、四级管理架构的CPU。通过页式管理机制完成虚拟地址(线性地址)到物理地址的映射。一般每个页大小为4K。cr3寄存器中保存了创建进程时分配的值。

    Linux操作系统采用虚拟内存管理技术,使得每个进程都有独立的进程地址空间,该空间大小是3G,用户看到和接触的都是虚拟地址,无法看到实际的物理地址。利用这种虚拟地址不但能起到保护操作系统的作用,而且更重要的是用户程序可使用比实际物理内存更大的地址空间。

    Linux将4G的虚拟地址空间划分为两个部分——用户空间与内核空间。用户空间从0到0xbfffffff,内核空间从3G到4G。用户进程通常情况下只能访问用户空间的虚拟地址,不能访问内核空间,例外是用户进程通过系统调用访问内核空间。

    每个用户空间是完全独立的,互不想干的。用户空间对应进程,所有每当进程切换,用户空间就会跟着变化。

    实际的物理内存只有当进程真的去访问新获取的虚拟地址时,才会由“请页机制”产生“缺页异常”,从而进入分配实际页框程序。

    内核空间是由内核负责映射,它并不会跟着进程改变,是固定的。

物理内存896MB以上的部分称之为高端内存。

 

2. mmap方法

    实现mmap方法,驱动程序只需要为该地址范围建立合适的页表,并将vma->ops替换成一系列的新操作就可以了。

void *mmap(void *addr, size_t len, intprot, int flags, int fd, off_t offset)

       内存映射函数,负责把文件内存映射到虚拟内存空间,返回映射地址空间地址。

       参数说明:

       addr:指定映射的起始地址,通常设为NULL,由系统指定。

       length:映射到内存的文件长度

       prot:映射区的保护模式,可以是PROT_EXEC(可执行)、PROT_READ(可读)、PROT_WRITE(可写)。

       flag:映射区的特性,可以是

       MAP_SHARED:写入映射区的数据会复制回文件,且允许其他映射该文件的进程共享。

       MAP_PRIVATE:对映射区的写入操作会产生一个映射区的复制,对此区域的修改不会写回原文件。

       fd:要映射的文件描述符

       offet:以文件开始出的偏移量,通常为0,从文件头开始映射。

int munmap(void *start, size_t length)

       解除映射。

struct vm_area_struct

       内核用来描述虚拟内存区域的结构。

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

int io_remap_page_range(structvm_area_struct *vma, unsignde long virt_add, unsigned long phys_add, unsignedlong size, pgprot_t prot)

       mmap的核心函数。他们映射了物理地址中从pfn表示的页号开始的size个字节到虚拟地址virt_add上。相关虚拟地址的保护位在port中指定。如果目标地址在I/O地址空间的话,使用io_remap_page_range函数。

 

 

二、驱动代码

 

staticint mem_mmap(struct file *filp, struct vm_area_struct *vma){       intret = 0;       structmem_dev *dev;       dev= filp->private_data;             ret = remap_pfn_range(vma,vma->vm_start, virt_to_phys(dev->data)>>PAGE_SHIFT, vma->vm_end- vma->vm_start, vma->vm_page_prot);          //建立页表           if(ret)              return-EAGAIN;                    returnret;} static const struct file_operationsmem_fops = {       .owner= THIS_MODULE,       .open= mem_open,       .write= mem_write,       .read= mem_read,       .release= mem_release,       .llseek= mem_llseek,       .ioctl= mem_ioctl,       .poll= mem_poll,       .mmap= mem_mmap,};

    

转载于:https://www.cnblogs.com/key000/archive/2011/09/19/4084790.html

你可能感兴趣的文章
GraphQL 01--- GraphQL 介绍及资源总结
查看>>
nginx配置访问密码,让用户输入用户名密码才能访问
查看>>
串结构练习——字符串匹配
查看>>
CF Round #426 (Div. 2) The Useless Toy 思维 水题
查看>>
UVA 122 Trees on the level 二叉树 广搜
查看>>
POJ-2251 Dungeon Master
查看>>
tortoisesvn的安装
查看>>
大S变"汪太"!与汪小菲注册结婚
查看>>
我是怎么使用最短路径算法解决动态联动问题的
查看>>
sublime Text 2 配置以及 Python环境搭建
查看>>
[2778]小明的花费预算 (二分查找)SDUT
查看>>
Runnable接口介绍(中文文档)
查看>>
URAL 1353 Milliard Vasya's Function DP
查看>>
速读《构建之法:现代软件工程》提问
查看>>
在iOS微信浏览器中自动播放HTML5 audio(音乐)的2种正确方式
查看>>
Android onclicklistener中使用外部类变量时为什么需要final修饰【转】
查看>>
Matlab2012a下配置LibSVM—3.18
查看>>
SpringBoot 搭建
查看>>
中信国健临床通讯2011年7月期目录
查看>>
iOS开发之设计模式篇
查看>>