• Linux之内存描述符mm_struct


    Linux对于内存的管理涉及到非常多的方面,这篇文章首先从对进程虚拟地址空间的管理说起。(所依据的代码是2.6.32.60)

    无论是内核线程还是用户进程,对于内核来说,无非都是task_struct这个数据结构的一个实例而已,task_struct被称为进程描述符(process descriptor),因为它记录了这个进程所有的context。其中有一个被称为'内存描述符‘(memory descriptor)的数据结构mm_struct,抽象并描述了Linux视角下管理进程地址空间的所有信息。
    mm_struct定义在include/linux/mm_types.h中,其中的域抽象了进程的地址空间,如下图所示:
      1 struct mm_struct {
      2     struct vm_area_struct * mmap;    //指向虚拟区间(VMA)的链表
      3     struct rb_root mm_rb;            //指向线性区对象红黑树的根
      4     struct vm_area_struct * mmap_cache;     //指向最近找到的虚拟区间
      5     unsigned long(*get_unmapped_area) (struct file *filp,
      6     unsigned long addr, unsigned long len,
      7     unsigned long pgoff, unsigned long flags);//在进程地址空间中搜索有效线性地址区
      8     unsigned long(*get_unmapped_exec_area) (struct file *filp,
      9         unsigned long addr, unsigned long len,
     10         unsigned long pgoff, unsigned long flags);
     11     void(*unmap_area) (struct mm_struct *mm, unsigned long addr);//释放线性地址区间时调用的方法
     12     unsigned long mmap_base;                /* base of mmap area */
     13     unsigned long task_size;                /* size of task vm space */
     14 
     15     unsigned long cached_hole_size;
     16     unsigned long free_area_cache;          //内核从这个地址开始搜索进程地址空间中线性地址的空闲区域
     17     pgd_t * pgd;                            //指向页全局目录
     18     atomic_t mm_users;                      //次使用计数器,使用这块空间的个数    
     19     atomic_t mm_count;                      //主使用计数器
     20     int map_count;                          //线性的个数
     21     struct rw_semaphore mmap_sem;           //线性区的读/写信号量
     22     spinlock_t page_table_lock;             //线性区的自旋锁和页表的自旋锁
     23 
     24     struct list_head mmlist;              //指向内存描述符链表中的相邻元素
     25 
     26     /* Special counters, in some configurations protected by the
     27     * page_table_lock, in other configurations by being atomic.
     28     */
     29     mm_counter_t _file_rss; //mm_counter_t代表的类型实际是typedef atomic_long_t
     30     mm_counter_t _anon_rss;  
     31     mm_counter_t _swap_usage;
     32 
     33     unsigned long hiwater_rss;    //进程所拥有的最大页框数
     34     unsigned long hiwater_vm;     //进程线性区中最大页数
     35 
     36     unsigned long total_vm, locked_vm, shared_vm, exec_vm;
     37     //total_vm 进程地址空间的大小(页数)
     38     //locked_vm 锁住而不能换出的页的个数
     39     //shared_vm 共享文件内存映射中的页数
     40 
     41     unsigned long stack_vm, reserved_vm, def_flags, nr_ptes;
     42     //stack_vm 用户堆栈中的页数
     43     //reserved_vm 在保留区中的页数或者在特殊线性区中的页数
     44     //def_flags 线性区默认的访问标志
     45     //nr_ptes 进程的页表数
     46 
     47     unsigned long start_code, end_code, start_data, end_data;
     48     //start_code 可执行代码的起始地址
     49     //end_code 可执行代码的最后地址
     50     //start_data已初始化数据的起始地址
     51     // end_data已初始化数据的最后地址
     52 
     53     unsigned long start_brk, brk, start_stack;
     54     //start_stack堆的起始位置
     55     //brk堆的当前的最后地址
     56     //用户堆栈的起始地址
     57 
     58     unsigned long arg_start, arg_end, env_start, env_end;
     59     //arg_start 命令行参数的起始地址
     60     //arg_end命令行参数的起始地址
     61     //env_start环境变量的起始地址
     62     //env_end环境变量的最后地址
     63 
     64     unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
     65 
     66     struct linux_binfmt *binfmt;
     67 
     68     cpumask_t cpu_vm_mask; //用于惰性TLB交换的位掩码
     69     /* Architecture-specific MM context */
     70     mm_context_t context; //指向有关特定结构体系信息的表
     71 
     72 
     73     unsigned int faultstamp;
     74     unsigned int token_priority;
     75     unsigned int last_interval;
     76 
     77     unsigned long flags; /* Must use atomic bitops to access the bits */
     78 
     79     struct core_state *core_state; /* coredumping support */
     80 #ifdef CONFIG_AIO
     81     spinlock_t              ioctx_lock;  //用于保护异步I/O上下文链表的锁
     82     struct hlist_head       ioctx_list;//异步I/O上下文
     83 #endif
     84 #ifdef CONFIG_MM_OWNER
     85     struct task_struct *owner;
     86 #endif
     87 
     88 #ifdef CONFIG_PROC_FS
     89     unsigned long num_exe_file_vmas;
     90 #endif
     91 #ifdef CONFIG_MMU_NOTIFIER
     92     struct mmu_notifier_mm *mmu_notifier_mm;
     93 #endif
     94 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
     95     pgtable_t pmd_huge_pte; /* protected by page_table_lock */
     96 #endif
     97 #ifdef __GENKSYMS__
     98     unsigned long rh_reserved[2];
     99 #else
    100     //有多少任务分享这个mm OOM_DISABLE
    101     union {
    102         unsigned long rh_reserved_aux;
    103         atomic_t oom_disable_count;
    104     };
    105 
    106     /* base of lib map area (ASCII armour) */
    107     unsigned long shlib_base;
    108 #endif
    109 };

     Reference:

    http://www.cnblogs.com/Rofael/archive/2013/04/13/3019153.html

    http://blog.csdn.net/persistence_s/article/details/70179419

  • 相关阅读:
    如何把新加的分区挂载到指定目录下
    怎样通过U盘安装启动Centos6.8
    Redis 单机安装【一】
    Linux漏洞扫描工具【lynis】
    mysql 主从 重新同步
    Centos 6.8下安装oracle10g数据库、
    监控服务supervisor服务的安装及使用
    制作c#桌面应用程序 安装程序 卸载程序
    Microsoft Visual SourceSafe 2005 服务端安装配置过程以及出现的问题,以及解决方法!
    .NET中的CSV导入导出
  • 原文地址:https://www.cnblogs.com/linhaostudy/p/7484587.html
Copyright © 2020-2023  润新知