操作系统进程映像

进程映像

程序与进程:
  • 程序是存储在磁盘上的可执行文件,当程序被运行时,系统会把程序从磁盘加载到内存中运行,正在运行中的程序称为进程,一个程序可以同时被加载多次,形成多个进程,每个进程相互独立,由操作系统管理

什么是进程映像:
  • 进程在内存空间中的分布使用情况就称为进程映像,从低地址到高地址分别是:

各个内存段的存储什么数据:
  • 代码段(text)

    • 存储二进制指令、字面值常量、被const修饰过的原data段的数据

    • 权限r-- 或者 r-x 权限只读

  • 数据段(data)

    • 存储初始化过的全局变量和静态变量

  • 静态数据段(BSS)

    • 存储未初始化过的全局变量和静态变量

    • 进程一旦加载,此内存段会被操作系统自动清零,默认值是0

    • 如果初始化的值给0,依然还在BSS

  • 堆区(heap)

    • 要程序员动态分配、动态释放,从低地址向高地址扩招

    • 使用malloc系列函数进行内存管理

    • 而malloc系列函数底层调用操作系统的API(brk\sbrk\mmap\munmap)

  • 栈区(stack)

    • 存储非静态局部变量、块变量,包括函数的参数(除了main函数的参数)、返回值

    • 内存扩展从高地址向低地址扩展

    • 栈区与堆区中间有一段预留空间,一个作用为了预留,第二个是让共享库的内存以及共享内存使用此段内存

  • 命令行参数与环境变量表

    • 里面存储环境变量表以及命令行传给main的参数内容

//  打印出每个内存段中各种数据的地址
//  通过ps -aux 查看出进程id
//  /proc/进程号/maps 该文件能查看该进程的内存分布情况
//  通过打印的内存地址,分析maps文件的内存段分布情况
#include <stdio.h>
#include <stdlib.h>
​
const int const_global = 10;    //  常全局变量
int init_global = 10;   //  初始化全局变量
int uninit_global;      //  未初始化全局变量
​
int main(int argc,const char* argv[])
{
    const static int const_static = 10; //  常静态局部变量
    static int init_static = 10;//  初始化静态局部变量
    static int uninit_static;   //  未初始化静态局部变量
​
    const int const_local;  //  常局部变量
    int prev_local;     //  前局部变量
    int next_local;     //  后局部变量                                                                                                                                                                                               
    int arr[10];
​
    int* prev_heap = malloc(sizeof(int));   //  前堆变量
    int* next_heap = malloc(sizeof(int));   //  后堆变量
​
    const char* literal = "literal";    //  字面值常量
    extern char** environ;      //  环境变量
​
    printf("-----命令行参数与环境变量-----<高>\n");
    printf("环境变量:%p\n",environ);
    printf("命令行参数:%p\n",argv);
    printf("-------------栈-------------------\n");
    printf("常局部变量:%p\n",&const_local);
    printf("前局部变量:%p\n",&prev_local);
    printf("后局部变量:%p\n",&next_local);
    printf("arr[0]:%p arr[1]:%p arr[2]:%p\n",&arr[0],&arr[1],&arr[2]);
    printf("-------------堆-------------------\n");
    printf("后堆变量:%p\n",next_heap);
    printf("前堆变量:%p\n",prev_heap);
    printf("-----------BSS--------------------\n");
    printf("未初始化全局变量:%p\n",&uninit_global);
    printf("未初始化静态变量:%p\n",&uninit_static);
    printf("----------data--------------------\n");
    printf("初始化全局变量:%p\n",&init_global);
    printf("初始化静态变量:%p\n",&init_static);
    printf("---------代码段-------------------\n");
    printf("常静态局部变量:%p\n",&const_static);
    printf("常全局变量:%p\n",&const_global);
    printf("字面值常量:%p\n",literal);
    printf("二进制指令:%p\n",main);
    printf("------------------------------<低>\n");
​
    getchar();
}

