网站公众号建设工具,广西壮族自治区人口,网站用动态图片做背景怎么写,营销展示型网站建设价格Linux|内存地址空间 现象基本概念理解如何理解地址空间什么是划分区域#xff1f;地址空间的理解为什么要有地址空间#xff1f;如何进一步理解页表和写时拷贝如何理解虚拟地址 Linux真正的进程调度方案 现象
#include stdio.h
#include string.h
#include … Linux|内存地址空间 现象基本概念理解如何理解地址空间什么是划分区域地址空间的理解为什么要有地址空间如何进一步理解页表和写时拷贝如何理解虚拟地址 Linux真正的进程调度方案 现象
#include stdio.h
#include string.h
#include unistd.h
#include stdlib.h
#includesys/types.h
int g_val 100;int main()
{printf(father is running, pid: %d, ppid: %d\n, getpid(), getppid());pid_t id fork();if(id 0){//childint cnt 0;while(1){printf(I am child process, pid: %d, ppid: %d. g_val: %d, g_val: %p\n, getpid(), getppid(), g_val, g_val);sleep(1);cnt;if(cnt 5){g_val 300;printf(I am child process, change %d - %d\n, 100, 300);}}}else{//fatherwhile(1){printf(I am father process, pid: %d, ppid: %d. g_val: %d, g_val: %p\n, getpid(), getppid(), g_val, g_val);sleep(1);}}
} 同一个地址但是值却不一样这是为什么呢我们可以得出一个最基本的结论就是我们看到的地址不是真实的物理地址
基本概念
操作系统为我们划分了4G的虚拟进程地址空间针对32位的机器 虚拟进程空间和真实的进程空间通过页表的映射联系起来 每一个进程都有自己的一份虚拟进程空间子进程会基础父进程的内核数据结构 内存空间是用来描述代码和数据的本质是操作内核中的一个数据结构 因为操作系统设计进程的时候要保证独立性子进程的数据是独立的子进程修改val的值的时候会发生写时拷贝 这也解释了为什么我们看到的地址一样值却不一样因为发生了写时拷贝虽然虚拟地址是一样的但是物理地址则不一样。 写实拷贝本质是一种按需申请如果把父进程内存空间的数据全部拷贝一份会浪费很多。比如命令行参数和环境变量几乎是不修改的。
理解
如何理解地址空间
什么是划分区域
上小学的的时候我们都会遇到这种情况就是和同桌划分三八线本来各占桌子的百分之五十但是一天你突发奇想想要把区域划分大一点。这怎么用计算机描述呢 我们可以定义一个区域的结构体来描述自己的区域大小。 另外一个结构体用来描述来个区域的信息。
struct area
{int startint end;
}typedef areastruct desk
{area left;area right;
}typedef deskdesk.left.end 20;
desk.right.start - 20;进程地址空间本质上也是一个结构体很多属性表示end 和start的范围。
地址空间的理解
操作系统给进程画的大饼 操作系统告诉每个进程你们可以使用整个的内存哦
为什么要有地址空间
实际中的物理内存中代码区数据区堆区栈区共享区命令行参数环境变量是杂乱存放的。页表和进程地址空间可以将无序变为有序。对进程管理模块和内存管理模块进行解耦。我们申请开辟空间只是在进程地址空间中调end的大小当使用时才真正的在内存中分配。这样做能提高内存的利用率拦截非法请求当我们访问内存时操作系统和硬件会在页表中寻找物理内存的位置但是当我们越界访问时就在页表中找不到对应的物理内存的位置操作系统就把这次访问内存的请求拦截了下来避免往内存中写入废旧的数据从而影响其他内存。
如何进一步理解页表和写时拷贝
页表里面有很多标记位比如能否读写的标记位是否在物理内存中的标记位 理解进程挂起就是把进程是否在物理内存中置为false了 解释 char *str “hello word” *str ‘H’ 在字符常量区为什么不能被修改呢 因为页表在映射时有权限管理
OS通过识别到错误比如父子进程对全局变量的权限都是r和w 父进程一旦创建了子进程对全局变量的权限都变为w 此时修改就会判断为错误来引发写时拷贝
先判断数据是不是在物理内存中看标记为是否ture如果不在发生缺页中断在内存中分配一个空间。这属于正常情况是不是需要写实拷贝怎么判断是否需要写实拷贝呢?通过引用计数的方式如果都不是才进行异常处理比如我们越界了地址就不页表的虚拟地址中
如何理解虚拟地址
最开始的时候页表里的数据从那里来的 我们知道程序里面本身就有地址 这个地址就是逻辑地址虚拟地址 当程序加载到物理内存的时候就得到物理地址 根据这个虚拟到物理建立映射关系
int main()
{pid_t id fork();if(id 0){// childwhile(1){printf(I am child, %d, %p\n, id, id);sleep(1);}}else if(id 0){while(1){printf(I am father, %d, %p\n, id, id);sleep(1);}}return 0;
}解释这个id怎么能同时0又!0呢return 的本质就是对ID进行写时拷贝
Linux真正的进程调度方案 runqueue里的queue虽然有140个空间 但是前100个空间不用。 和我们nice -20到19 对应优先级 60~99 queue里面的每一个元素又是一个队列把task_struct 按优先级放入对应下标的队列中因为前面有很多空间没用我们又使用了大小为5个长整型的位图 32位 32位的查找 使用的下标。实际当中有两个这样的结构 通过一个active指针和expired指针指向active指向的队列 只出不进expired指向的队列只进不出。active指向的队列为空时交换两个指针。