Linux 第十八章

embedded/2024/12/22 13:20:48/

🐶博主主页:@ᰔᩚ. 一怀明月ꦿ 

❤️‍🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++,linux

🔥座右铭:“不要等到什么都没有了,才下定决心去做”

🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀

目录

程序地址空间

区间的地址分布

真正理解同一个地址进行读取不同内容

地址空间

虚拟地址和物理地址

虚拟地址:

物理地址:

struct mm_struct

页表


程序地址空间

区间的地址分布

[BCH@hcss-ecs-6176 10_21]$ cat test.c
#include<stdio.h>
#include<stdlib.h>
int un_gval;
int init_gval=100;
int main(int argc,char* argv[],char* env[])
{printf("code addr:%p\n",main);//代表代码区的地址const char *str="hello linux";printf("read only char addr:%p\n",str);//代表字符常量取得地址printf("init global value addr:%p\n",&init_gval);//代表初始化全局数据区printf("uninit global value addr:%p\n",&un_gval);//代表未初始化全局数据区char* heap1=(char*)malloc(100);printf("heap addr:%p\n",heap1);//代表堆区的地址printf("stack addr:%p\n",&str);//代表栈区的地址int i=0;for(;argv[i];i++){printf("argv[%d]:%p\n",i,argv[i]);}for(i=0;env[i];i++){printf("env[%d]:%p\n",i,env[i]);}return 0;
}结果:
[BCH@hcss-ecs-6176 10_21]$ ./mytest
code addr:0x40057d
read only char addr:0x40077e
init global value addr:0x60103c
uninit global value addr:0x601044
heap addr:0x1c9d010
stack addr:0x7ffdc6730228
argv[0]:0x7ffdc67307fd
env[0]:0x7ffdc6730806
env[1]:0x7ffdc6730819
env[2]:0x7ffdc6730830
env[3]:0x7ffdc673083b
env[4]:0x7ffdc673084b
env[5]:0x7ffdc673085a
env[6]:0x7ffdc673087e
env[7]:0x7ffdc673088f
env[8]:0x7ffdc673089c
env[9]:0x7ffdc67308af
env[10]:0x7ffdc67308b8
env[11]:0x7ffdc6730e54
env[12]:0x7ffdc6730e82
env[13]:0x7ffdc6730e9b
env[14]:0x7ffdc6730ef5
env[15]:0x7ffdc6730f09
env[16]:0x7ffdc6730f1a
env[17]:0x7ffdc6730f31
env[18]:0x7ffdc6730f39
env[19]:0x7ffdc6730f48
env[20]:0x7ffdc6730f54
env[21]:0x7ffdc6730f88
env[22]:0x7ffdc6730fab
env[23]:0x7ffdc6730fca
env[24]:0x7ffdc6730fe4

真正理解同一个地址进行读取不同内容

[BCH@hcss-ecs-6176 10_21]$ cat test.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int g_val=100;
int main()
{pid_t id =fork();//创建子进程if(id==0){//childint cnt=5;while(1){printf("pid:%d,ppid:%d,g_val:%d,&g_val:%p\n",getpid(),getppid(),g_val,&g_val);sleep(1);if(cnt==0){g_val=200;printf("child change g_val:100->200\n");}cnt--;}}else{//parentwhile(1){printf("pid:%d,ppid:%d,g_val:%d,&g_val:%p\n",getpid(),getppid(),g_val,&g_val);sleep(1);}}return 0;
}[BCH@hcss-ecs-6176 10_21]$ ./mytest
pid:29919,ppid:7584,g_val:100,&g_val:0x60105c
pid:29920,ppid:29919,g_val:100,&g_val:0x60105c
pid:29919,ppid:7584,g_val:100,&g_val:0x60105c
pid:29920,ppid:29919,g_val:100,&g_val:0x60105c
pid:29919,ppid:7584,g_val:100,&g_val:0x60105c
pid:29920,ppid:29919,g_val:100,&g_val:0x60105c
pid:29919,ppid:7584,g_val:100,&g_val:0x60105c
pid:29920,ppid:29919,g_val:100,&g_val:0x60105c
pid:29919,ppid:7584,g_val:100,&g_val:0x60105c
pid:29920,ppid:29919,g_val:100,&g_val:0x60105c
pid:29919,ppid:7584,g_val:100,&g_val:0x60105c
pid:29920,ppid:29919,g_val:100,&g_val:0x60105c
pid:29919,ppid:7584,g_val:100,&g_val:0x60105c
child change g_val:100->200
pid:29920,ppid:29919,g_val:200,&g_val:0x60105c//子进程的值是200,地址0x60105c
pid:29919,ppid:7584,g_val:100,&g_val:0x60105c//父进程的是100,地址0x60105c
pid:29920,ppid:29919,g_val:200,&g_val:0x60105c
pid:29919,ppid:7584,g_val:100,&g_val:0x60105c

得出的结论是:我们C/C++看到的地址,绝对不是物理地址!!!

我们平时用的地址都是虚拟地址/线性地址!!

地址空间

每一个进程运行之后,都会有一个进程地址空间存在!!

就可以解释fork之后形成了父进程和子进程

返回给父进程的id是子进程的pid,返回给子进程的是0

因为,父进程有自己的虚拟地址空间,给id在栈区开辟一个空间,然后通过页表实现虚拟地址映射物理地址,id的存储在内存中

子进程继承父进程,拷贝父进程的地址空间和页表,但是页表上虚拟地址映射物理地址不同,id在子进程虚拟地址和id在父进程虚拟地址是相同的,而映射的物理地址是不同的,所以内存中又会开辟空间去存储在子进程中的id

