进程虚拟地址管理

文章目录

  • 1 地址分布
    • 实际使用中的内存区域
  • 2 进程的虚拟地址描述
    • 用户空间mmap
    • 线程之间共享内存地址的实现机制

1 地址分布

在这里插入图片描述
现在采用虚拟内存的操作系统通常都使用平坦地址空间,平坦地址空间是指地址空间范围是一个独立的连续空间(比如,地址从0扩展到429496729位地址空间),对于32位的操作系统而言,每个进程的虚拟地址空间都是0x00000000~0xC0000000,合计3G大小。

进程的3G虚拟地址空间只有映射为物理地址空间,才能够被使用,那么进程是如何管理和分配它的3G虚拟地址空间呢?
在这里插入图片描述
这就用到了分治思想,进程虚拟地址空间按照不同的访问属性和功能划分为不同的内存区域,我们也叫虚拟内存区域(VMA)。
内存区域可以包含各种内存对象,比如:

  • 代码段(text section):可执行文件的内存映射
  • 数据段:可执行文件的已初始化全局变量和静态局部变量的内存映射
  • bss段:未初始化的或者值为0的变量的内存映射
  • lib库的代码段:(多个)
  • lin库的数据段:(多个)
  • lib库的bss段:(多个)
  • 任何内存映射文件(有名mmap建立)
  • 任何共享内存段(匿名mmap建立)
  • 进程栈(stack)
  • 进程堆(heap)

实际使用中的内存区域

可以使用/proc文件系统和pmap工具查看给定进程的内存空间和其中所包含的内存区域。

#include <stdio.h>
#include <unistd.h>int main(void)
{printf("PID=%d\n",getpid());while(1){sleep(2);}return 0;
}

运行该程序,输入命令 cat /proc/<pid>/maps查看进程地址空间中的全部内存区域(我的机子是64位,所以使用的是64位虚拟地址空间)
在这里插入图片描述

进程的内存区域由vm_area_struct结构体描述,定义在文件linux/mm.h中

struct vm_area_struct {struct mm_struct * vm_mm;	/* The address space we belong to. */unsigned long vm_start;		/* Our start address within vm_mm. */unsigned long vm_end;		/* The first byte after our end addresswithin vm_mm. *//* linked list of VM areas per task, sorted by address */struct vm_area_struct *vm_next;pgprot_t vm_page_prot;		/* Access permissions of this VMA. */unsigned long vm_flags;		/* Flags, listed below. */struct rb_node vm_rb;/** For areas with an address space and backing store,* linkage into the address_space->i_mmap prio tree, or* linkage to the list of like vmas hanging off its node, or* linkage of vma in the address_space->i_mmap_nonlinear list.*/union {struct {struct list_head list;void *parent;	/* aligns with prio_tree_node parent */struct vm_area_struct *head;} vm_set;struct prio_tree_node prio_tree_node;} shared;/** A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma* list, after a COW of one of the file pages.  A MAP_SHARED vma* can only be in the i_mmap tree.  An anonymous MAP_PRIVATE, stack* or brk vma (with NULL file) can only be in an anon_vma list.*/struct list_head anon_vma_node;	/* Serialized by anon_vma->lock */struct anon_vma *anon_vma;	/* Serialized by page_table_lock *//* Function pointers to deal with this struct. */struct vm_operations_struct * vm_ops;/* Information about our backing store: */unsigned long vm_pgoff;		/* Offset (within vm_file) in PAGE_SIZEunits, *not* PAGE_CACHE_SIZE */struct file * vm_file;		/* File we map to (can be NULL). */void * vm_private_data;		/* was vm_pte (shared mem) */#ifdef CONFIG_NUMAstruct mempolicy *vm_policy;	/* NUMA policy for the VMA */
#endif
};

上面的图片中,输出由六列,每一列都是vm_area_struct的一项

内核vm_area_struct中的项/proc/pid/maps中的项及其含义
vm_start第一列’-'前的数字,如55c4b4d68000 ,表示该虚拟内存区域的开始地址
vm_end第一列’-'后的数字 ,如55c4b4d69000 ,表示该虚拟内存区域的结束地址
vm_flags第二列,如r-xp,表示该虚拟内存区域的属性,每种属性用一个字段表示,r表示可读,w表示可写,x表示可执行,p和s共用一个字段,p表示私有段,s表示共享段,如果没有相应权限,用’-'代替
vm_pgoff第三列,如00001000,含义:对用有名映射,表示此虚拟内存起始地址在文件中以页为单位的编译,对匿名映射,它等于0或者vm_start/PAGE_SIZE
vm_file->f_dentry->d_inode->i_sb->s_dev第四列,如08:01,表示映射文件所属设备号,对匿名映射来说,因为没有文件在磁盘上,所有没有设备号,始终为00:00,对有名映射来说,是映射的文件所在设备的设备号
vm_file->f_dentry->d_inode->i_ino第五列,如1724853,含义:映射文件所属节点号,对匿名文件来说,因为没有节点号,所以时钟是0,对有名映射来说,是映射文件的结点号
第六列,如/lib/x86_64-linux-gnu/libc-2.27.so,对有名映射来说,是映射的文件名,对匿名映射来说,是此段虚拟内存在进程中的角色,stack表示在进程中作为栈使用,heap表示堆