<think>我们正在讨论进程上下文,它描述了进程执行时的状态。根据引用,进程上下文是进程执行活动全过程的静态描述,包括三个部分:用户级上下文、寄存器上下文和系统级上下文。此外,引用还提到进程上下文可以细分为上文(已执行)、正文(正在执行)和下文(待执行)。在Linux内核中,进程上下文包括进程的虚拟地址空间和硬件上下文。具体组成:1.用户级上下文:包括进程的正文(代码)、数据、用户堆栈和共享存储区。这些是进程在用户空间运行时所需要的信息。2.寄存器上下文:也称为硬件上下文,包括通用寄存器、程序计数器(PC/IP)、处理器状态寄存器(如EFLAGS)、栈指针(SP)等。在ARM64架构中,这些信息保存在task_struct结构的thread成员的cpu_context中。3.系统级上下文:包括进程控制块(task_struct)、内存管理信息(如mm_struct,vm_area_struct,页表等)和内核栈。当进程陷入内核态时,会使用内核栈。另外,引用[5]提到,系统调用过程中会发生两次CPU上下文切换(用户态到内核态,再回到用户态),这涉及到寄存器状态的保存和恢复。因此,我们可以将进程上下文定义为进程执行环境的完整描述,它包含了进程在处理器上执行时所需的所有状态信息,包括用户空间和内核空间的状态。下面详细说明每个部分:一、用户级上下文这是进程在用户空间运行时的环境,包括:-正文段(代码):即程序的可执行代码。-数据段:包括初始化的全局变量、静态变量等。-用户堆栈:用于函数调用、局部变量等。-共享存储区:进程间共享的内存区域。二、寄存器上下文(硬件上下文)这是CPU寄存器的状态,当进程被切换出去时,必须保存这些寄存器的值,以便下次恢复执行。包括:-通用寄存器:如x86中的EAX,EBX等,ARM64中的X0-X30等。-程序计数器(PC/IP):指向下一条要执行的指令。-状态寄存器:如x86的EFLAGS,ARM64的PSTATE,记录CPU的状态(如进位、溢出等)。-栈指针(SP):指向当前栈顶。在Linux中,硬件上下文保存在进程的task_struct结构体的thread成员中。例如,ARM64的cpu_context结构体包含x19-x28,sp,pc等寄存器。三、系统级上下文这是操作系统管理进程所需的信息,包括:-进程控制块(PCB):在Linux中就是task_struct结构体,包含进程的状态、ID、优先级、资源使用情况等。-内存管理信息:如mm_struct(描述进程的整个虚拟地址空间)、vm_area_struct(描述虚拟内存区域)、页表(pgd,pte等)等。-内核栈:当进程进入内核态时,使用的堆栈。每个进程都有一个独立的内核栈。此外,进程上下文在进程切换(上下文切换)时起到关键作用。操作系统需要保存当前进程的上下文(包括上述三部分),并恢复下一个进程的上下文。上下文切换的过程:1.保存当前进程的寄存器上下文(硬件上下文)到其PCB中。2.更新内存管理信息(如切换页表)。3.切换到新进程的内核栈。4.恢复新进程的寄存器上下文(从新进程的PCB中恢复)。5.切换用户空间(包括用户堆栈等)。注意,系统调用也会引起上下文切换,但只是同一进程内的用户态和内核态之间的切换(不涉及进程切换)。这时,需要保存用户态的寄存器状态,然后切换到内核态执行,执行完毕后再恢复用户态。总结:进程上下文是进程运行环境的完整静态描述,由用户级上下文、寄存器上下文和系统级上下文组成。它使得操作系统能够暂停一个进程的执行并在之后恢复执行,从而实现多任务。下面我们用Mermaid图表来展示进程上下文的组成:```mermaidgraphTDA[进程上下文]-->B[用户级上下文]A-->C[寄存器上下文]A-->D[系统级上下文]B-->E1[正文段/代码]B-->E2[数据段]B-->E3[用户堆栈]B-->E4[共享存储区]C-->F1[通用寄存器]C-->F2[程序计数器PC]C-->F3[状态寄存器]C-->F4[栈指针SP]D-->G1[进程控制块task_struct]D-->G2[内存管理信息mm_struct等]D-->G3[内核栈]```最后,根据要求生成相关问题:§§相关问题§§1.在进程上下文切换过程中,哪些部分的开销最大?如何优化?2.用户级上下文和系统级上下文在进程切换时分别如何处理?3.为什么系统调用会导致两次上下文切换?请详细说明过程。4.在ARM64架构中,硬件上下文是如何保存和恢复的?5.进程上下文和进程映像(ProcessImage)之间有何区别与联系?</think>### 进程上下文的定义及组成 进程上下文(Process Context)是**进程执行环境的完整静态描述**,包含进程在处理器上执行时所需的全部状态信息。当进程切换时,操作系统必须保存当前进程上下文并恢复目标进程上下文,这是实现多任务并发的核心机制[^1][^3]。 #### 一、核心定义与功能 1. **本质**:进程执行活动全过程的静态快照[^1] 2. **核心作用**: - 实现进程切换时执行现场的保存与恢复 - 隔离不同进程的运行环境 - 支持系统调用和中断处理[^4][^5] 3. **关键特性**: - **静态性**:某一时刻的状态冻结 - **完整性**:覆盖用户空间和内核空间 - **硬件关联**:直接映射到CPU寄存器状态[^2] ```mermaid graph LR A[进程上下文] --> B[用户级上下文] A --> C[寄存器上下文] A --> D[系统级上下文] B --> B1(正文/代码) B --> B2(数据段) B --> B3(用户堆栈) B --> B4(共享存储区) C --> C1(通用寄存器) C --> C2(程序计数器PC) C --> C3(状态寄存器EFLAGS) C --> C4(栈指针SP) D --> D1(进程控制块task_struct) D --> D2(内存管理信息) D --> D3(内核栈) ``` #### 二、详细组成结构 ##### 1. 用户级上下文(User-Level Context) 进程在用户空间运行的资源集合[^3]: - **正文段(Text Segment)**:可执行代码(如函数指令) - **数据段(Data Segment)**:全局变量、静态变量 - **用户堆栈(User Stack)**:函数调用栈、局部变量 - **共享存储区(Shared Memory)**:进程间通信区域 ##### 2. 寄存器上下文(Register Context) CPU硬件状态的精确记录[^2][^3]: | 寄存器类型 | 作用描述 | 示例寄存器 | |-------------------|--------------------------------------------------------------------------|--------------------------| | **通用寄存器** | 存储临时计算数据 | x86: EAX, EBX<br>ARM64: X0-X30 | | **程序计数器PC** | 指向下一条待执行指令地址 | x86: EIP<br>ARM64: PC | | **状态寄存器** | 记录CPU标志位(溢出/中断/权限等) | x86: EFLAGS<br>ARM64: PSTATE | | **栈指针SP** | 指向当前栈顶位置 | x86: ESP<br>ARM64: SP | > 在ARM64架构中,寄存器上下文通过`task_struct->thread->cpu_context`结构保存,包含x19-x28, sp, pc等关键寄存器值[^2]。 ##### 3. 系统级上下文(System-Level Context) 操作系统管理进程所需的内核资源[^3][^4]: - **进程控制块(PCB)**: 存储进程元数据(PID、状态、优先级等),Linux中为`task_struct`结构体 - **内存管理信息**: 包含: - `mm_struct`:虚拟地址空间描述 - `vm_area_struct`:虚拟内存区域映射 - 页表结构(pgd/pte):物理内存映射关系 - **内核栈(Kernel Stack)**: 进程在内核态执行时的专用堆栈(与用户栈隔离)[^4] #### 三、上下文切换机制 当发生进程切换或系统调用时: 1. **保存现场**: - 将当前CPU寄存器值存入原进程的寄存器上下文 - 保存内核栈指针和内存管理状态[^5] 2. **切换资源**: - 更新CR3寄存器切换页表(变更内存映射) - 加载新进程的`task_struct`和内核栈 3. **恢复现场**: - 从新进程上下文恢复寄存器值(包括PC指针) - 跳转到PC指向的地址继续执行[^2][^5] > **系统调用特殊场景**:用户态→内核态→用户态切换需**两次上下文保存/恢复**,但仅涉及同一进程的权限级别变化[^5]。 #### 四、与进程映像的关系 | 概念 | 进程映像 | 进程上下文 | |---------------|----------------------------------|--------------------------------| | **本质** | 进程的静态内存表示 | 进程执行环境的完整快照 | | **包含内容** | 程序段+数据段+PCB | 用户资源+寄存器状态+内核资源 | | **作用场景** | 进程创建/终止时的内存分配 | 进程切换/系统调用时的状态保存 | | **空间范畴** | 主要位于用户空间 | 覆盖用户空间和内核空间 | 进程上下文扩展了进程映像的执行维度,补充了寄存器状态和内核资源信息,共同构成操作系统调度进程的完整基础[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值