虚拟地址和物理地址

在 Linux 中,虚拟地址和物理地址是计算机系统中重要的概念,特别是在操作系统和硬件之间的交互中。

虚拟地址:

虚拟地址是由 CPU 生成的地址空间中的地址,它是进程所见到的地址。每个进程都有自己的虚拟地址空间,通常是连续的地址空间,从 0 开始。
虚拟地址提供了一种抽象机制,使得每个进程都认为它在独占系统资源,而不必担心与其他进程的冲突。
虚拟地址的转换是由硬件中的内存管理单元(MMU)来完成的。MMU 根据页面表(Page Table)将虚拟地址映射到物理地址。

物理地址:

物理地址是实际存在于计算机系统中的内存单元的地址,它是 RAM 中存储数据的位置。
物理地址是实际用于访问计算机系统中内存模块的地址。
虚拟地址通过地址映射机制转换为物理地址,然后在物理地址上进行访问和操作。
在 Linux 中,虚拟地址和物理地址的管理是由操作系统负责的。操作系统通过分页机制将进程的虚拟地址映射到物理地址,从而实现了内存管理和进程间的隔离。

struct mm_struct

虚拟地址空间也要被OS管理起来!!每一个进程都要有地址空间,系统中,一定要对地址空间做管理!!,地址空间最终一定是一个内核的数据结构对象!

linux中,这个进程/虚拟地址空间的东西,叫做:struct mm_struct

Struct mm_struct
{Long code_start;Long code_end;Long data_start;Long data_end;Long heap_start;Long heap_end;Long stack_start;Long stack_end;…...
}

页表

总结:

1)每一个进程都是有页表的

2)如何理解切换:只要把上下文数据保存好,pcb、地址空间、页表就保存好了

3)让进程以统一的视角看待内存,所以一个进程,可以通过地址空间+页表可以将乱序的内存数据,变成有序,分门别类的规划好!无序变有序

4)页表还有访问权限字段这就是为什么常量字符串,不可被修改,就是由于对应的内存访问权限是只读的

5)存在虚拟地址空间,可以有效的进行进程内存的安全检查!

6)将进程管理和内存管理进行结耦,通过页表,让进程映射到不同的物理内存处,从而实现进程独立性

CPU中的CR3寄存器

存储当前进程的页目录表物理地址。当CPU从虚拟地址空间中访问内存时,会首先将虚拟地址通过分页机制翻译为物理地址,而这个翻译过程需要使用到页表。

  🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸 


http://www.ppmy.cn/embedded/29459.html

相关文章

WPF —— 跑马灯

标签页面 <Label Width"800" Height"80" Background"Black" VerticalAlignment"Top"></Label><Label Width"360" Height"40"HorizontalAlignment"Left" VerticalAlignment"Top&quo…

什么是DevOps?

&#xff08;学校作业&#xff09; 维基百科定义 DevOps&#xff08;Development和Operations的组合词&#xff09;是一种重视“软件开发人员&#xff08;Dev&#xff09;”和“IT运维技术人员&#xff08;Ops&#xff09;”之间沟通合作的文化、运动或惯例。透过自动化“软件交…

C# 使MessageBox.Show弹出框保持最前

要确保 MessageBox.Show 弹出框保持在最前面&#xff0c;你可以使用 MessageBoxOptions 枚举中的 SetForeground 选项。这将确保消息框置于其他窗口之前。 以下是如何在 C# 中使用 MessageBox.Show 来显示一个保持最前的消息框的示例代码&#xff1a; MessageBox.Show("…

设计模式:建造者模式

目录 一&#xff0c;概念 二&#xff0c;不使用建造者有什么麻烦 三&#xff0c;格式 一&#xff0c;概念 建造者模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;用于将复杂对象的构建与其表示分离&#xff0c;以便同样的构建过程可以创建不同…

excel办公系列-图表元素及其作用

Excel图表元素及其作用 Excel图表由各种元素组成&#xff0c;每个元素都有其特定的作用&#xff0c;可以帮助我们更清晰地传达数据信息。下面将介绍Excel图表中常见的一些元素及其作用&#xff0c;并附上相关截图。 原始数据 月份 网站访问量 (万次&#xff09; 销售额 (万…

IDEA中测试时的包名问题

报错&#xff1a;Unable to find a SpringBootConfiguration, you need to use ContextConfiguration or SpringBootTest(classes...) with your test 原因&#xff1a;&#xff08;图是别人那巴来的&#xff09;启动类所在的包名和测试类的包名不一致导致的&#xff0c;原因是…

分享自己一篇在亚马逊云科技AWS官网发的Blog技术文章

小李哥在亚马逊AWS官网&#xff0c;作为第一作者发了自己的第一篇AWS Blog文章&#xff0c;也是自己今年在AWS官网的第11篇文章。文章主要内容是描述为出海的金融企业&#xff0c;搭建满足PCI-DSS合规、FIPS 140-2 Level 3安全标准的传输中数据加密云端方案&#xff0c;主要用于…

2024大学本科/研究生物理专业考试/考研/论文/重点公式考点汇总/最难公式投票考试通过

## 核心公式列表http://deepnlp.org/equation/category/physics ## 力学http://deepnlp.org/equation/amplitude-of-a-driven-oscillation http://deepnlp.org/equation/angular-frequency-for-a-damped-oscillationhttp://deepnlp.org/equation/angular-momentum http://dee…