Linux之内存描述符mm_struct
时间:2022-05-03
本文章向大家介绍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
- 入门Webpack(上)
- 碎片化 | 第四阶段-56-ManyToOne和OneToMany映射关系-视频
- 基于网络流量的SDN最短路径转发应用
- 碎片化 | 第四阶段-57-hibernate二级缓存-视频
- NoSQL篇 | NoSQL从小白到码神 之 Redis篇
- Neutron和ONOS集成实践
- 基于OpenDaylight和OVSDB搭建VxLAN网络
- 史上最强----机器学习经典总结---入门必读
- SDNLAB群分享(四):利用ODL下发流表创建VxLAN网络
- Neutron集成ONOS源码分析
- “访问限制”&“代理访问”实验
- OpenDaylight Lithium-SR2 Cluster集群搭建
- Linux | CentOS7下会玩JDK不?你确定?
- Linux | 不懂Linux的码神,不是真正的菜鸟
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 链表:一道题目考察了常见的五个操作!
- 性能测试必备知识(11)- 怎么理解内存中的Buffer和Cache?
- 神经网络-感知器(二):Python代码实现
- Kylin、Druid、ClickHouse 核心技术对比
- 在线教育系统开发中,如何实现作业功能字体自定义?
- 保护模式第六讲-IDT表-中断门 陷阱门 任务门
- 跟牛老师一起学WEBGIS——GIS基础(QGIS中数据的创建与编辑)
- Qt信号与槽使用方法最完整总结
- 玩转 PhpStorm 系列(十二):单元测试篇
- 使用Notepad++代替笨拙的Arduino IDE
- mimikatz的使用
- Arduino数字引脚作为GPIO的使用
- TikTok 用什么算法传输并加密内容?
- 如何编写自己的Arduino库?
- 玩转 PhpStorm 系列(十一):编码风格篇