Linux中mmap系统调用原理分析与达成
发布时间:2021-11-23 16:08:59 所属栏目:教程 来源:互联网
导读:1、mmap系统调用(功能) void* mmap ( void * addr , size_t len , int prot , int flags ,int fd , off_t offset ) 内存映射函数mmap, 负责把文件内容映射到进程的虚拟内存空间, 通过对这段内存的读取和修改,来实现对文件的读取和修改,而不需要再调用read
1、mmap系统调用(功能) void* mmap ( void * addr , size_t len , int prot , int flags ,int fd , off_t offset ) 内存映射函数mmap, 负责把文件内容映射到进程的虚拟内存空间, 通过对这段内存的读取和修改,来实现对文件的读取和修改,而不需要再调用read,write等操作。 2、mmap系统调用(参数) 1)addr: 指定映射的起始地址, 通常设为NULL, 由系统指定。 2)length: 映射到内存的文件长度。 3) prot: 映射区的保护方式, 可以是: PROT_EXEC: 映射区可被执行 PROT_READ: 映射区可被读取 PROT_WRITE: 映射区可被写入 4)flags: 映射区的特性, 可以是: MAP_SHARED:写入映射区的数据会复制回文件, 且允许其他映射该文件的进程共享。 MAP_PRIVATE:对映射区的写入操作会产生一个映射区的复制(copy-on-write), 对此区域所做的修改不会写回原文件。 5)fd: 由open返回的文件描述符, 代表要映射的文件。 6)offset: 以文件开始处的偏移量, 必须是分页大小的整数倍, 通常为0, 表示从文件头开始映射。 3、解除映射 int munmap(void *start,size_t length) 功能:取消参数start所指向的映射内存,参数length表示欲取消的内存大小。 返回值:解除成功返回0,否则返回-1,错误原因存于errno中。 实例分析 mmap系统调用 4、虚拟内存区域 虚拟内存区域是进程的虚拟地址空间中的一个同质区间,即具有同样特性的连续地址范围。一个进程的内存映象由下面几部分组成:程序代码、数据、BSS 和栈区域,以及内存映射的区域。 一个进程的内存区域可以通过查看:/proc/pid/maps 08048000-0804f000 r-xp 00000000 08:01 573748 /sbin/rpc.statd #text 0804f000-08050000 rw-p 00007000 08:01 573748 /sbin/rpc.statd #data 08050000-08055000 rwxp 00000000 00:00 0 #bss 040000000-40015000 r-xp 00000000 08:01 933965 /lib/ld2.3.2.so #text 40015000-40016000 rw-p 00014000 08:01 933965 /lib/ld-2.3.2.so #data 每一行的域为:start_end perm offset major:minor inode 1) Start: 该区域起始虚拟地址 2) End: 该区域结束虚拟地址 3) Perm: 读、写和执行权限;表示对这个区域,允许进程做什么。这个域的最后一个字符要么是p表示私有的,要么是s表示共享的。 4) Offset: 被映射部分在文件中的起始地址 5) Major、minor:主次设备号 6) Inode:索引结点 5、vm_area_struct Linux内核使用结构vm_area_struct(<linux/mm_types.h>)来描述虚拟内存区域,其中几个主要成员如下: 1)unsigned long vm_start 虚拟内存区域起始地址 2)unsigned long vm_end 虚拟内存区域结束地址 3)unsigned long vm_flags 该区域的标记。如:VM_IO和VM_RESERVED。VM_IO将该VMA标记为内存映射的IO区域,VM_IO会阻止系统将该区域包含在进程的存放转 存(core dump )中,VM_RESERVED标志内存区域不能被换出。 6、mmap设备操作 映射一个设备是指把用户空间的一段地址关联到设备内存上。当程序读写这段用户空间的地址时,它实际上是在访问设备。 mmap设备方法需要完成什么功能? mmap方法是file_oprations结构的成员,在mmap系统调用发出时被调用。在此之前,内核已经完成了很多工作。mmap设备方法所需要做的就是建立 虚拟地址到物理地址的页表。 int (*mmap) (struct file *, struct vm_area_struct *) mmap如何完成页表的建立? 方法有二: 1)使用remap_pfn_range一次建立所有页表; 2)使用nopage VMA方法每次建立一个页表。 构造页表的工作可由remap_pfn_range函数完成,原型如下: 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得到。 size: 要映射的区域的大小。 prot: VMA的保护属性。 int memdev_mmap(struct file*filp, struct vm_area_struct *vma) { Vma->vm_flags |= VM_IO; Vma->vm_flags |= VM_RESERVED; if (remap_pfn_range(vma, vma->vm_start, virt_to_phys(dev- >data)>> PAGE_SHIFT, size, vma->vm_page_prot)) return -EAGAIN; return 0; } (编辑:济南站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |