Linux——进程地址空间,写时拷贝,进程独立性

news/2024/11/28 13:47:05/

Linux进程内存分布

验证地址空间排布


结论:堆区向地址增大的方向增长,栈区向地址减少的方向增长。局部变量通常保存在栈上,先定义的先入栈,地址是比较高的,后定义的则地址小。

static变量

作用域不变,生命周期改变,如何改变?
编译器会把静态变量放到全局区。静态变量和全局变量的存在同一块空间的,但是只有在函数内才可见。

进程地址空间

每一个进程被运行的时候,操作系统都会为其创建进程地址空间,也会建立各自的页表。虚拟地址空间是物理地址的映射。
如何管理地址空间?
先描述再组织。进程地址空间实际上也是内核中的一个数据结构,mm_struct。
虚拟地址和物理地址之间会有一个页表用于建立映射关系。

mm_struct和vm_area_struct

mm_struct是虚拟地址空间,vm_area_struct是用于划分区域的。
task_struct里有一个mm_struct指针指向虚拟地址空间结构体。
mm_struct里有一个vm_area_struct指针指向mmap,维护了虚拟地址空间的各个区域,来划分每一个区域(栈、堆、代码区)的起点与终点。

unsigned long total_vm, locked_vm, shared_vm, exec_vm;unsigned long stack_vm, reserved_vm, def_flags, nr_ptes;unsigned long start_code, end_code, start_data, end_data;unsigned long start_brk, brk, start_stack;unsigned long arg_start, arg_end, env_start, env_end;

标识每个区域的起始和终止地址范围。
这里的地址作为页表的K值来与物理地址建立映射。
页表是进程加载到程序的时候自动建立的。通过页表的K值找到实际物理内存里的数据。

程序是如何被加载变成进程的?

程序被编译后,还没被加载,此时程序内部有地址和区域吗?
有!链接就是把程序内部函数的地址和库中函数的地址关联起来。
编译后区域已经划分好了,变量放在对应的区域。除了堆区和栈区是加载到内存之后才有的。

进程本身中的代码也会有地址,但是这个地址是虚拟地址,在页表中作为K值,经过映射,加上偏移量,就能找到实际占用操作系统资源的地址。

比如程序中函数的代码的地址在程序中已经确定,为0x100,加载到内存后,这个地址加上了偏移量10000,放在了内存上的代码区。进程开始后,运行到这里,就要到物理内存中的0x10100中去找。编译后代码的位置已经确定,放到内存中又是一回事,因此要加上偏移量放到物理内存上。

fork的返回值


修改子进程val后父进程的val不变,同一地址的变量会有两个值?

很显然,在C/C++中的地址并不是内存物理上的地址,而是操作系统提供的虚拟地址,操作系统不允许直接读取物理内存。虚拟地址是一样的,但是物理地址是不一样的。

val是父进程的栈空间中的变量,fork函数return会被执行两次,return的本质就是通过寄存器赋值。当父子各自执行return,会发生写时拷贝。

写时拷贝

进程具有独立性,为了保证进程间数据独立,进程间不相互干扰,会有数据的写时拷贝,得到一张新的页表。在上面的程序中,变量的物理地址实际就不同了,因此数据也是不同的。

为什么要写时拷贝?

为什么不创建子进程的时候就写时拷贝?
在数据被修改的时候再深拷贝,而不是一开始就全部拷贝下来,因为可能数据都是只读的,可以节省空间。
最理想的是:只拷贝父进程中会被修改的数据,但是这是无法预测的,因此只能采用写时拷贝这种方式妥协。

代码会不会有写时拷贝?
如果涉及程序替换的时候就会。

为什么要有进程地址空间?

保证进程的独立性

有了自己的虚拟空间之后,就不会有任何系统级别的越界问题存在了。对某一地址空间进行操作之前需要先通过页表映射到物理内存,而页表只会映射属于各个进程自己的物理内存。

解耦了虚拟地址和物理地址

每个进程都认为拥有相同的空间范围,认为自己在独占内存,包括进程地址空间的构成和内部区域的划分顺序等都是相同的,编写程序的时候就只需关注虚拟地址,而无需关注数据在物理内存当中实际的存储位置。

进一步完善进程的独立性以及合理分配内存空间(当实际需要使用内存空间的时候再在内存进行开辟),并能将进程调度与内存管理进行解耦或分离。

比如Linux下向系统malloc申请空间时,系统不会立即真实分配,而只是修改vm_area中的起点和终点,因为怕用户占着不用浪费资源,而是在用户调用到的时候再立刻申请,建立页表映射关系。


http://www.ppmy.cn/news/559745.html

相关文章

PotPlayer:最强播放器,无边框

下载地址: 链接:https://pan.baidu.com/s/1QnuCm1OTOJompZJDuF2gFg 提取码:3elw 1.无边框简约皮肤 如果有人问这款播放器的优点有哪些? 很多人可能会说启动速度快,解码能力强,耗内存低,无广告…

PotPlayer下载

PotPlayer官网:https://potplayer.daum.net/ 32位 下载:https://t1.daumcdn.net/potplayer/PotPlayer/Version/Latest/PotPlayerSetup.exe64位 下载:https://t1.daumcdn.net/potplayer/PotPlayer/Version/Latest/PotPlayerSetup64.exe 点击…

BiuBiu播放器「修复版」

第一次进入软件,或出现下面的提示,自行选择适合的模式。 以电视模式举个例子,点击【设置】 在第一个【全局接口】输入给大家提供的影视源地址。 这时候就可以爽起来了,各种影视资源都可以免费看。 急速秒播无缓冲,画质…

一款简洁的 jplayer 音乐播放器完整版

一款简洁 jplayer 音乐播放器&#xff0c;做音乐站很漂亮&#xff0c;直接套用就好了。 效果图&#xff1a; 部分源代码&#xff1a; <div id"lei_jplayer"></div> <div id"jp_container_1"><div class"jp-controls">…

kodi没有中文设置_kodi播放器如何设置为中文界面-kodi播放器设置中文的方法 - 河东软件园...

KODI播放器是一款强大的多媒体播放器&#xff0c;其能够支持目前几乎所有的主流格式文件的播放&#xff0c;而且除了视频文件外&#xff0c;即使是音乐、图片、电视节目等其他媒体文件也能够正常进行播放&#xff0c;而且能够支持投屏扥更种辅助功能&#xff0c;为用户提供了一…

优酷、腾讯视频播放器插件

优酷、腾讯视频播放器插件 js文件 /*** playVideo 1.0.4* https://github.com/zhouxitian/playVideo* author:zhouxitian163.com*/ eval(function(p,a,c,k,e,d){efunction(c){return(c<a?:e(parseInt(c/a)))((cc%a)>35?String.fromCharCode(c29):c.toString(36))};if(…

使用苹果原生视频播放器MPMoviePlayerController播放来自优酷等网页的视频

没有自己的流媒体服务器&#xff0c;又想在app中用原生视频播放器MPMoviePlayerController将视频插入到界面&#xff0c;在界面可以直接播放&#xff0c;或者全屏播放&#xff0c;可以通过以下方法实现 先创建原生播放器 _moviePlayer [[MPMoviePlayerController alloc] init…

优酷、腾讯视频播放器接口参数说明

优酷: 优酷的视频播放器接口连接为&#xff1a;http://open.youku.com/tools/ 里面已经有教详细的说明了。 在这里也做一些说明吧&#xff1a;导入js文件&#xff1a; 1 <script type"text/javascript" src"http://player.youku.com/jsapi"> 调用&…