基于msm-5.4
一、struct mm_struct
1. 简介
内嵌在 task_struct 结构中,表示一个进程虚拟地址空间。
2. 成员介绍
//include/linux/mm_types.h struct mm_struct { struct { struct vm_area_struct *mmap; /* list of VMAs */ struct rb_root mm_rb; u64 vmacache_seqnum; /* per-thread vmacache */ unsigned long (*get_unmapped_area) (struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags); unsigned long mmap_base; /* base of mmap area */ unsigned long mmap_legacy_base; /* base of mmap area in bottom-up allocations */ unsigned long task_size; /* size of task vm space */ unsigned long highest_vm_end; /* highest vma end address */ pgd_t * pgd; atomic_t membarrier_state; //CONFIG_MEMBARRIER atomic_t mm_users; atomic_t mm_count; atomic_long_t pgtables_bytes; /* PTE page table pages */ int map_count; /* number of VMAs */ spinlock_t page_table_lock; /* Protects page tables and some counters */ struct rw_semaphore mmap_sem; struct list_head mmlist; unsigned long hiwater_rss; /* High-watermark of RSS usage */ unsigned long hiwater_vm; /* High-water virtual memory usage */ unsigned long total_vm; /* Total pages mapped */ unsigned long locked_vm; /* Pages that have PG_mlocked set */ atomic64_t pinned_vm; /* Refcount permanently increased */ unsigned long data_vm; /* VM_WRITE & ~VM_SHARED & ~VM_STACK */ unsigned long exec_vm; /* VM_EXEC & ~VM_WRITE & ~VM_STACK */ unsigned long stack_vm; /* VM_STACK */ unsigned long def_flags; spinlock_t arg_lock; /* protect the below fields */ 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_auxv[AT_VECTOR_SIZE]; /* 46 for /proc/PID/auxv */ struct mm_rss_stat rss_stat; struct linux_binfmt *binfmt; mm_context_t context; /* Architecture-specific MM context */ unsigned long flags; /* Must use atomic bitops to access */ struct core_state *core_state; /* coredumping support */ #ifdef CONFIG_AIO spinlock_t ioctx_lock; struct kioctx_table __rcu *ioctx_table; #endif struct task_struct __rcu *owner; //CONFIG_MEMCG struct user_namespace *user_ns; struct file __rcu *exe_file; /* store ref to file /proc/<pid>/exe symlink points to */ atomic_t tlb_flush_pending; struct uprobes_state uprobes_state; struct work_struct async_put_work; } __randomize_layout; unsigned long cpu_bitmap[]; };
get_unmapped_area: 用于在此进程虚拟地址空间中查找一块未映射的虚拟内存的回调。
mmap: 执向任务VMA链表的链表头。
mm_rb: 执向任务VMA红黑树的根节点。
map_count: 任务VMA的总个数。
total_vm: 进程地址空间总大小. TODO: 内存管理上是如何区分进程和线程的?
start_stack: 指向栈顶的虚拟地址,栈是向下生长的。
mmap_base: mmap段起始虚拟地址,向下生长。
start_brk/brk: 指向堆的起始和结束虚拟地址,堆是向上生长的。
start_code/end_code: 代码段的起始和结束虚拟地址。
start_data/end_data: 数据段的起始和结束地址。其中 end_data-->start_brk之前是BSS段的空间。
membarrier_state: 控制 membarrier 行为的标志。此字段接近 @pgd,希望适合相同的缓存行,这需要由 switch_mm() 触及。
mm_users: 用户的数量,包括用户空间。使用 mmget()/mmget_not_zero()/mmput() 进行修改。当该值降至 0 时(即当任务退出且没有其他临时引用持有者时),我们还会释放对@mm_count 的引用(如果 @mm_count 也降至 0,则可能会释放 &struct mm_struct)。
mm_count:对 &struct mm_struct 的引用数(@mm_users 计为 1)。使用 mmgrab()/mmdrop() 进行修改。当此值降至 0 时,&struct mm_struct 将被释放。
mm_list: 可能交换(swapped )的 mm 列表。这些列表全局地串联在 init_mm.mmlist 上,并受 mmlist_lock 保护。
rss_stat: 特殊计数器在某些配置中受 page_table_lock 保护,在其他配置中则具有原子性。
owner: 指向被视为此 mm 的规范用户/所有者的任务。必须满足以下所有条件才能更改它:current == mm->owner; current->mm != mm; new_owner->mm == mm; new_owner->alloc_lock is held;
tlb_flush_pending: 正在进行批量 TLB 刷新操作。任何可以移动进程内存的操作在移动 PROT_NONE 或 PROT_NUMA 映射页面时都需要刷新 TLB。
cpu_bitmap[]: mm_cpumask 需要位于 mm_struct 的末尾,因为它是根据 nr_cpu_ids 动态调整大小的。
二、struct vm_area_struct
1. 简介
此结构用来描述一个 VMM 内存区域。每个 VM 区域/任务都有一个这样的区域。VM 区域是进程虚拟内存空间的一部分,它对page-fault处理程序有特殊规则(即共享库、可执行区域等)。
无论是加载一个动态链接库,还是通过mmap创建映射,都需要在进程地址空间中增加一个新的vma结构。具体过程是首先通过 get_unmapped_area()找到虚拟地址空间中一块空闲且大小满足要求的区域,分配给新vma并设置其flag属性,返回该vma起始处的虚拟地址。注意分配的vma只是这段虚拟地址的使用权,而不是物理地址的使用权。
2. 成员介绍
//include/linux/mm_types.h struct vm_area_struct { /* The first cache line has the info for VMA tree walking. */ unsigned long vm_start; /* Our start address within vm_mm. */ unsigned long vm_end; /* The first byte after our end address within vm_mm. */ struct vm_area_struct *vm_next, *vm_prev; struct rb_node vm_rb; unsigned long rb_subtree_gap; /* Second cache line starts here. after 64B */ struct mm_struct *vm_mm; /* The address space we belong to. */ pgprot_t vm_page_prot; /* Access permissions of this VMA. */ unsigned long vm_flags; /* Flags, see mm.h. */ union { struct { struct rb_node rb; unsigned long rb_subtree_last; } shared; const char __user *anon_name; }; struct list_head anon_vma_chain; /* Serialized by mmap_sem & page_table_lock */ struct anon_vma *anon_vma; /* Serialized by page_table_lock */ const struct vm_operations_struct *vm_ops; unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE units */ struct file * vm_file; /* File we map to (can be NULL). */ void * vm_private_data; /* was vm_pte (shared mem) */ atomic_long_t swap_readahead_info; //CONFIG_SWAP struct vm_region *vm_region; //CONFIG_MMU struct vm_userfaultfd_ctx vm_userfaultfd_ctx; } __randomize_layout;
vm_start: 指向此区域起始虚拟地址
vm_end: 指向此区域结束虚拟地址
vm_page_prot: 描述此区域所有页面的读写权限
vm_flags: 描述此区域是私有的还是共享的等,见mm.h, VM_IO: 此区域映射的是设备IO地址;VM_LOCKED: 此页被锁住了不能交换出去;
vm_next/vm_prev: 任务的所有 VM 区域构成的链表,按地址排序。
rb_subtree_gap: 此 VMA 左侧的最大可用内存间隙(以字节为单位)。此 VMA 与 vma->vm_prev 之间,或 VMA rbtree 中我们下方的 VMA 之一与其 ->vm_prev 之间。这有助于get_unmapped_area 找到合适大小的可用区域。
shared.rb/shared.rb_subtree_last: 对于具有地址空间和后备存储的区域,链接到 address_space->i_mmap 间隔树。
anon_name: 对于私有匿名映射,指向用户进程中以空字符结尾的字符串的指针,该字符串包含赋予 vma 的名称,如果未命名,则为 NULL。
anon_vma_chain: 在文件页面之一的 COW 之后,文件的 MAP_PRIVATE vma 可以同时位于 i_mmap 树和 anon_vma list 中。MAP_SHARED vma 只能位于 i_mmap 树中。匿名 MAP_PRIVATE、堆栈或 brk vma(带有 NULL 文件)只能位于 anon_vma 列表中。
vm_ops: 用于处理此结构的函数指针。
vm_pgoff: 有关后备存储的信息
三、struct vm_operations_struct
1. 简介
VMA的操作函数集。这些是虚拟 MM 函数 - 打开、关闭和取消映射一个区域(需要使磁盘上的文件保持最新等)、指向发生 no-page 或 wp-page 异常时调用的函数。
//include/linux/mm.h struct vm_operations_struct { void (*open)(struct vm_area_struct * area); void (*close)(struct vm_area_struct * area); int (*split)(struct vm_area_struct * area, unsigned long addr); int (*mremap)(struct vm_area_struct * area); vm_fault_t (*fault)(struct vm_fault *vmf); vm_fault_t (*huge_fault)(struct vm_fault *vmf, enum page_entry_size pe_size); void (*map_pages)(struct vm_fault *vmf, pgoff_t start_pgoff, pgoff_t end_pgoff); unsigned long (*pagesize)(struct vm_area_struct * area); vm_fault_t (*page_mkwrite)(struct vm_fault *vmf); vm_fault_t (*pfn_mkwrite)(struct vm_fault *vmf); int (*access)(struct vm_area_struct *vma, unsigned long addr, void *buf, int len, int write); const char *(*name)(struct vm_area_struct *vma); struct page *(*find_special_page)(struct vm_area_struct *vma, unsigned long addr); };
2. 成员介绍
page_mkwrite: 通知以前只读的页面即将变为可写,如果返回错误,则会导致 SIGBUS.
pfn_mkwrite: 当使用 VM_PFNMAP|VM_MIXEDMAP 时与 page_mkwrite 相同
access: 当 get_user_pages() 失败时由 access_process_vm 调用,通常由可以在内存和硬件之间切换的特殊 VMA 使用.
name: 由 /proc/PID/maps 代码调用,询问 vma 是否具有特殊名称。返回非 NULL 也将导致此 vma 被无条件dumped。
find_special_page: 由 vm_normal_page() 调用,用于特殊 PTE 查找 @addr 的页面。如果默认行为(使用 pte_page())找不到正确的页面,则此功能很有用。
标签:struct,area,mm,vm,long,unsigned,内存,相关,虚拟内存 From: https://www.cnblogs.com/hellokitty2/p/18256486