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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏文渊之博

关于数据存储类型的一点分析

简介     SQL Server每个表中各列的数据类型的有各种形式,产生的效果也各有不同,我们主要根据效率兼顾性能的情况下讨论下如何规定类型。     在SQ...

1666
来自专栏猿人谷

对缓存的思考——提高命中率

开篇 编写高效的程序并不只在于算法的精巧,还应该考虑到计算机内部的组织结构,cpu微指令的执行,缓存的组织和工作原理等。 好的算法在实际中不见得有高效率,如果完...

1939
来自专栏xingoo, 一个梦想做发明家的程序员

Elasticsearch聚合初探——metric篇

Elasticsearch是一款提供检索以及相关度排序的开源框架,同时,也支持对存储的文档进行复杂的统计——聚合。 前言 ES中的聚合被分为两大类:Met...

17310
来自专栏orientlu

FreeRTOS 任务调度 系统节拍

文章 < FreeRTOS 任务调度 任务切换 > 记录了 FreeRTOS 中任务切换的过程, 提到触发任务切换的两种情况 : 高优先级任务就绪抢占和同优先...

593
来自专栏Linux驱动

32.Linux-2440下的DMA驱动(详解)

DMA(Direct Memory Access) 即直接存储器访问, DMA 传输方式无需 CPU 直接控制传输,通过硬件为 RAM 、I/O 设备开辟一条直...

2049
来自专栏我是攻城师

Apache Pig和Solr问题笔记(一)

3326
来自专栏IT派

Python 标准库之 LRU 缓存实现学习

LRU (Least Recently Used) 是缓存置换策略中的一种常用的算法。当缓存队列已满时,新的元素加入队列时,需要从现有队列中移除一个元素,LRU...

702
来自专栏青青天空树

EventBus轻松使用

  由greenrobot组织贡献(该组织还贡献了greenDAO),一个Android事件发布/订阅轻量级框架,功能:通过解耦发布者和订阅者简化Android...

552
来自专栏章鱼的慢慢技术路

《算法图解》第五章笔记与课后练习

1334
来自专栏性能与架构

快速了解 YAML

什么是 YAML? YAML 是一个数据序列化的标准,适用于所有开发语言,最大的特点是可读性好 YAML 的一个主要应用方向就是编写配置文件,有非常多的系统和框...

2975

扫描关注云+社区