虚拟地址的映射建立

1.使用register_chrdev注册字符设备
int register_chrdev(unsigned int major,const char  *name, struct file_operations*fops);
其中参数major如果等于0,则表示采用系统动态分配的主设备号;不为0,则表示静态册。参数 name为字符设备的名字;参数 file_operations是一个结构体。
file_operation就是把系统调用和驱动程序关联起来的关键数据结构。这个结构的每一个成员都对应着一个系统调用。读取 file_operation中相应的函数指针,接着把控制权转交给函数,从而完成了Linux设备驱动程序的工作。在系统内部,I/O设备的存取操作通过特定的入口点来进行,而这组特定的入口点恰恰是由设备驱动程序提供的。通常这组设备驱动程序接口是由结构 file_operations结构体向系统说明的,它定义在 include/linux/fs.h中。
struct file_operations scull_fops = {
 .owner =  THIS_MODULE, 
 .llseek =  scull_llseek, 
 .read =  scull_read, 
 .write =  scull_write, 
 .ioctl =  scull_ioctl, 
 .open =  scull_open, 
 .release =  scull_release,  
};  

注销字符设备可以使用unregister_chrdev函数。
int unregister_chrdev(unsigned int major, const char *name);
2.确认io映射的地址是否被人使用
  使用I/O内存首先要申请,然后才能映射,使用I/O端口首先要申请,或者叫请求,对于I/O端口的请求意思是让内核知道你要访问这个端口,这样内核知道了以后它就不会再让别人也访问这个端口了.毕竟这个世界僧多粥少啊.申请I/O端口的函数是 request_region, 申请I/O内存的函数是 request_mem_region,来自 include/linux/ioport.h
define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name))
参数start表示要映射的物理起始地址;参数n表示地址的大小;参数name表示虚拟地址的名字。
3.建立映射页表
void * ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);
ioremap函数, ioremap主要是检查传入地址的合法性,建立页表(包括访问权限),完成物理地址到虚拟地址的转换。
参数 phys_addr表示要映射的物理地址;参数 size表示大小;参数flag可以不用写。
完成上面步骤即可完成虚拟地址映射物理地址的功能。

注意:如果内核已启动就已经帮我们映射好的地址,我们再去申请一个新的虚拟地址便会报错,有两个解决方案:1、直接使用ioremap函数建议映射关系2、到内核找到映射地址的函数module_init(xxxxx_init),module_exit(xxxxx_exit),将这两个东西注销掉,避免它们一启动便加入内核,这样可以重新申请申请一个新的地址。


本文仅供个人学习用,文中若有侵犯了其他作者的合法权利,请通知我将其删除

你可能感兴趣的:(初级驱动,地址映射)