文章目录

  • 一、引出概念
  • 二、Linux下数据大致是这样管理
  • 三、mm_struct
    • 一、Linux下查看mm_struct
    • 二、mm_struct是什么?
    • 三、mm_struct
  • 四、vm_area_struct
  • 五、vm_operations_struct
  • 六、图解(在网上看到的,画的很具体就用上了)

一、引出概念

先看代码

   #include<stdio.h>#include<unistd.h>#include<errno.h>int g_val = 0;int main(){pid_t pid;pid = fork();if(pid < 0){perror("fork error\n");}else if(pid == 0){printf("this is child process...........\n");printf("g_val:%d g_val'adress: %p\n",g_val,&g_val);}else{printf("this is parent process..........\n");printf("g_val:%d g_val'adress: %p\n",g_val = 100,&g_val);sleep(5);}return 0;
}

看一下结果

我们看到g_val的值在父进程和子进程分别打印出不同的值,但是地址是相同的,我们所认知的是同一块物理地址空间数据是一定相同的,但是,此时是不同的。说明这块空间不为物理地址。根据冯诺依曼体系结构可知,我们向磁盘写入数据有两种方式:一、直接写入磁盘;二、先写入缓冲区(内存),再让CPU去执行存储到磁盘。CPU是一个高效的处理器,磁盘是读写速率较慢的存储器,所以为了高速进行,采取第二种写入方式。内存的数据是虚拟,不具永久性,断电就会消失。那么,这里面数据不同,但是,地址相同。所以两个进程是在内存中。我们知道task_struct结构体里有一项成员叫做mm_struct——虚拟地址空间。

二、Linux下数据大致是这样管理

三、mm_struct

一、Linux下查看mm_struct

vim /usr/src/kernels/3.10.0-514.26.2.el7.x86_64/include/linux/mm_types.h
注:kernels不同对应路径里的3.10.0-514.26.2.el7.×86_64不同。

二、mm_struct是什么?

操作系统运用了面向对象的思路对mm_struct进行封装,Linux就是通过mm_struct实现了内存管理。一个进程的虚拟地址空间主要由两个数据结构进行描述,一个是mm_struct,另一个是vm_area_struct。mm_struct描述的是虚拟地址的整体空间,vm_area_struct描述的是虚拟地址空间的一个区间(子集)。可以说,mm_struct结构是对整个用户空间的描述。

在进程的task_struct结构体中包含一个指向mm_struct结构的指针,mm_struct用来描述一个进程的虚拟地址空间。进程的mm_struct则包含装入的可执行映像信息以及进程的页表目录指针pgd。该结构还包含有指向vm_area_struct结构的几个指针,每个vm_area_struct代表进程的一个虚拟地址区间。vm_area_struct结构含有指向vm_operations_struct结构的一个指针,vm_operations_struct描述了在这个区间的操作。vm_operations_struct结构中包含的是函数指针,其中open、close分别用于虚拟区间的打开、关闭,而nopage用于当虚拟页面不再物理内存而引起的”缺页异常”时所调用的函数,当Linux处理这一缺页异常时,就可以为新的虚拟内存分配实际的物理内存。

三、mm_struct

每个进程都只有一个内存描述符mm_struct。在每个进程的task_struct结构中,有一个指向mm_struct的变量,这个变量常常是mm。
mm_struct是对进程的地址空间(虚拟内存)的描述。一个进程的虚拟空间中可能有多个虚拟区间,对这些虚拟空间的组织方式有两种,当虚拟区较少时采用单链表,由mmap指针指向这个链表,当虚拟区间多时采用红黑树进行管理,由mm_rb指向这棵树。因为程序中用到的地址常常具有局部性,因此,最近一次用到的虚拟区间很可能下一次还要用到,因此把最近用到的虚拟区间结构放到高速缓存,这个虚拟区间就由mmap_cache指向。
指针pgt指向该进程的页表目录(每个进程都有自己的页表目录),当调度程序调度一个程序运行时,就将这个地址转换成物理地址,并写入控制寄存器。
由于进程的虚拟空间及下属的虚拟区间有可能在不同的上下文中受到访问,而这些访问又必须互斥,所以在该结构中设置了用于P,V操作的信号量mmap_sem。此外,page_table_lock也是为类似的目的而设置。
虽然每个进程只有一个虚拟空间,但是这个虚拟空间可以被别的进程来共享。如:子进程共享父进程的地址空间,而mm_user和mm_count就对其计数。
另外,还描述了代码段、数据段、堆栈段、参数段及环境段的起始和结束地址。

398 struct mm_struct {399   struct vm_area_struct * mmap;   /* list of VMAs */    //虚拟地址空间结构体,双向链表包含红黑树节点访问到不能访问的区域。400   struct rb_root mm_rb;                                 //红黑树的根节点401   struct vm_area_struct * mmap_cache; /* last find_vma result */  //mmap的高速缓冲器,指的是mmap最后指向的一个虚拟地址区间402 #ifdef CONFIG_MMU                                                                                                              403   unsigned long (*get_unmapped_area) (struct file *filp,404         unsigned long addr, unsigned long len,405         unsigned long pgoff, unsigned long flags);406   void (*unmap_area) (struct mm_struct *mm, unsigned long addr);407 #endif408   unsigned long mmap_base;    /* base of mmap area */                                       //mmap区域的基地址409   unsigned long mmap_legacy_base;         /* base of mmap area in bottom-up allocations */  //自底向上的配置410   unsigned long task_size;    /* size of task vm space */                                   //进程的虚拟地址空间大小411   unsigned long cached_hole_size;   /* if non-zero, the largest hole below free_area_cache */ //缓冲器的最大的大小412   unsigned long free_area_cache;    /* first hole of size cached_hole_size or larger */       //不受约束的空间大小413   unsigned long highest_vm_end;   /* highest vma end address */                             //虚拟地址空间最大结尾地址414   pgd_t * pgd;                                                                              //页表的全局目录415   atomic_t mm_users;      /* How many users with user space? */                             //有多少用户416   atomic_t mm_count;      /* How many references to "struct mm_struct" (users count as 1) */ //有多少用户引用mm_struct417   atomic_long_t nr_ptes;  /* Page table pages */                                       //页表418   int map_count;        /* number of VMAs */                                               //虚拟地址空间的个数419 420   spinlock_t page_table_lock;   /* Protects page tables and some counters */               //保护页表和用户421   struct rw_semaphore mmap_sem;                                                            //读写信号422 423   struct list_head mmlist;    /* List of maybe swapped mm's.  These are globally strung424              * together off init_mm.mmlist, and are protected425              * by mmlist_lock426              */427 428 429   unsigned long hiwater_rss;  /* High-watermark of RSS usage */                     //标志430   unsigned long hiwater_vm; /* High-water virtual memory usage */431 432   unsigned long total_vm;   /* Total pages mapped */433   unsigned long locked_vm;  /* Pages that have PG_mlocked set */434   unsigned long pinned_vm;  /* Refcount permanently increased */435   unsigned long shared_vm;  /* Shared pages (files) */436   unsigned long exec_vm;    /* VM_EXEC & ~VM_WRITE */                                                                          437   unsigned long stack_vm;   /* VM_GROWSUP/DOWN */438   unsigned long def_flags;439   unsigned long start_code, end_code, start_data, end_data;               //开始代码段,结束代码。开始数据,结束数据440   unsigned long start_brk, brk, start_stack;                              //堆的开始和结束。441   unsigned long arg_start, arg_end, env_start, env_end;                   //参数的起始和结束,环境变量的起始和终点442 443   unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */...
};

四、vm_area_struct

