网站设计师培训中心,广东加盟网站建设,唐山网站推广优化,怎么做企业网站平台#x1f381;个人主页#xff1a;我们的五年
#x1f50d;系列专栏#xff1a;Linux课程学习
#x1f337;追光的人#xff0c;终会万丈光芒
#x1f389;欢迎大家点赞#x1f44d;评论#x1f4dd;收藏⭐文章 Linux学习笔记#xff1a; https://blog.csdn.net/…个人主页我们的五年
系列专栏Linux课程学习
追光的人终会万丈光芒
欢迎大家点赞评论收藏⭐文章 Linux学习笔记 https://blog.csdn.net/djdjiejsn/category_12669243.html
前言 之前听过一遍课但是如今还对它很模糊不知道它到底是如何进行的。所以今天重新听课重新学习。进程地址空间话题很大这次也只能讲很少一部分能对进程地址空间的宏观了解就OK。 目录
一.小实验不是物理地址而是虚拟地址/线性地址
1.1实现目的和预想
1.2修改gval的值继续进行实验 二.虚拟地址是什么
2.1小故事画饼
2.2理解虚拟地址空间
2.3mm_struct结构体
2.4内存编址 三.页表
3.1代码共享
3.2页表和物理地址的映射
3.3页表中的标志位
3.3.1rwx权限
3.3.2isexit标记位
四.为什么要有虚拟地址页表
4.1安全和隐私保护
4.2进程管理和文件管理解耦合
4.3有效利用内存资源
4.4让进程以统一的视角看待物理内存 一.小实验不是物理地址而是虚拟地址/线性地址
Linux大哥你别骗我我之前一直给我的时物理地址没想到你给我一个虚拟的地址我真的看透你了。线性
路上的一个下BUG
刚刚在进行运行代码的时候运行结果没有输出一直卡在那我以为是出现什么错误了。结果是我没有换行因为我创建了子进程这时候的显示器文件缓冲区采取的刷新模式可能是满刷新当缓冲区满的时候才会进行刷新。所以一开始在显示器上没有看见东西。后面啪的一下出现很多内容。大概就是这个原因。啊哈哈哈哈哈。下面我又无知了请原谅我。
1.1实现目的和预想 因为之前不是说父进程和子进程的代码共享数据会独立一份吗现在我们创建一个子进程打印同一个值的地址是不是一样的按理来说他们地址是不一样的因为数据相互独立。但是真实的结果是如何呢 看上面的图我们居然发现他们的地址是一样啊这好像不对啊但好像又可以理解。我们之前学C的时候比如字符串string的拷贝的时候不会立马进行拷贝不会立即复制字符串的内容而是增加一个引用计数。这里好像也可以这样理解如果你不对数据进行修改那么我还是用原来的呗你要修改的时候我再给你申请空间进行赋值再让你修改呗那么我们下面就把gval的值修改一下看是不是地址会不一样。
好像结果不是这样的不是要写时拷贝是因为Linux大哥C语言给了我们一个虚拟的地址。
1.2修改gval的值继续进行实验
我们每次循环让子进程的gval发生变化他们的地址还是一样的。为什么会这样啊这就真的不能理解的啊上面我还能去想想可能是写时拷贝的原因在这里写时拷贝也关不上啊
#includestdio.h
#includesys/types.h
#includeunistd.h int gval100; int main()
{ printf(我是一个进程pid:%d , ppid:%d\n,getpid(),getppid()); pid_t idfork(); if(id0) { while(1) { printf(子进程,pid:%d,ppid:%d,gval:%d,gval:%p\n,getpid(),getppid(),gval,gval); sleep(1); } } else { while(1) { printf(父进程,pid:%d,ppid:%d,gval:%d,gval:%p\n,getpid(),getppid(),gval,gval);sleep(1); } }return 0; } 二.虚拟地址是什么 这不是程序地址空间哈这是进程地址空间。为了引入虚拟地址空间必须把老师说的小故事在这里重复一遍。 2.1小故事画饼
在美国有一个大富翁他很有钱手上有10亿美金并且他有很多孩子。有一天他的孩子A跑过来对他说我想要100美元。大富翁听到以后觉得没啥我都有10亿美金了这100美元能算啥就把这100美元给了A孩子。但是还没道A孩子的手上B孩子就冲过来把大富翁手上的100美元给抢走了B孩子说这100美元是我先看到的应该是我的。B孩子还没说完C孩子就抢着说B孩子都拿了100美元那我要200美元。A孩子听到以后觉得很不公平为什么最开始是我先找父亲要的钱你们反倒比我要的多为此A孩子说那我最起码也要200美元。大富翁听到以后非常头疼不知道该怎么办 在美国的另一边也有一个大富翁他很有钱也有10亿美元也有很多的孩子但是这些孩子都是他的私生子他们不知道彼此的存在都以为大富翁只有我这一个孩子。有一天大富翁跑到私生子A住的地方去看望A孩子然后发现A孩子在一家上市公司上班每天工作非常辛苦。大富翁对孩子A说好样的好好干以后我10亿美金全是你的孩子A听到以后非常的开心认为只要好好干以后父亲的10亿美金全是我的。
后面大富翁又跑到B私生子那里B孩子还在读大学他是他们学习篮球队的主力 为了以后能打进NBA每天训练也是非常的辛苦。大富翁看到以后对B孩子说好好打球只要你好好打球以后我的10亿美金也是你的。孩子B听到以后也是非常的开心觉得马上就能继承父亲的10亿美金了。
大富翁看望完B孩子以后就去看望私生子C了C孩子是女儿现在在读高中但是跳舞很厉害她的梦想是去当模特。大富翁看到C孩子以后也对C孩子说只要你好好跳以后我的10亿美金全部都是你的此时C孩子很开心……当然大富翁还有其他很多的私生子。
大富翁对每个私生子都是这么说的每个私生子都以为自己可以拿到父亲的10亿美金却不知道他们根本拿不到只能拿到一部分。
以后每个孩子在找父亲要钱的时候都会有一个潜台词就是父亲有10亿而且以后都是我的。
饼画多了也需要管理。先描述再组织。这个大富翁就是操作系统这里的大饼就是程序地址空间
2.2理解虚拟地址空间 假如内存大小是4GB一个进程过来申请了500MB此时这个进程认为还有3.5GB可以用。但是另外一个进程也申请了500MB这个进程也觉得它还有3.5GB可以申请其实此时内存的真实大小只有3GB了。 2.3mm_struct结构体 理解区域划分的本质 交代区域的开始和结束就能进行区域划分。 mm_struct中就有每个地址区域的地址空间。有起始位置和结束位置。
PCB中有一个mm_struct结果体指针指向一个mm_struct结构体。
mm_struct是由谁来初始化的?信息来源是可执行程序因为可执行程序被编译好就有需要多大的空间等信息。可以不加载可执行程序的内容但是这些信息必须被加载这些属于PCB的范畴。
栈区是运行的时候操作系统自己创建的由操作系统决定。
物理内存延迟开辟需要的时候先给你虚拟地址没有对应的物理地址只有当真正使用的时候才会填入物理地址形成映射。
2.4内存编址
最小内存寻址是计算机能访问的最小内存单元。内存是按字节来划分的32位系统中地址总线通常是32了能最大表示的地址范围是2的32次方的存储单位2的10次方是10242的32次方就表示4GB大小。
用unsigned long就能表示地址的所以范围这就是内存编码。 三.页表
3.1代码共享 当父进程创建子进程的时候子进程会拿父进程的PCB进行初始化mm_struct也相同页表也相同。页表中的代码区指向同样的物理地址所以形成了代码共享。父子映射道同样的内存代码区域。所以子进程也是看到fork以上的代码的只是不会执行它。 3.2页表和物理地址的映射
页表也被子进程继承所以最开始的虚拟地址和物理地址都是和父进程一样的用的还是父进程的代码和数据。当时当子进程的数据修改的时候在此之前操作系统OS会先申请空间给子进程用然后修改子进程中的页表物理地址虚拟地址不变。所以父子进程的有不同的页表向上返回的虚拟地址是一样的但是通过不同的页表能映射到不同的物理空间上去。所以就能解释上面小实验了。
在C语言中变量名就相当于地址。 3.3页表中的标志位 页表中会有很多的标记位下面就来谈谈rwx标记位和isexit标记位。 3.3.1rwx权限
rwx标记位可以设置权限比如代码区只能是只读的当如果要写页表不让你从虚拟地址映射到真实的物理地址了。还有可能直接杀死进程。在代码层面如果去修改一个只读区编译器是识别不出来的这是在运行时才会去发生映射才会报错。所以为了让编译器能检查就引入了const。
3.3.2isexit标记位
1.分批加载。2.挂起等操作。
表示在页表中这个映射关系是否存在是都能在内存中找到。因为有种种原因数据不会一直占着内存会被放回到磁盘中内存的大小是有限的。所以这个标记就是说是否在内存中存在。当不存在的时候如果要进行操作就会重新加载。所以才能跑大型程序。 四.为什么要有虚拟地址页表
野指针就是有一个虚拟地址在进行映射的时候发现找不到真实的物理地址或者权限不对就会发生错误。操作系统就可以控制该进程终止。
可执行程序的代码和数据可以加载到物理内存的任何地址处。有页表进行映射。
4.1安全和隐私保护
虚拟地址的设定可以避免程序直接访问物理内存。必须通过页表的映射才能知道物理内存。页表是操作系统来管理的。防止错误程序和恶意软件篡改内存数据增加系统的稳定性。
4.2进程管理和文件管理解耦合
进程在进行管理的时候操作的是虚拟地址不要去物理地址。这样就大大降低了程序开发的复杂度。
4.3有效利用内存资源
让进程都以为独占内存空间但是操作系统可以进行自由切换没用的时候就能从内存中放到磁盘中。
4.4让进程以统一的视角看待物理内存
代码和数据可以加载到物理内存的任意位置但是对于mm_struct一样还是相同的数据放在一起。
无序变有序。