程序地址空间
程序地址空间是指操作系统中为每个运行的程序分配的内存区域。它包括了程序的代码、数据和堆栈每个部分。
在32位平台下,程序地址空间的大小为2^32,即4GB。这将是程序可以访问的最大内存范围。
程序地址空间通常被划分为不同的段:
程序地址空间的具体分布方式会因为操作系统和编译器的不同而有所差异。然而,不管具体分布方式如何,所有程序都必须在程序地址空间中找到自己的位置来执行和存储数据。
程序地址空间的大小和布局对程序的执行和性能有重要影响。合理利用和管理程序地址空间可以提高程序的运行效率和资源利用率。
下面通过地址来验证地址空间的分布:
int g_unval; 137 int g_val=100; 138 139 int main(int argc,char *argv[],char *env[]) 140 { 141 printf("code addr:%p\n",main); 142 printf("init data addr: %p\n",&g_val); 143 printf("uninit data addr: %p\n",&g_unval); 144 145 char *heap=(char*)malloc(20); 146 char *heap1=(char*)malloc(20); 147 char *heap2=(char*)malloc(20); 148 char *heap3=(char*)malloc(20); 149 static int c; 150 printf("heap addr: %p\n",heap); 151 printf("heap1 addr: %p\n",heap1); 152 printf("heap2 addr: %p\n",heap2); 153 printf("heap3 addr: %p\n",heap3) ; 154 155 printf("stack addr: %p\n",&heap); 156 printf("stack addr: %p\n",&heap1); 157 printf("stack addr: %p\n",&heap2); 158 printf("stack addr: %p\n",&heap3); 159 printf("c addr: %p, c: %d\n",&c,c); 160 int i; 161 for(i=0;argv[i];i++) 162 { 163 printf("argv[%d]=%p\n",i,argv[i]); 164 } 165 for(i=0;env[i];i++) 166 { 167 printf("end[%d]=%p\n",i,env[i]); 168 } 169 170 return 0; 171 172 }
虚拟地址
虚拟地址是计算机中用来表示内存地址的一种抽象概念,它是相对于实际物理内存地址空间而言的。
下面我们先来看个代码:
int g_gal=100; int main() { pid_t id=fork(); if(id==0) { int cnt=0; while(1) { printf("child , pid %d,ppid %d, g_gal %d &g_gal %p\n",getpid(),getppid(),g_gal,&g_gal); sleep(1); cnt++; if(cnt==5) { g_gal=200; printf("child change g_val: 100->200\n"); } } } else { while(1) { printf("father pid %d ppid %d g_gal %d &g_gal %p\n",getpid(),getppid(),g_gal,&g_gal); sleep(1); } } return 0; }
结果:
这里的拷贝称为写时拷贝:
在操作系统中,每个进程都有自己独立的虚拟地址空间,这个虚拟地址空间可以看作是进程可以使用的内存空间。虚拟地址由两部分组成:页号和页内偏移量(即页表)。操作系统使用页表来将虚拟地址映射到实际的物理内存地址,这样就可以实现不同进程之间的地址隔离和内存保护。