2 进程的虚拟地址描述

内核使用mm_struct来描述一个进程的地址空间,进程的地址空间由多个VMA组成,下面列举几个mm_struct管理内存的几个重要域:

struct mm_struct {.../* 指向虚拟内存区域的链表 */struct vm_area_struct * mmap;		/* list of VMAs *//* 指向最近找到的虚拟内存区域 */struct vm_area_struct * mmap_cache;	/* last find_vma result *//* 指向该进程的页目录表 */pgd_t * pgd;...
};

VMA用struct vm_area_struct描述,内核将每个内存区域作为一个单独的内存对象管理,每个内存区域都有一致的属性,比如权限等。所以我们程序的代码段、数据段和bss段在内核里都分别有一个struct vm_area_struct结构体来描述。

在这里插入图片描述
进程由结构体task_struct描述,task_struct里面的mm域用来管理进程的内存,它指向mm_struct结构体,mm_struct的mmap域指向VMA链表,用来管理进程虚拟内存,虚拟内存地址又通过页表转换为物理地址,怎么转换的,由mm_struct的pgd页目录表来转换,从页目录表中找到物理地址。

用户空间mmap

 #include <sys/mman.h>void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);int munmap(void *addr, size_t length);

在用户空间使用mmap就是给进程添加一个虚拟内存区域,即在VMA链表中添加一个vm_area_struct结构

线程之间共享内存地址的实现机制

在Linux中,如果clone()时设备CLONE_VM标志,我们把这样的进程称作为线程,线程之间共享同样的虚拟内存空间。即将父进程的mm域复制给子进程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/379524.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

标题:加法变乘法

标题&#xff1a;我们都知道&#xff1a;123 … 49 1225 现在要求你把其中两个不相邻的加号变成乘号&#xff0c;使得结果为2015 比如&#xff1a; 123…10*1112…27*2829…49 2015 就是符合要求的答案。 请你寻找另外一个可能的答案&#xff0c;并把位置靠前的那个乘号左…

【翻译】eXpressAppFramework QuickStart 业务模型设计(四)—— 实现自定义业务类...

这一讲&#xff0c;你将学到如何从头开始实现业务类。为此&#xff0c;将要实现Department和Position业务类。这些类将被应用到之前实现的Contact类中。你将学到引用对象自动生成用户界面的基本要素。 在此之前&#xff0c;我建议你去阅读一下 【翻译】eXpressAppFramework Qui…

内存重映射

文章目录1 kmap2 映射内核内存到用户空间使用remap_pfn_range使用io_remap_pfn_rangemmap文件操作建立VMA和实际物理地址的映射mmap 之前分配 一次性映射mmap 之前分配 Page FaultPage Fault 中分配 映射内核内存有时需要重新映射&#xff0c;无论是从内核到用户空间还是从内…

math.sqrt 有问题_JavaScript中带有示例的Math.sqrt()方法

math.sqrt 有问题JavaScript | Math.sqrt()方法 (JavaScript | Math.sqrt() Method) The Math.sqrt() method is inbuilt in JavaScript to find the square root of a number. In this tutorial, we will learn about the sqrt() method with examples. JavaScript中内置了Mat…

ISAPI Rewrite 实现简单url重写、二级域名重写

实现步骤&#xff1a; 第一步&#xff1a;下载ISAPI_Rewrite.rar&#xff0c;将Rewrite文件夹和httpd.ini直接放在项目根目录下面。 第二步&#xff1a;IIS配置&#xff0c;筛选Rewrite文件夹里面的Rewrite.dll文件&#xff0c;如图&#xff1a; 第三步&#xff1a;在httpd.ini…

用户登录

