驱动笔记(5)

来源:互联网 发布:封lol端口 编辑:程序博客网 时间:2024/05/16 14:57

虚拟内存区域:是虚拟地址空间的一个同质区间,即有同样特性的连续地址范围。一个进程的内存映像由以下几部分组成:程序代码,数据,BSS和栈区域,以及内存映射区域

 

一个进程的内存区域可以通过查看 /proc/pid/maps

每一行的域为:start_endperm offset major:minor inode

 

linux内核使用结构vm_area_struct来描述虚拟内存区域,其中主要成员如下:

unsigned long vm_start 虚拟内存区域起始地址

unsigned long vm_end 虚拟内存区域结束地址

unsigned long vm_flags

 

映射一个设备是指把用户空间的一段地址关联到设备内存上。

mmap做了三件事:1.找到用户空间地址(内核完成)2.找到设备的物理地址(原理图)3.关联(通过页式管理)

mmap设备方法需要做的就是建立虚拟地址到物理地址的页表。

int(*mmap)(struct file*, struct vm_area_struct *)

建立页表有两种方法:

1.使用remap_pfn_range一次建立所有页表;

2.使用nopage VMA方法每次建立一个也表。

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

vma:虚拟内存区域指针 virt_addr:虚拟地址的起始值 pfn:要映射的物理地址所在的物理页祯号,可将物理地址>>PAGE_SHIFT得到(PAGE_SHIFT为12,相当于除以4KB)

size:要映射的区域的大小  prot:VMA的保护属性

 

硬件访问

寄存器和内存的区别:寄存器和RAM主要不同在于寄存器操作由副作用(side

effect或边际效果):读取某刻地址可能导致该地址内容变化,读中断状态寄存器,便自动清零

 

内存与IO

在X86存在IO空间(串口并口等),在32为x86

IO空间是64K,内存空间是4G,ARM,PowerPC只有内存地址空间的

 

IO端口:一个寄存器或内存位于IO空间时,称为IO端口

IO内存:一个寄存器或内存位于内存空间时,称为IO内存

 

对IO端口的操作需要按如下步骤完成:1,申请 2,访问  3,释放

申请:structresource *request_region(unsigned long first, unsigned long n,

const char *name)  从first开始的n个端口,name设备名字

系统中端口的分配情况记录在/proc/ioports中

访问:intboutb  intw outw  intl outl 

释放:voidrelease_region(unsigned long start, unsigned long n)

 

IO内存有4步:1.申请 2,映射 3,访问  4,释放

申请:structresource *request_mem_region(unsigned long start, unsigned long

len,char

*name)从start开始,长度为len字节的内存区。成功,返回非NULL,否则返回NULL。

可在/proc/iomem中列出

访问:在访问IO内存之前,必须进行物理地址到虚拟地址的转化,使用下面函数

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

访问:ioread8(void *addr) iowrite8(u8 value, void*addr)  老版本使用readb writeb

释放: 1,void iounmap(void *addr) 2,voidrelease_mem_region(unsigned long

start, unsigned long len)

 

混杂设备驱动:共享一个主设备号10,成为混杂设备

Linux内核使用struct miscdevice描述混杂设备

struct miscdevice{

       intminor;

       constchar *name;

       conststruct file_operations *fops;

       structlist_head list;

       structdevice *parent;

       structdevice *this_device;

}

使用misc_register函数来注册一个混杂设备驱动 misc_register(structmiscdevice *misc)

原创粉丝点击