




已阅读5页,还剩31页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
内存mmap实现原理内存mmap实现原理谨以此文纪念过往的岁月。结构体列表1. struct rb_node_s2 struct page3. struct vm_area_struct4. struct mm_struct函数列表do_mmapdo_mmap2红黑树结构 Linux内核从2.4.10开始,对虚拟区的组织不再采用AVL树,而是采用红黑树,这也是出于效率的考虑,虽然AVL树和红黑树很类似,但在插入和删除节点方面,采用红黑树的性能更好一些,下面对红黑树给予简单介绍。 一颗红黑树是具有以下特点的二叉树:(1) 每个节点着有颜色,或者为红,或者为黑(2) 根节点为黑色(3) 如果一个节点为红色,那么它的子节点必须为黑色(4) 从一个节点到叶子节点上的所有路径都包含有相同的黑色节点数 红黑树的结构在include/linux/rbtree.h中定义如下:typedef struct rb_node_s struct rb_node_s * rb_parent; int rb_color;#define RB_RED 0#define RB_BLACK 1 struct rb_node_s * rb_right; struct rb_node_s * rb_left; rb_node_t;O(_)Ostruct page unsigned long flags; /* Atomic flags, some possibly * updated asynchronously */ atomic_t _count; /* Usage count, see below. */ union atomic_t _mapcount; /* Count of ptes mapped in mms, * to show when page is mapped * & limit reverse map searches. */ struct /* SLUB */ u16 inuse; u16 objects; ; ; union struct unsigned long private; /* Mapping-private opaque data: * usually used for buffer_heads * if PagePrivate set; used for * swp_entry_t if PageSwapCache; * indicates order in the buddy * system if PG_buddy is set. */ struct address_space *mapping; /* If low bit clear, points to * inode address_space, or NULL. * If page mapped as anonymous * memory, low bit is set, and * it points to anon_vma object: * see PAGE_MAPPING_ANON below. */ ;#if USE_SPLIT_PTLOCKS spinlock_t ptl;#endif struct kmem_cache *slab; /* SLUB: Pointer to slab */ struct page *first_page; /* Compound tail pages */ ; union pgoff_t index; /* Our offset within mapping. */ void *freelist; /* SLUB: freelist req. slab lock */ ; struct list_head lru; /* Pageout list, eg. active_list * protected by zone-lru_lock ! */ /* * On machines where all RAM is mapped into kernel address space, * we can simply calculate the virtual address. On machines with * highmem some memory is mapped into kernel virtual memory * dynamically, so we need a place to store that address. * Note that this field could be 16 bits on x86 . * * Architectures with slow multiplication can define * WANT_PAGE_VIRTUAL in asm/page.h */#if defined(WANT_PAGE_VIRTUAL) void *virtual; /* Kernel virtual address (NULL if not kmapped, ie. highmem) */#endif /* WANT_PAGE_VIRTUAL */;/* This struct defines a memory VMM memory area. There is one of these* per VM-area/task.A VM area is any part of the process virtual memory* space that has a special rule for the page-fault handlers (ie a shared* library, the executable area etc).*/O(_)Ostruct vm_area_struct struct mm_struct * vm_mm; /* The address space we belong to. */ unsigned long vm_start; /* Our start address within vm_mm. */ unsigned long vm_end; /* The first byte after our end address within vm_mm. */ /* linked list of VM areas per task, sorted by address */ struct vm_area_struct *vm_next; pgprot_t vm_page_prot; /* Access permissions of this VMA. */ unsigned long vm_flags; /* Flags, see mm.h. */ struct rb_node vm_rb; /* * For areas with an address space and backing store, * linkage into the address_space-i_mmap prio tree, or * linkage to the list of like vmas hanging off its node, or * linkage of vma in the address_space-i_mmap_nonlinear list. */ union struct struct list_head list; void *parent; /* aligns with prio_tree_node parent */ struct vm_area_struct *head; vm_set; struct raw_prio_tree_node prio_tree_node; shared; /* * A files MAP_PRIVATE vma can be in both i_mmap tree and anon_vma * list, after a COW of one of the file pages. A MAP_SHARED vma * can only be in the i_mmap tree.An anonymous MAP_PRIVATE, stack * or brk vma (with NULL file) can only be in an anon_vma list. */ struct list_head anon_vma_node; /* Serialized by anon_vma-lock */ struct anon_vma *anon_vma; /* Serialized by page_table_lock */ /* Function pointers to deal with this struct. */ struct vm_operations_struct * vm_ops; /* Information about our backing store: */ unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE units, *not* PAGE_CACHE_SIZE */ struct file * vm_file; /* File we map to (can be NULL). */ void * vm_private_data; /* was vm_pte (shared mem) */ unsigned long vm_truncate_count;/* truncate_count or restart_addr */#ifndef CONFIG_MMU atomic_t vm_usage; /* refcount (VMAs shared if !MMU) */#endif#ifdef CONFIG_NUMA struct mempolicy *vm_policy; /* NUMA policy for the VMA */#endif;struct core_thread struct task_struct *task; struct core_thread *next;struct core_state atomic_t nr_threads; struct core_thread dumper; struct completion startup;O(_)O struct mm_struct struct vm_area_struct * mmap; /vmas链表/* list of VMAs */ struct rb_root mm_rb; /红黑树的根节点 struct vm_area_struct * mmap_cache; /* last find_vma result */ 最后一次通过find_vma查找的vma的结果 unsigned long (*get_unmapped_area) (struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags); void (*unmap_area) (struct mm_struct *mm, unsigned long addr); unsigned long mmap_base; /* base of mmap area */ unsigned long task_size; /* size of task vm space */ unsigned long cached_hole_size; /* if non-zero, the largest hole below free_area_cache */ unsigned long free_area_cache; /* first hole of size cached_hole_size or larger */ pgd_t * pgd; /页目录表 atomic_t mm_users; /* How many users with user space? */ atomic_t mm_count; /* How many references to struct mm_struct (users count as 1) */ int map_count; /* number of VMAs */ struct rw_semaphore mmap_sem; /读写信号量 spinlock_t page_table_lock; /* Protects page tables and some counters */ struct list_head mmlist; /* List of maybe swapped mms. These are globally strung * together off init_mm.mmlist, and are protected * by mmlist_lock */ /* Special counters, in some configurations protected by the * page_table_lock, in other configurations by being atomic. */ mm_counter_t _file_rss; mm_counter_t _anon_rss; unsigned long hiwater_rss; /* High-watermark of RSS usage */ unsigned long hiwater_vm; /* High-water virtual memory usage */ unsigned long total_vm, locked_vm, shared_vm, exec_vm; unsigned long stack_vm, reserved_vm, def_flags, nr_ptes; unsigned long start_code, end_code, start_data, end_data; unsigned long start_brk, brk, start_stack; unsigned long arg_start, arg_end, env_start, env_end; unsigned long saved_auxvAT_VECTOR_SIZE; /* for /proc/PID/auxv */ cpumask_t cpu_vm_mask; /* Architecture-specific MM context */ mm_context_t context; /* Swap token stuff */ /* * Last value of global fault stamp as seen by this process. * In other words, this value gives an indication of how long * it has been since this task got the token. * Look at mm/thrash.c */ unsigned int faultstamp; unsigned int token_priority; unsigned int last_interval; unsigned long flags; /* Must use atomic bitops to access the bits */ struct core_state *core_state; /* coredumping support */ /* aio bits */ rwlock_t ioctx_list_lock; /* aio lock */ struct kioctx *ioctx_list;#ifdef CONFIG_MM_OWNER /* * owner points to a task that is regarded as the canonical * user/owner of this mm. All of the following must be true in * order for it to be changed: * * current = mm-owner * current-mm != mm * new_owner-mm = mm * new_owner-alloc_lock is held */ struct task_struct *owner;#endif#ifdef CONFIG_PROC_FS /* store ref to file /proc/exe symlink points to */ struct file *exe_file; unsigned long num_exe_file_vmas;#endif#ifdef CONFIG_MMU_NOTIFIER struct mmu_notifier_mm *mmu_notifier_mm;#endif;O(_)Ostatic inline unsigned long do_mmap(struct file *file, unsigned long addr,unsigned long len, unsigned long prot, unsigned long flag, unsigned long offset) unsigned long ret = -EINVAL;if (offset + PAGE_ALIGN(len) PAGE_SHIFT);out: return ret;O(_)Oinline long do_mmap2(unsigned long addr, unsigned long len,unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) int error = -EINVAL; struct file * file = NULL; flags &= (MAP_EXECUTABLE | MAP_DENYWRITE); /将标志设置为不可执行以及可写/在ARM中 #define FIRST_USER_ADDRESS PAGE_SIZE if (flags & MAP_FIXED & addr mm-mmap_sem);/锁定信号量,防止其它进程是使用 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); /注意do_mmap 和do_mmap1中的pgoff传入的参数不同。Do_mmap中pgoff直接为偏移地址,而在do_mmap1中为偏移页帧数 up_write(¤t-mm-mmap_sem); if (file) fput(file);out: return error;O(_)Ounsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long pgoff) struct mm_struct * mm = current-mm; /mm指针指向当前进程的mm_struct struct inode *inode; unsigned int vm_flags; int error; int accountable = 1; unsigned long reqprot = prot; /* * Does the application expect PROT_READ to imply PROT_EXEC? * * (the exception is when the underlying filesystem is noexec *mounted, in which case we dont add PROT_EXEC.) */ if (prot & PROT_READ) & (current-personality & READ_IMPLIES_EXEC)/? if (!(file & (file-f_path.mnt-mnt_flags & MNT_NOEXEC) prot |= PROT_EXEC; if (!len) return -EINVAL; if (!(flags & MAP_FIXED)/如果没有设置直接地址,对addr进行检测,如果小于mmap_min_addr的最小地址,则将addr改为最小的addr,在设置安全配置后有效 addr = round_hint_to_min(addr); / #ifndef arch_mmap_check/#define arch_mmap_check(addr, len, flags) (0)/#endif error = arch_mmap_check(addr, len, flags); /对参数进行检测,在ARM中没有对其定义直接返回0 if (error) return error; /* Careful about overflows. */ / #define PAGE_ALIGN(addr) (addr)+PAGE_SIZE-1)&PAGE_MASK) len = PAGE_ALIGN(len); /将物理地址addr修整为页边界地址(页的上边界) if (!len | len TASK_SIZE)/len大于0并且len小于用户进程空间的最大值 return -ENOMEM; /* offset overflow? */ if (pgoff + (len PAGE_SHIFT) map_count sysctl_max_map_count)/ map_count记录用户进程的映射个数,如果大于最大的映射个数 return -ENOMEM;/* Obtain the address to map to. we verify (or select) it and ensure that it represents a valid section of the address space. */ addr = get_unmapped_area(file, addr, len, pgoff, flags); if (addr & PAGE_MASK) return addr; /* Do simple checking here so the lower-level routines wont have * to. we assume access permissions have been handled by the open * of the memory object, so we dont do any here. */ vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags) | mm-def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; if (flags & MAP_LOCKED) if (!can_do_mlock() return -EPERM; vm_flags |= VM_LOCKED; /* mlock MCL_FUTURE? */ if (vm_flags & VM_LOCKED) unsigned long locked, lock_limit; locked = len PAGE_SHIFT; locked += mm-locked_vm; lock_limit = current-signal-rlimRLIMIT_MEMLOCK.rlim_cur; lock_limit = PAGE_SHIFT; if (locked lock_limit & !capable(CAP_IPC_LOCK) return -EAGAIN; inode = file ? file-f_path.dentry-d_inode : NULL; if (file) switch (flags & MAP_TYPE) case MAP_SHARED: if (prot&PROT_WRITE) & !(file-f_mode&FMODE_WRITE) return -EACCES; /* * Make sure we dont allow writing to an append-only * file. */ if (IS_APPEND(inode) & (file-f_mode & FMODE_WRITE) return -EACCES; /* * Make sure there are no mandatory locks on the file. */ if (locks_verify_locked(inode) return -EAGAIN; vm_flags |= VM_SHARED | VM_MAYSHARE; if
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年教师招聘之《小学教师招聘》通关练习试题(综合卷)附答案详解
- 考试题及答案大全集
- 汽车救援员技能巩固考核试卷及答案
- 光学计量员职业考核试卷及答案
- 润滑油脂灌装制桶工内部技能考核试卷及答案
- 集输工成本预算考核试卷及答案
- 静脉输血考试题及答案
- 经理升职考试题及答案
- 课件文案精简
- 今年监理考试题及答案
- 高中政治统编版(2022)必修3(教案)我国法治建设历程(完整文档)
- 2021年康平县工会系统招聘笔试试题及答案解析
- 游标卡尺的使用flash动画演示教学课件
- 市场营销策划(第五版)第08章 促销策划
- 管理层财务基础知识培训
- 立式储罐重量表
- 电气系统调试方案
- 呋喃树脂msds
- 福建省机关事业单位工勤人员技术等级岗位考核公共课
- 落实乡村振兴战略山核桃产业振兴五年行动方案
- 中国五矿集团供应商准入承诺书
评论
0/150
提交评论