内存描述符mm_struct指向整个地址空间,vm_area_struct只是指向了虚拟空间的一段。vm_area_struct是由双向链表链接起来的,它们是按照虚拟地址降序排序的,每个这样的结构都对应描述一个地址空间范围。之所以这样分隔是因为每个虚拟区间可能来源不同,有的可能来自可执行映像,有的可能来自共享库,而有的可能是动态内存分配的内存区,所以对于每个由vm_area_struct结构所描述的区间的处理操作和它前后范围的处理操作不同,因此linux把虚拟内存分割管理,并利用了虚拟内存处理例程vm_ops来抽象对不同来源虚拟内存的处理方法。不同的虚拟区间其处理操作可能不同,linux在这里利用了面向对象的思想,即把一个虚拟区间看成是一个对象,用vm_area_struct描述这个对象的属性,其中的vm_operation结构描述了在这个对象上的操作。

  281 struct vm_area_struct {282   /* The first cache line has the info for VMA tree walking. */    //第一个高速缓存行包含VMA树便利的信息283 284   unsigned long vm_start;   /* Our start address within vm_mm. */ //虚拟地址空间vm_mm起始地址285   unsigned long vm_end;   /* The first byte after our end address  286              within vm_mm. */                                     //在vm_mm中结束地址的第一个字节287 288   /* linked list of VM areas per task, sorted by address */       289   struct vm_area_struct *vm_next, *vm_prev;                       //双向链表连接以便于遍历290
E>291   struct rb_node vm_rb;                                           //红黑树节点292 293   /*294    * Largest free memory gap in bytes to the left of this VMA.     //VMA左边最大的可用内存缺口295    * Either between this VMA and vma->vm_prev, or between one of the  296    * VMAs below us in the VMA rbtree and its ->vm_prev. This helps   //要么在当前的VMA和vma的前一个,要么是在VMA红黑树和它的前                                                                              一个中的VMAs之间297    * get_unmapped_area find a free area of the right size.        //这样有助于get_unmapped_area找到合适的空闲区域              298    */299   unsigned long rb_subtree_gap;                                  //红黑树子树的缺口300 301   /* Second cache line starts here. */302 302 303   struct mm_struct *vm_mm;  /* The address space we belong to. */   //进程拥有的地址空间
E>304   pgprot_t vm_page_prot;    /* Access permissions of this VMA. */   //此VMA访问权限305   unsigned long vm_flags;   /* Flags, see mm.h. */                  //标志306 307   /*308    * For areas with an address space and backing store,                                                                        309    * linkage into the address_space->i_mmap interval tree, or310    * linkage of vma in the address_space->i_mmap_nonlinear list.  //作为地址空间和后备存储区域,链接到间隔树或者链接到非线性链                                                                           表里的vma311    */312   union {313     struct {314       struct rb_node rb;315       unsigned long rb_subtree_last;316     } linear; //线性317     struct list_head nonlinear;  //链表非线性318   } shared;319 320   /*321    * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma322    * list, after a COW of one of the file pages.  A MAP_SHARED vma323    * can only be in the i_mmap tree.  An anonymous MAP_PRIVATE, stack324    * or brk vma (with NULL file) can only be in an anon_vma list. //MAP_SHARED只能                           在i_mmap树。匿名的对象,栈或者堆只能存在链表                                                                           里325    */326   struct list_head anon_vma_chain; /* Serialized by mmap_sem &327             * page_table_lock */      328   struct anon_vma *anon_vma;  /* Serialized by page_table_lock */329 330   /* Function pointers to deal with this struct. */331   const struct vm_operations_struct *vm_ops;               //虚拟内存332 333   /* Information about our backing store: */334   unsigned long vm_pgoff;   /* Offset (within vm_file) in PAGE_SIZE335              units, *not* PAGE_CACHE_SIZE */336   struct file * vm_file;    /* File we map to (can be NULL). */    //指向的文件337   void * vm_private_data;   /* was vm_pte (shared mem) */...};

五、vm_operations_struct

vm_operations_struct结构中封装的是函数指针,其中open、close分别是虚拟操作的打开、关闭,而nopage相当于default用于当虚拟内存页面没有实际的物理内存映射而引起的”缺页异常”时所调用的函数指针。

struct vm_operations_struct
{void (*open)(struct vm_area_strucr *area);void (*close)(struct vm_area_struct *area);struct page *(nopage)(struct vm_area_struct *area,unsigned long address,int unused);
}

六、图解(在网上看到的,画的很具体就用上了)

mm_struct(内存描述符)相关推荐

  1. 【Linux 内核 内存管理】虚拟地址空间布局架构 ③ ( 内存描述符 mm_struct 结构体成员分析 | mmap | mm_rb | task_size | pgd | mm_users )

    文章目录 一.mm_struct 结构体成员分析 1.mmap 成员 2.mm_rb 成员 3.get_unmapped_area 函数指针 4.task_size 成员 5.pgd 成员 6.mm_ ...

  2. 【Linux 内核 内存管理】虚拟地址空间布局架构 ② ( 用户虚拟地址空间组成 | 内存描述符 mm_struct 结构体源码 )

    文章目录 一.用户虚拟地址空间组成 二.内存描述符 mm_struct 结构体源码 一.用户虚拟地址空间组成 " 用户虚拟地址空间 " 包括以下区域 : ① 代码段 ② 数据段 ③ ...

  3. 【Linux 内核 内存管理】Linux 内核堆内存管理 ① ( 堆内存管理 | 内存描述符 mm_struct 结构体 | mm_struct 结构体中的 start_brk、brk 成员 )

    文章目录 一.堆内存管理 二.内存描述符 mm_struct 结构体 三.mm_struct 结构体中的 start_brk.brk 成员 一.堆内存管理 Linux 操作系统中的 " 堆内 ...

  4. Linux之内存描述符mm_struct

    Linux对于内存的管理涉及到非常多的方面,这篇文章首先从对进程虚拟地址空间的管理说起.(所依据的代码是2.6.32.60) 无论是内核线程还是用户进程,对于内核来说,无非都是task_struct这 ...

  5. 【Linux】虚拟地址空间 --- 虚拟地址、空间布局、内存描述符、写时拷贝、页表…

    该吃吃,该喝喝,遇事儿别往心上隔

  6. MDL 内存描述符链表

    友链 references: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_mdl https:/ ...

  7. Linux内核机制总结内存管理之用户页错误文件描述符(二十八)

    文章目录 1 用户页错误文件描述符 1.1 使用方法 1.2 技术原理 重要:本系列文章内容摘自<Linux内核深度解析>基于ARM64架构的Linux4.x内核一书,作者余华兵.系列文章 ...

  8. Linux进程描述符task_struct结构体详解--Linux进程的管理与调度(一)

    转自:http://blog.csdn.net/gatieme/article/details/51383272 日期 内核版本 架构 作者 GitHub CSDN 2016-05-12 Linux- ...

  9. 进程管理—进程描述符(task_struct)

    本文章转载自:http://blog.csdn.net/qq_26768741/article/details/54348586?locationNum=4&fps=1 前言 当把一个程序加载 ...

最新文章

  1. TypeError: Class advice impossible in Python3. Use the @Implementer class decorator instead
  2. 使用Docker Compose 部署Nexus后提示:Unable to create directory /nexus-data/instance
  3. uchome 数据库结构 数据库字典
  4. Vue -- 项目报错整理(1):RangeError: Maximum call stack size exceeded
  5. 直接修改html文本页面没变化,VUE 直接通过JS 修改html对象的值导致没有更新到数据中解决方法分析...
  6. vmware 克隆centos 6.4网卡不识别
  7. 2021教师资格证中学科目二简答汇总分享
  8. QT最常用的字符串操作
  9. android打印动画,Android 中的转场动画及兼容处理
  10. salt 源码之 salt-minion启动过程
  11. 自动生成小学四则运算题目(加强版)
  12. eclipse alt+/ 无效时,如何设置 《转》
  13. SpringBoot06 统一响应格式
  14. 常用连接Linux的SSH工具、SFTP工具
  15. 固定Vmware 虚拟机 系统时间
  16. keil C51代码优化等级介绍
  17. word插入图片之后只显示一部分的解决方法
  18. 神奇的零知识证明,既能保守秘密,又能让别人信你!
  19. 音诺恒RK3568高性能智能商显安卓广告机主板解决方案
  20. 设计模式之六:工厂方法模式(Factory method Pattern)

热门文章

  1. Navicat for MySQL 12破解
  2. 概率论 1.3 古典概型与几何概型
  3. Kafka实时数据同步
  4. 2003-2019年A股上市公司名义所得税率(Wind)
  5. python工程师是什么专业-python工程师的工作一般都在做什么?
  6. mysql定时执行任务
  7. 面向对象三大特性,五大原则
  8. C++生成正态分布随机数
  9. HTML基础选择器之属性选择器的基本介绍
  10. android listview 美化,Android界面美化 -- 自定义ListView分割线