进程地址空间也就是每个进程所使用的内存,内核对进程地址空间的管理,也就是对用户态程序的内存管理。

主要内容

  • 地址空间(mm_struct)
  • 虚拟内存区域(VMA)
  • 地址空间和页表

 

1. 地址空间(mm_struct)

地址空间就是每个进程所能访问的内存地址范围。

这个地址范围不是真实的,是虚拟地址的范围,有时甚至会超过实际物理内存的大小。

 

现代的操作系统中进程都是在保护模式下运行的,地址空间其实是操作系统给进程用的一段连续的虚拟内存空间。

地址空间最终会通过页表映射到物理内存上,因为内核操作的是物理内存。

 

虽然地址空间的范围很大,但是进程也不一定有权限访问全部的地址空间(一般都是只能访问地址空间中的一些地址区间),

进程能够访问的那些地址区间也称为 内存区域。

进程如果访问了有效内存区域以外的内容就会报 “段错误” 信息。

 

内存区域中主要包含以下信息:

  • - 代码段(text section),即可执行文件代码的内存映射
  • - 数据段(data section),即可执行文件的已初始化全局变量的内存映射
  • - bss段的零页(页面信息全是0值),即未初始化全局变量的内存映射
  • - 进程用户空间栈的零页内存映射
  • - 进程使用的C库或者动态链接库等共享库的代码段,数据段和bss段的内存映射
  • - 任何内存映射文件
  • - 任何共享内存段
  • - 任何匿名内存映射,比如由 malloc() 分配的内存

bss是 block started by symbol 的缩写。

 

linux中内存相关的概念稍微整理了一下,供参考:

英文

含义

SIZE 进程映射的内存大小,这不是进程实际使用的内存大小
RSS(Resident set size) 实际驻留在“内存”中的内存大小,不包含已经交换出去的内存
SHARE RSS中与其他进程共享的内存大小
VMSIZE 进程占用的总地址空间,包含没有映射到内存中的页
Private RSS 仅由进程单独占用的RSS,也就是进程实际占用的内存

 

1.1 mm_struct介绍

linux中的地址空间是用 mm_struct 来表示的。

下面对其中一些关键的属性进行了注释,有些属性我也不是很了解......

struct mm_struct {
    struct vm_area_struct * mmap;        /* [内存区域]链表 */
    struct rb_root mm_rb;               /* [内存区域]红黑树 */
    struct vm_area_struct * mmap_cache;    /* 最近一次访问的[内存区域] */
    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);  /* 取消地址 addr 的映射 */
    unsigned long mmap_base;        /* 地址空间中可以用来映射的首地址 */
    unsigned long task_size;        /* 进程的虚拟地址空间大小 */
    unsigned long cached_hole_size;     /* 如果不空的话,就是 free_area_cache 后最大的空洞 */
    unsigned long free_area_cache;        /* 地址空间的第一个空洞 */
    pgd_t * pgd;                        /* 页全局目录 */
    atomic_t mm_users;            /* 使用地址空间的用户数 */
    atomic_t mm_count;            /* 实际使用地址空间的计数, (users count as 1) */
    int map_count;                /* [内存区域]个数 */
    struct rw_semaphore mmap_sem;   /* 内存区域信号量 */
    spinlock_t page_table_lock;        /* 页表锁 */

    struct list_head mmlist;        /* 所有地址空间形成的链表 */

    /* 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_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */

    struct linux_binfmt *binfmt;

    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 */
#ifdef CONFIG_AIO
    spinlock_t        ioctx_lock;
    struct hlist_head    ioctx_list;
#endif
#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/<pid>/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
};
View Code

相关文章: