首页 > 系统相关 >Linux 进程 | 进程地址空间

Linux 进程 | 进程地址空间

时间:2024-08-25 15:50:59浏览次数:6  
标签:物理地址 虚拟地址 空间 地址 Linux 进程 全局变量

文章目录

进程地址空间

程序地址空间

地址空间一共有如下的几个区域,从下到上地址逐渐增加,其中栈区的空间是从上往下使用,即从高地址往低地址增长;堆区的空间是从下往上使用,即从低地址往高地址增长需要注意的是,在不同位操作系统下或者不同编译器下,内存的分配规则都可能是不同的,这里以linux为例,也是最经典的一种。

我们平时敲代码使用程序地址空间的时候,当我们定义一个局部变量,它的空间就是在栈区上开辟的,有临时性;当我们使用malloc申请空间的时候,是在堆区开辟的空间;当我们定义一个全局变量的时候,它的空间就是在全局变量中开辟的,其中也分为未初始化全局变量和已初始化全局变量。在32位系统下的寻址空间是4GB

为了直观地体现出地址分配的规则,我们使用一些例子来做演示:

#include<stdio.h>
#include<stdlib.h>

int val1 = 10;
int val2;

int main() {
	//以下均为存储在各区地址空间中的实例
	printf("代码区:            %p\n", main);
	const char* str = "helllo linux";
	printf("字符常量区:         %p\n", str);
	printf("已初始化全局变量区:  %p\n", &val1);
	printf("未初始化全局变量区:  %p\n", &val2);
	char* a = (char*)malloc(sizeof(char));
	printf("堆区:             %p\n", a);
	printf("栈区:             %p\n", &str);
	return 0;
}

运行结果如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过运行结果会发现打印出来的地址从代码区到栈区依次递增。

进程地址空间

当我们使用fork()函数生成一个子进程的时候,子进程会对将要访问的父进程的内容进行写时拷贝,但是会发现子进程和父进程对于同一个全局变量进行访问更改等操作的时候,这个变量的地址是不变的,也就是说同一个地址可能会有两个值,因为这里的地址并不是物理地址,而是虚拟地址(我们平时写程序用到的地址相关的内容一般都是虚拟地址)。如果是物理地址,这是绝对不可能的,可以配合下面案例理解:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int val = 0;
int main()
{
	pid_t id = fork();
 	if(id < 0){
 		perror("fork");
 		return 0;
 	}
 	else if(id == 0){ //child,子进程肯定先跑完,也就是子进程先修改,完成之后,父进程再读取
 		val=100;
 		printf("child: %d : %p\n", val, &val);
 	}
    else{ //parent
 	sleep(3);
 	printf("parent: %d : %p\n", val, &val);
 	}
 	sleep(1);
    return 0;
}

运行结果如图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

会发现前文所说的现象,同一个变量,子进程对其将要访问的变量进行写时拷贝,但是父子进程中的val确是同一个地址,因此这里的地址是虚拟地址而非物理地址。他们地址上的逻辑应该对应下图(简化):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 当父进程创建出来,系统创建了父进程的PCB和父进程的进程地址空间,PCB指向进程地址空间
  • 这里创建的进程地址空间是虚拟地址,虚拟地址和物理内存是通过页表来映射的
  • 当访问某个地址时,页表通过映射关系,查找到物理地址,并读取存在当中的数据
  • 当父进程创建子进程的时候,系统也根据父进程为模板创建子进程对应的PCB和进程地址空间
  • 由于子进程时以父进程为模板创建的,因此他们页表是一样的,因此子进程和父进程能够共享代码
  • 对于同一个全局变量,当子进程需要对其进行写入等操作时,由于父子进程的虚拟地址对应同一块物理地址,为保证独立性,系统会在物理内存中额外开辟一块空间
  • 至此,父子进程各自页表中对于此全局变量的虚拟地址是相同的,但是对应的物理地址是不同的。

简化):

[外链图片转存中…(img-xn3KL9cr-1724489534997)]

[外链图片转存中…(img-1r95tjqS-1724489534998)]

  • 当父进程创建出来,系统创建了父进程的PCB和父进程的进程地址空间,PCB指向进程地址空间
  • 这里创建的进程地址空间是虚拟地址,虚拟地址和物理内存是通过页表来映射的
  • 当访问某个地址时,页表通过映射关系,查找到物理地址,并读取存在当中的数据
  • 当父进程创建子进程的时候,系统也根据父进程为模板创建子进程对应的PCB和进程地址空间
  • 由于子进程时以父进程为模板创建的,因此他们页表是一样的,因此子进程和父进程能够共享代码
  • 对于同一个全局变量,当子进程需要对其进行写入等操作时,由于父子进程的虚拟地址对应同一块物理地址,为保证独立性,系统会在物理内存中额外开辟一块空间
  • 至此,父子进程各自页表中对于此全局变量的虚拟地址是相同的,但是对应的物理地址是不同的。

标签:物理地址,虚拟地址,空间,地址,Linux,进程,全局变量
From: https://blog.csdn.net/TTKunn/article/details/141501784

相关文章

  • Android fork 进程 process(init/Zygote/SystemServer)
    ##Android的init/Zygote/SystemServer Android手机先开机,init/Zygote/SystemServer,然后启动Framework,然后启动Launcher;【安装APP(PMS),】然后启动APP(AMS)。所有的Android应用进程都是有Zygote进程fork出来的。Android系统启动流程(一)解析init进程-http://blog.csdn.net/itach......
  • Linux内核——内核源码的探索+教你如何系统认识Linux内核源码树(推荐方式+推荐工具+推
    Linux全称GNU/Linux,是一种免费使用和自由传播的类UNIX操作系统,该操作系统是由LinusTorvalds于1991年10月5号首次发布,它主要受到Minix和Unix思想的启发,是一个基于POSIX的多用户、多任务、支持多线程和多CPU的操作系统。严格地讲,Linux单指操作系统的内核,加上用户空间的应用程......
  • IO与进程
    #include<stdio.h>fopen("文件路径","打开方式");//打开文件标准iofclose(文件流);//关闭文件标准iofgetc(文件流);//读一个字符标准iofgutc(‘要写的字符’,文件流);//写一个字符标准iofgets(存放字符串首地址(如buf),大小,文件流);//读一串字符标准iofguts(存放字符......
  • IO进程练习---往文件中录入当前时间
     题目要求编程读写一个文件test.txt,每隔1秒向文件中写入一行录入时间的数据,类似这样:1 2007-7-3015:16:42 2 2007-7-3015:16:43该程序应该无限循环,直到按Ctrl-C中断程序。再次启动程序写文件时可以追加到原文件之后,并且序号能够接续上次的序号,比如:1  2007......
  • 如何快速将经纬度坐标解析为地址文本?
    GIS数据转换器的"坐标转地址"功能,可以帮助用户将经纬度坐标快速转换为对应的地址文本,广泛用于地图导航、地籍管理、物流追踪、紧急救援等多个领域,提高地理位置信息的实用性和可访问性。下面是详细的使用步骤:方法/步骤1.数据要求(1)数据格式:软件支持DWG、DX......
  • linux下试验中间件canal的example示例-binlog日志的实时获取显示以及阿里巴巴中间件ca
    一、linux下试验中间件canal的example示例-binlog日志的实时获取显示    今天重装mysql后,进行了canal的再次试验,原来用的mysql5.7,今天重装直接换了5.6算了。反正测试服务器的mysql也不常用。canal启动后日志显示examplepreparetofindstartpositionjustshowmaste......
  • 进程间通信
    进程间通信进程间通信(Inter-ProcessCommunication,IPC)是指在不同进程之间进行数据交换和信息传递的机制。常见的通信方式有:管道、消息队列、共享内存、信号量、socket。管道(Pipe)无名管道:特点:只能在具有亲缘关系的进程之间使用(如父子进程)。它是半双工的,即数据只能在一个方向上......
  • Linux常用命令
    1echo命令echo命令用于在终端设备上输出字符串或变量提取后的值,语法格式为“echo[字符串] [$变量]”。2 date命令date命令用于显示或设置系统的时间与日期,语法格式为“date[+指定的格式]”。【中间的空格不能省略】   ......
  • Linux 内核源码分析---NIC 数据包接收与发送
    网络接口控制器(networkinterfacecontroller,NIC),又称网络接口控制器,网络适配器(networkadapter),网卡(networkinterfacecard),或局域网接收器(LANadapter),是一块被设计用来允许计算机在计算机网络上进行通信的计算机硬件。由于其拥有MAC地址,因此属于OSI模型的第2层。它使......
  • 浦语Camp3:入门1-Linux基础
    任务等级任务内容闯关任务完成SSH连接与端口映射并运行hello_world.py可选任务1将Linux基础命令在开发机上完成一遍可选任务2使用VSCODE远程连接开发机并创建一个conda环境可选任务3创建并运行test.sh文件1.完成SSH连接与端口映射并运行hello_world.py新建hello_world.p......