跳至主要內容

进程虚拟地址空间

张威大约 3 分钟c/c++操作系统虚拟内存

任何的编程语言都会产生两种东西:指令和数据。c++代码编译链接之后产生一个可执行文件***.exe存储在磁盘上,运行时会把程序从磁盘加载到内存(虚拟)中,

产生几个问题

  1. 运行时把可执行程序的哪些东西加载到内存中?
  2. 加载到内存后是如何存放的?
  3. 内存空间有没有区域划分?划分后是什么样的??

前提条件

虚拟如何理解?

存在,能看见 是物理的

存在, 看不见 是透明的

不存在, 看得见 是虚拟的

不存在, 看不见 被删除了

linux系统会为当前进程分配一个2^32大小的空间

image-20240130150034776
image-20240130150034776

0x00000000到0x08048000是系统预留的空间不可访问,如访问空指针时程序会崩溃

.text段:代码段,存放指令

.rodata只读数据段,常量就存放在此,例如const char *p = “hello”;//p在栈上,而“hello”在只读数据段上,因为这个是字符串常量

.data:数据段,存放已经初始化且初始化不为0全局变量/静态变量

.bss:数据段,存放初始化为0和未初始化全局变量/静态变量,内核会将此数据段都置0

.heap:堆区,当程序运行时,new或malloc后才会分配堆内存,由低地址向高地址增长,程序员自己管理内存

.dll,*so加载共享库,也就是动态链接库,window下是.dll,linux下是so

.stack:函数运行或产生线程时,每一个函数或线程独有的栈空间,由高地址向低地址增长

命令行参数,环境变量:命令行参数如main函数传参,环境变量如搜索头文件或库文件时默认的路径

内核空间

  • ZONE_DMA:ZONE“区域的意思”,约16M
  • ZONE_BORMAL:约800多M,存放进程控制块(PCB块,task_struct)、内核空间的线程、内核函数运行时所依赖的栈空间……
  • ZONE_HIGHMEN:高地址物理内存,做内存映射用的
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
 
int a=7;
int b=0;
int c;
 
static int sa=8;
static int sb=0;
static int sc;
int main(){
    
    int d=10;	//move dword ptr[d],0AH 
    			//move dword ptr[esp],0AH
    int e=0;
    int f;
    
    static int sd=10;
    static int se=0;
    static int sf;
    
    cout<<c<<" "<<sc<<" "<<f<<" "<<sf;
 
}
  • 全局变量都是数据,放在数据段(a,sa在.data段 b,c,sb,sc在.bss段)

  • 🍊声名**,运行时会在栈上开辟空间存储变量值,**cout << f << c << endl f不为0、c为0

  • e在.data,f,g在.bss
  • ,匿名管道通信就是在内核空间划分一道地址空间进行通信
image-20240130153420171
image-20240130153420171

为什么进程间通信比较困难,主要原因是用户空间是私有的,只要内核空间是共享的