进程地址空间 - 数据结构

进程描述结构 task_struct中包含下列成员

        struct mm_struct *mm, *active_mm;

每个进程描述符都包含: mm和active__mm,其中mm成员指向进程拥有的内存描述符,而active_mm则指向当前正在执行的内存描述符。

对于普通进程来说,二者是一样的;但是对于kernel线程没有内存描述符,mm为空,active_mm指向前一个执行进程的mm。


mm_struct

该结构保存了进程的内存管理信息

156 struct mm_struct {
157         struct vm_area_struct * mmap;           /* list of VMAs */
158         struct rb_root mm_rb;
159         struct vm_area_struct * mmap_cache;     /* last find_vma result */
160         unsigned long (*get_unmapped_area) (struct file *filp,
161                                 unsigned long addr, unsigned long len,
162                                 unsigned long pgoff, unsigned long flags);
163         void (*unmap_area) (struct mm_struct *mm, unsigned long addr);
164         unsigned long mmap_base;                /* base of mmap area */
165         unsigned long task_size;                /* size of task vm space */
166         unsigned long cached_hole_size;         /* if non-zero, the largest hole below free_area_cache */
167         unsigned long free_area_cache;          /* first hole of size cached_hole_size or larger */
168         pgd_t * pgd;
169         atomic_t mm_users;                      /* How many users with user space? */
170         atomic_t mm_count;                      /* How many references to "struct mm_struct" (users count as 1) */
171         int map_count;                          /* number of VMAs */
172         struct rw_semaphore mmap_sem;
173         spinlock_t page_table_lock;             /* Protects page tables and some counters */
174 
175         struct list_head mmlist;                /* List of maybe swapped mm's.  These are globally strung
176                                                  * together off init_mm.mmlist, and are protected
177                                                  * by mmlist_lock
178                                                  */
179 
180         /* Special counters, in some configurations protected by the
181          * page_table_lock, in other configurations by being atomic.
182          */
183         mm_counter_t _file_rss;
184         mm_counter_t _anon_rss;
185 
186         unsigned long hiwater_rss;      /* High-watermark of RSS usage */
187         unsigned long hiwater_vm;       /* High-water virtual memory usage */
188 
189         unsigned long total_vm, locked_vm, shared_vm, exec_vm;
190         unsigned long stack_vm, reserved_vm, def_flags, nr_ptes;
191         unsigned long start_code, end_code, start_data, end_data;
192         unsigned long start_brk, brk, start_stack;
193         unsigned long arg_start, arg_end, env_start, env_end;
194 
195         unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
196 
197         cpumask_t cpu_vm_mask;
198 
199         /* Architecture-specific MM context */
200         mm_context_t context;
201 
202         /* Swap token stuff */
203         /*
204          * Last value of global fault stamp as seen by this process.
205          * In other words, this value gives an indication of how long
206          * it has been since this task got the token.
207          * Look at mm/thrash.c
208          */
209         unsigned int faultstamp;
210         unsigned int token_priority;
211         unsigned int last_interval;
212 
213         unsigned long flags; /* Must use atomic bitops to access the bits */
214 
215         /* coredumping support */
216         int core_waiters;
217         struct completion *core_startup_done, core_done;
218 
219         /* aio bits */
220         rwlock_t                ioctx_list_lock;
221         struct kioctx           *ioctx_list;
222 };

描述内存布局相关的信息

mem_base:表示虚拟地址空间中用于地址映射的区域,早期mmap是从mem_base向上增长的,最终和stack会合;当前引入了一种新布局,mmap可以从mem_base向下增长,最终和對会和。

start_code, end_code 定义了代码的起始地址,和结束地址。start_code和end_code在进程生命周期中不会变化。

start_data, end_data定义了已初始化数据区起始地址和结束地址。start_data和end_data在进程生命周期中不会变化。

start_brk, brk 定义了堆区域的起始地址和结束地址,start_brk在进程生命周期中不会发生变化,brk会随着堆的扩大和缩小而变化。

arg_start, arg_end保存参数列表,位于栈中最高的地址区域

env_start, env_end保存环境变量,位于栈中最高的地址区域。

task_size:进程的地址空间长度,不包括kernel部分。

get_unmapped_area:这个函数搜索进程地址空间,找到一个可用的线性地址区。这个函数会区分两种情况:文件内存映射和匿名内存映射。


描述虚拟地址空间的内存区域:

mmap:虚拟内存区单链表,进程所有的虚拟内存区都会链接到这个单链表中

mm_rb:虚拟内存区红黑树的根节点。

map_cache:最后一次fina_vma的查找结果,根据局部性理论,下一次访问有很大可能还发生在这个区域内。

map_count:内存映射区数目,最大数目限制是sysctl_max_map_count, 65536


虚拟内存使用统计

rss:分配给进程的物理页框数目。又称为驻留内存数目。

anon_rss:分配给进程的匿名内存映射页框数

total_vm:进程使用的地址空间页面数,这个总数是虚拟内存的数目。这个数目应该就是ps 命令中的的VSS列

locked_vm:通过mlock系统调用,锁定住的虚拟内存页数,这部分页面一旦映射后是无法交换出来的。注意,这个数目是虚拟地址页面数,而不是物理页面数

shared_vm:文件共享映射虚拟内存数,只要是文件映射,都会计入这个统计数。

exec_vm:如果内存映射是文件映射,并且是可执行部分,那么统计到这个值中

stack_vm:进程栈空间的虚拟页面大小,初始值为1个页面,扩展stack会增加stack_vm

reserved_vm:


其他成员

pgd:当前进程的页表

