目录
1. 内存空间布局
2. 虚拟地址的引出
3. 进程地址空间
补充:
Linux
在之前我们学习C语言时,我们知道可以大致将内存划分为:堆区、栈区和静态区;
其实这样的划分是相当粗略的,下来看一下较为细致的空间布局图:
用户空间是供我们使用的,内核空间是供操作系统使用的。
下来用一段代码来验证一下地址空间划分是否真如上述一般:
#include
#include
#include
#include
int g_val=100;
int g_unval;
int main(int argc,char* argv[],char* env[])
{
const char* s="hello linux!\n";
printf("code addr: %p\n",main);
printf("const string addr: %p\n",s);
printf("init_val addr: %p\n",&g_val);
printf("uninit_val addr: %p\n",&g_unval);
char* heap1=(char*)malloc(1);
char* heap2=(char*)malloc(1);
char* heap3=(char*)malloc(1);
printf("heap-1 addr: %p\n",heap1);
printf("heap-2 addr: %p\n",heap2);
printf("heap-3 addr: %p\n",heap3);
int a=10;
int b=2;
printf("stack-1 addr: %p\n",&s);
printf("stack-2 addr: %p\n",&heap1);
printf("stack-3 addr: %p\n",&heap2);
printf("stack-4 addr: %p\n",&heap3);
printf("stack-5 addr: %p\n",&a);
printf("stack-6 addr: %p\n",&b);
printf("cmd addr: %p\n",argv[0]);
printf("env addr: %p\n",env[0]);
return 0;
}
经过证实,内存空间布局确实如上述图中所画。
由低地址->高地址,首先是:代码区、字符串常量区、已初始化的全局变量、未初始化的全
局变量、堆区(地址由小到大)、栈区(地址由大到小)、命令行参数、环境变量。
先来看一段代码:
#include
#include
#include
int g_val=100;
int main()
{
//创建子进程
if(fork()== 0)
{
//child
int count=5;
while(count)
{
printf("I am child, times: %d ,g_val=%d ,&g_val=%p\n",count,g_val,&g_val);
count--;
sleep(1);
if(count==3)
{
printf("******child开始更改数据************\n");
g_val=200;
printf("******child更改数据完成************\n");
}
}
}
else
{
//parent
while(1)
{
printf("I am father,g_val=%d,&g_val=%p\n",g_val,&g_val);
sleep(1);
}
}
return 0;
}
上述代码:创建了一个子进程,父子进程分别打印g_val的值和g_val的地址,当子进程在count=3
时,将g_val的值更改,发现父子进程打印出来的g_val的值不一样了,这个我们知道—是因为“写时
拷贝”的原因呢。但我们惊奇的发现,它们的值不一样,但是地址却一样。
在这时我们很疑惑,难道同一地址空间能存不同的值吗?显然是不能的!
那是怎么回事呢?
其实我们打印出来的这个地址,绝对不是物理地址(物理内存),是虚拟地址!
我们在用C/C++语言所看到的地址,全部都是虚拟地址!
物理地址,用户一概看不到,由OS统一管理。
OS负责将虚拟地址转化为物理地址!
进程每次被创建出来,其实OS不止为进程创建task_struct,其实还为每个进程开辟了虚拟地址空
间mm_struct(大小4GB / 在32位下),以及页表(保存虚拟地址—>物理地址的映射)
如下所示:
在这时我们便要对进程这一概念进一步完善:
进程 = task_struct + mm_struct + 页表 + 数据 + 代码
我们在学习进程优先级时,知道nice为优先级的优先级的修正值,其取值为-19~20,共40个级别;
其实进程的运行队列也是有40个,将优先级相同的进程放在一个运行队列中,这时候更加方便
CPU的调度。
坚持打卡!