用户登录 代码namespace 用户登录 {public partial class Form1 : Form{public Form1(){InitializeComponent();}bool b1, b2, b3, b4, b5, b6;private void button1_Click(object sender, EventArgs e){try{if (b1 && b2 && b3 && b4 && b5 &…

进程上下文和中断上下文

文章目录进程的preempt_count变量thread_infopreempt_counthardirq相关softirq相关上下文原文链接&#xff1a; https://zhuanlan.zhihu.com/p/88883239进程的preempt_count变量 thread_info 在内核中&#xff0c;上下文的设置和判断接口可以参考 include/linux/preempt.h 文…

标题:凑算式

标题&#xff1a;凑算式 这个算式中AI代表19的数字&#xff0c;不同的字母代表不同的数字。 比如&#xff1a; 68/3952/714 就是一种解法&#xff0c; 53/1972/486 是另一种解法。 这个算式一共有多少种解法&#xff1f; 注意&#xff1a;你提交应该是个整数&#xff0c;不要…

Linux内存地址管理

文章目录系统内存布局内核地址的低端和高端内存概念低端内存高端内存地址转换和MMULinux中的四级分页模型虚拟地址字段页表处理将虚拟地址转换物理地址Linux系统中的每个内存地址都是虚拟的&#xff0c;它们不直接指向任何物理内存地址。每当访问内存位置时&#xff0c;可以执行…

录制caf 转 mp3

编译需要使用的 lame库http://www.cocoachina.com/bbs/read.php?tid108237参考的文章http://blog.csdn.net/ysy441088327/article/details/7392842说起来&#xff0c;我一直在找一个音频转换成mp3的方法。一年前&#xff0c;我成功编译出了一个lame for armv7的库。苦于不会使…

開發記要 詭異的變量

告別繁體文盲,從寫blog開始 Variable命名很重要,有多重要,看看.net和java的加密就知道, 都是把variable改到一塌糊塗,你想看看都沒門. 但是這幾天看遺留系統的代碼,真是大開眼界。 我一直以為別人寫a,b,c,d這些單字節variable已經很過分。直到我看到以下這幾個&#xff0…

排序算法---快速排序、堆排序、冒泡排序

排序算法1 快速排序代码实现stdlib库快排2 堆排序堆排序的基本思想如何构造一个大顶堆排序3 冒泡排序1 快速排序 文章原地址&#xff1a;https://blog.csdn.net/morewindows/article/details/6684558 快速排序的平均时间复杂度是0(NlogN)&#xff0c;它采用了一种分治的策略&a…

项目总结:华南师范大学校园开发教育android客户端总结

忽略之前小打小闹&#xff0c;这个项目算是我的第一个项目--SCNU的网络公选课的android版本的客户端。项目是从5月中旬开始的&#xff0c;中间经历了几个星期的复习考试时间&#xff0c;到现在可以说是完工了吧&#xff08;或许还有写细节要修改&#xff09;。这个项目带给我蛮…

Linux系统编程---守护进程

1 守护进程的概述 Daemon&#xff08;守护进程&#xff09;是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。它不需要用户输入就能运行而且提供某种服务&#xff0c;不是对整个系统就是对某个用户程序提供服务。Linux系统的大…

邮箱服务器

一&#xff0e;邮箱服务器的基本概念 邮件的客户端&#xff1a;可以只安装在电脑上&#xff08;C/S&#xff09;的也可以是网页形式&#xff08;B/S&#xff09;的 邮件服务器&#xff1a;起到邮件的接受与推送的作用 邮件发送的协议&#xff1a; 协议&#xff1a;就是数据传输…

类加载器

一、类加载器 1&#xff0c;什么是类加载器&#xff1f; 类加载器就是用来加载字节码文件 2&#xff0c;类加载器的种类有哪些&#xff1f; 1&#xff09;BootStrap&#xff1a;引导类加载器&#xff1a;加载都是最基础的文件 2&#xff09;ExtClassLoader&#xff1a;扩展类加…

算法---链表

文章目录反转链表合并两个有序链表删除重复元素反转链表 反转链表包括两种&#xff0c;反转全部元素或者反转部分元素。在这里&#xff0c;我们约定&#xff1a;数据元素类型是struct LinkNode&#xff0c;要反转链表的第一个节点是head&#xff0c;head的前面一个节点是pre&a…

SSM

二、环境设置&#xff08;MyEclipse&#xff09; 1&#xff0c;字体设置 window–>Preference->General->Appearance->Colors and Fonts->Basic Text->Font 2&#xff0c;workspace字符集设置 window–>Preference->General->Appearance->W…

设计模式--Strategy 策略模式

所谓策略模式(Strategy Pattern)&#xff0c;就是将策略 (算法) 封装为一个对象&#xff0c;易于相互替换&#xff0c;如同 USB 设备一样可即插即用&#xff1b;如果将策略、具体的算法和行为&#xff0c;编码在某个类或客户程序内部&#xff0c;将导至事后的修改和扩展不易。 …

打开eclipse出现Failed to load the JNI shared library “D:\java\jdk\bin\...\jre\bin\server\jvm.dll”如何解决?

eclipse打开的时候出现Failed to load the JNI shared library “D:\java\jdk\bin…\jre\bin\server\jvm.dll”如何解决&#xff1f;&#xff1f; 如图所示&#xff1a; 即代表你的jdk与eclipse的位数不一样&#xff01;&#xff01;&#xff01; 你可以查看一下eclipse和jd…