mm_users:表示使用这个mm结构的线程数目,比如有两个线程使用它,那么值为2。

mm_count:mm结构的使用计数,为0表示没有使用者,可以释放。由于mm结构可能被内核线程借用,那么为了保证借用期间不会导致被释放,所以会对mm_count加1;此外mm的线程共用一个使用计数,也就是说mm_users大于1只会使mm_count加1

mmlist:所有的mm都链接到一个双向链表上,并通过mmlist链接到一起,这个list的地一个节点是init_mm.mmlist,也就是进程0的内存描述符

mmlist_lock:用来保护mmlist的spin lock


vm_area_struct

kernel使用vm_area_struct表示一个内存区域

 93 /*
 94  * This struct defines a memory VMM memory area. There is one of these
 95  * per VM-area/task.  A VM area is any part of the process virtual memory
 96  * space that has a special rule for the page-fault handlers (ie a shared
 97  * library, the executable area etc).
 98  */
 99 struct vm_area_struct {
100         struct mm_struct * vm_mm;       /* The address space we belong to. */
101         unsigned long vm_start;         /* Our start address within vm_mm. */
102         unsigned long vm_end;           /* The first byte after our end address
103                                            within vm_mm. */
104 
105         /* linked list of VM areas per task, sorted by address */
106         struct vm_area_struct *vm_next;
107 
108         pgprot_t vm_page_prot;          /* Access permissions of this VMA. */
109         unsigned long vm_flags;         /* Flags, listed below. */
110 
111         struct rb_node vm_rb;
112 
113         /*
114          * For areas with an address space and backing store,
115          * linkage into the address_space->i_mmap prio tree, or
116          * linkage to the list of like vmas hanging off its node, or
117          * linkage of vma in the address_space->i_mmap_nonlinear list.
118          */
119         union {
120                 struct {
121                         struct list_head list;
122                         void *parent;   /* aligns with prio_tree_node parent */
123                         struct vm_area_struct *head;
124                 } vm_set;
125 
126                 struct raw_prio_tree_node prio_tree_node;
127         } shared;
128 
129         /*
130          * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
131          * list, after a COW of one of the file pages.  A MAP_SHARED vma
132          * can only be in the i_mmap tree.  An anonymous MAP_PRIVATE, stack
133          * or brk vma (with NULL file) can only be in an anon_vma list.
134          */
135         struct list_head anon_vma_node; /* Serialized by anon_vma->lock */
136         struct anon_vma *anon_vma;      /* Serialized by page_table_lock */
137 
138         /* Function pointers to deal with this struct. */
139         struct vm_operations_struct * vm_ops;
140 
141         /* Information about our backing store: */
142         unsigned long vm_pgoff;         /* Offset (within vm_file) in PAGE_SIZE
143                                            units, *not* PAGE_CACHE_SIZE */
144         struct file * vm_file;          /* File we map to (can be NULL). */
145         void * vm_private_data;         /* was vm_pte (shared mem) */
146         unsigned long vm_truncate_count;/* truncate_count or restart_addr */
147 
148 #ifndef CONFIG_MMU
149         atomic_t vm_usage;              /* refcount (VMAs shared if !MMU) */
150 #endif
151 #ifdef CONFIG_NUMA
152         struct mempolicy *vm_policy;    /* NUMA policy for the VMA */
153 #endif
154 };

vm_mm:内存区所属的地址空间

vm_start:在内存去地址空间内的起始地址

vm_end:在内存区地址空间的结束地址

vm_next:进程地址空间包含一个内存区单链表,所有的内存区都会通过这个单链表链接起来,表头是mm->mmap

vm_page_prot:由vm_flags生成。vm_page_prot使用来设置pte页表项的保护位的,不同的体系结构,pte保护位设置方法不同。


vm_flags:存储内存区的属性,包括以下标志位

VM_READ, VM_WRITE, VM_EXEC和VM_SHARED用来标识页面内容是否有读,写,执行,以及是否可以被几个进程共享。

VM_MAYREAD, VM_MAYWRITE, VM_MAYEXEC和VM_MAYSHARE决定是否VM_READ, VM_WRITE, VM_EXEC, VM_SHARED可以被设置。在执行系统调用mprotext时会检查这个标志。

VM_GROWNSDOWN, VM_GROWSUP 指明这个内存区的增长方向。heap是从下向上增长的,所以设置为VM_GROWSUP;而stack是从上向下增长的,所以设置为VM_GROWSDOWN

VM_DONTCOPY,在执行fork系统调用时,内存区不会被copy

VM_DONTEXPAND,禁止使用mremap系统调用扩展这个内存区

VM_HUGETLB,在某些架构下,内存区是使用huge pages进行管理的,此时会设置这个标记。


vm_rb,内存区通过这个节点挂接到进程地址空间的红黑树上。

anon_vma_node和anon_vma

vm_ops:指向许多方法的集合,这些方法用于在内存区上执行各种标准操作。

  • 在创建和删除内存区域时,会分别调用open close函数。一般我们设置为NULL,表示不使用这个接口。
  • fault是最终要的一个方法,当访问地址空间的某个虚拟地址时,还没有做物理内存映射(或者是没有page没有写权限),自动触发的缺页异常管理最终会调用到该函数。这个函数会处理地址映射,数据读取,copy on write.

vm_pgoffset:指定了文件映射的偏移量,该值只用于映射了文件部分内容时(如果映射了整个文件,那么偏移量为0)

vm_file:指向映射文件的file object的指针,如果vm映射的是一个文件。如果映射的对象不是文件爱你,否则为NULL

vm_private_data:用于存储私有数据,不由通用内存管理程序操作。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值