void* mmap ( void * addr , size_t len , int prot , int flags ,int fd , off_t offset )
内存映射函数mmap, 负责把文件内容映射到进程的虚拟内存空间, 通过对这段内存的读取和修改,来实现对文件的读取和修改,而不需要再调用read,write等操作。
int munmap(void *start,size_t length)
取消参数start所指向的映射内存,参数length表示欲取消的内存大小。
解除成功返回0,否则返回-1,错误原因存于errno中。
虚拟内存区域是进程的虚拟地址空间中的一个同质区间,即具有同样特性的连续地址范围。一个进程的内存映象由下面几部分组成:程序代码、数据、BSS和栈区域,以及内存映射的区域。
一个进程的内存区域可以通过查看 /proc/pid/maps
每一行的域为:start_end perm offset major:minor inode
Linux内核使用结构vm_area_struct(<linux/mm_types.h>)来描述虚拟内存区域,其中几个主要成员如下:
映射一个设备是指把用户空间的一段地址关联到设备内存上。当程序读写这段用户空间的地址时,它实际上是在访问设备。
mmap方法是file_oprations结构的成员,在mmap系统调用发出时被调用。在此之前,内核已经完成了很多工作。mmap设备方法所需要做的就是建立虚拟地址到物理地址的页表
int (*mmap) (struct file *, struct vm_area_struct *)
mmap如何完成页表的建立?
构造页表的工作可由remap_pfn_range函数完成,原型如下:
int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,unsigned long pfn, unsigned long size, pgprot_t prot)
1 int memdev_mmap(struct file*filp, struct vm_area_struct *vma) 2 { 3 Vma->vm_flags |= VM_IO; 4 Vma->vm_flags |= VM_RESERVED; 5 if (remap_pfn_range(vma, vma->vm_start,virt_to_phys(dev- >data)>> PAGE_SHIFT,size,vma->vm_page_prot)) 6 { 7 return -EAGAIN; 8 } 9 return 0; 10 }
寄存器与内存的区别在哪里呢?
在X86处理器中存在I/O空间的概念,I/O 空间是相对内存空间而言的,他们是彼此独立的地址空间,在32位的x86系统中,I/O空间大小为64K,内存空间大小为4G。
操作I/O端口: 对I/O端口的操作需按如下步骤完成:
内核提供了一套函数来允许驱动申请它需要的I/O端口,其中核心的函数是: struct resource *request_region(unsigned long first,unsigned long n, const char *name)
这个函数告诉内核,你要使用从 first 开始的n个端口,name参数是设备的名字。如果申请成功,返回非 NULL,申请失败,返回 NULL。
系统中端口的分配情况记录在/proc/ioports 中(展示)。如果不能分配需要的端口,可以来这里查看谁在使用。
I/O端口可分为8-位, 16-位, 和 32-位端口。Linux内核头文件(体系依赖的头文件 <asm/io.h>) 定义了下列内联函数来访问 I/O 端口:
存取 16-位 端口。
存取 32-位 端口。
当用完一组 I/O 端口(通常在驱动卸载时),应使用如下函数把它们返还给系统:
void release_region(unsigned long start, unsigned long n)
对I/O内存的操作需按如下步骤完成:
内核提供了一套函数来允许驱动申请它需要的I/O内存,其中核心的函数是:
struct resource *request_mem_region(unsigned long start, unsigned long len, char *name)
这个函数申请一个从start 开始,长度为len 字节的内存区。如果成功,返回非NULL;否则返回NULL,所有已经在使用的I/O内存在/proc/iomem 中列出。
在访问I/O内存之前, 必须进行物理地址到虚拟地址的映射,ioremap 函数具有此功能:
void *ioremap(unsigned long phys_addr, unsigned long size)
访问 I/O 内存的正确方法是通过一系列内核提供的函数:
从 I/O 内存读, 使用下列之一:
写I/O 内存, 使用下列之一:
老版本的 I/O 内存访问函数:
从 I/O 内存读, 使用下列之一:
写I/O 内存, 使用下列之一:
在Linux系统中,存在一类字符设备,它们共享一个主设备号(10),但次设备号不同,我们称这类设备为混杂设备(miscdevice)。所有的混杂设备形成一个链表,对设备访问时内核根据次设备号查找到相应的miscdevice设备。
Linux内核使用struct miscdevice来描述一个混杂设备。
struct miscdevice
{
int minor; /* 次设备号*/
const char *name; /* 设备名*/
const struct file_operations *fops; /*文件操作*/
struct list_head list;
struct device *parent;
struct device *this_device;
};
Linux内核使用misc_register函数来注册一个混杂设备驱动。
int misc_register(struct miscdevice * misc)
上拉是将不确定的信号通过一个电阻与电源相连,固定在高电平。下拉是将不确定的信号通过一个电阻与地相连,固定在低电平。上拉是对器件注入电流,下拉是输出电流。当一个接有上拉电阻的I/O端口设为输入状态时,它的常态为高电平,可用于检测低电平的输入。
原文:https://www.cnblogs.com/WenLee/p/12114983.html