网络安全参考 | UNIX参考 | GPS参考 | 无线参考 | 在线手册 | OSBUG.ORG | SUNNY-NETWORK.COM
天线制作 GPS 地标
网站地图 RSS订阅
高级搜索 收藏本站
Home | 业界动态 | Open source | GNU | Linux | BSD | Solaris | AIX | HP-UX | IRIX | Mac OS X | Minix | Tru64 | SCO UNIX | Network | Security | X-Window | Database | 应用服务 | Programming | 经典著作 | 永远的纪念 | 杂项
 当前位置: Home > Linux > 设备驱动 > 文章  
Linux设备驱动编程之内存与I/O操作
文章来源: 天极开发 文章作者: 宋宝华 发布时间: 2006-10-27   字体: [ ]  
 

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
MODULE_LICENSE("GPL");
unsigned char *pagemem;
unsigned char *kmallocmem;
unsigned char *vmallocmem;

int __init mem_module_init(void)
{
 //最好每次内存申请都检查申请是否成功
 //下面这段仅仅作为演示的代码没有检查
 pagemem = (unsigned char*)get_free_page(0);
 printk("<1>pagemem addr=%x", pagemem);

 kmallocmem = (unsigned char*)kmalloc(100, 0);
 printk("<1>kmallocmem addr=%x", kmallocmem);

 vmallocmem = (unsigned char*)vmalloc(1000000);
 printk("<1>vmallocmem addr=%x", vmallocmem);

 return 0;
}

void __exit mem_module_exit(void)
{
 free_page(pagemem);
 kfree(kmallocmem);
 vfree(vmallocmem);
}

module_init(mem_module_init);
module_exit(mem_module_exit);

  我们的系统上有160MB的内存空间,运行一次上述程序,发现pagemem的地址在0xc7997000(约3G+121M)、kmallocmem 地址在0xc9bc1380(约3G+155M)、vmallocmem的地址在0xcabeb000(约3G+171M)处,符合前文所述的内存布局。

  接下来,我们讨论Linux设备驱动究竟怎样访问外设的I/O端口(寄存器)。

  几乎每一种外设都是通过读写设备上的寄存器来进行的,通常包括控制寄存器、状态寄存器和数据寄存器三大类,外设的寄存器通常被连续地编址。根据CPU体系结构的不同,CPU对IO端口的编址方式有两种:

  (1)I/O映射方式(I/O-mapped)

  典型地,如X86处理器为外设专门实现了一个单独的地址空间,称为"I/O地址空间"或者"I/O端口空间",CPU通过专门的I/O指令(如X86的IN和OUT指令)来访问这一空间中的地址单元。

  (2)内存映射方式(Memory-mapped)

  RISC指令系统的CPU(如ARM、PowerPC等)通常只实现一个物理地址空间,外设I/O端口成为内存的一部分。此时,CPU可以象访问一个内存单元那样访问外设I/O端口,而不需要设立专门的外设I/O指令。

  但是,这两者在硬件实现上的差异对于软件来说是完全透明的,驱动程序开发人员可以将内存映射方式的I/O端口和外设内存统一看作是"I/O内存"资源。

  一般来说,在系统运行时,外设的I/O内存资源的物理地址是已知的,由硬件的设计决定。但是CPU通常并没有为这些已知的外设I/O内存资源的物理地址预定义虚拟地址范围,驱动程序并不能直接通过物理地址访问I/O内存资源,而必须将它们映射到核心虚地址空间内(通过页表),然后才能根据映射所得到的核心虚地址范围,通过访内指令访问这些I/O内存资源。Linux在io.h头文件中声明了函数ioremap(),用来将I/O内存资源的物理地址映射到核心虚地址空间(3GB-4GB)中,原型如下:

void * ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);

  iounmap函数用于取消ioremap()所做的映射,原型如下:

void iounmap(void * addr);

 
推荐文章
·让arm-linux支持普通USB摄像头
·Linux设备驱动编程之结构化设备
·Linux设备驱动编程之复杂设备驱
·深入浅出Linux设备驱动之并发控
·深入浅出Linux设备驱动之字符设
·深入浅出Linux设备驱动编程之内
·深入浅出Linux设备驱动编程之引
·Linux设备驱动编程之定时器
·Linux设备驱动编程之中断处理
·Linux设备驱动编程之异步通知
·Linux设备驱动编程之阻塞与非阻
·摄像头(WebCam)在Linux操作系
·中星微芯片(301,302)USB 摄像头
·Linux的I2C驱动架构
 

 
↑返回顶部   打印本页   关闭窗口↓  

Google
 
Web oldhand.org unixreference.net meshmea.org
相关分类
热点文章
·摄像头(WebCam)在Linu
·在Linux中使用中星微301
·中星微芯片(301,302)USB
·深入浅出Linux设备驱动
·Linux培训园地:Linux下
·Linux的I2C驱动架构
·让arm-linux支持普通USB
·Linux设备驱动编程之复
相关文章
·Linux设备驱动编程之阻
·Linux设备驱动编程之异
·Linux设备驱动编程之中
·ARM的嵌入式Linux移植体
·Linux设备驱动编程之定
·深入浅出Linux设备驱动
·深入浅出Linux设备驱动
·深入浅出Linux设备驱动
更多...
 
 

Copyright(c) 2001-2009 OLDHAND ORGANIZATION, All Rights reserved.
Power by DedeCms 织梦内容管理系统