进程

定义:进程是由内核定义的抽象的实体,并为该实体分配用以执行程序和各项系统资源。从内核角度看,进程由用户内存空间和一系列内核数据结构组成,其中用户内存空间包含了程序代码及代码所使用的变量,而内核数据结构则用于维护进程状态信息。

1、进程内存布局

每个进程所分配的内存由多个部分组成,通常称之为段,主要有以下段:

  • 文本段
      文本段包含进程运行的机器语言指令。具有只读属性,防止被意外修改。因为多个进程可以运行同一个程序,因此文本段也是可共享的。

  • 初始化数据段
      包含显式初始化的全局变量和静态变量。

  • 未初始化数据段
      包含未进行显式初始化的全局变量和静态变量。程序启动之前会将此段所有变量初始化为0。

  • 栈段
      栈是一个动态增长和收缩的段,用以支持函数调用,由栈帧组成。系统会为每个当前调用的函数创建一个栈帧,其中存储函数的局部变量,实参和返回值。由高地址向低地址方向增长。


  •   堆是可在运行时动态分配的区域。由低地址向高地址方向增长。
    这里写图片描述

栈和栈帧

  一个过程调用包括将数据和控制从代码的一部分传递到另一部分。还必须在进入时为局部变量分配空间,并在退出时释放这些空间。在32位机器上,这些是通过操作栈来实现的。
  系统用栈来传递过程参数、存储返回信息、保存寄存器用于以后恢复等。为单个函数调用创建的那部分栈称为栈帧。每次调用函数时,会在栈上新分配一帧,函数返回时再从栈上将此帧移去(移除帧时,栈大小并未改变,而会在新分配帧时重用这部分内存)。

这里写图片描述
  假设函数P调用函数Q,则Q的参数放在P的栈帧中。当P调用 Q时,P中的返回地址被压入栈中,形成P的栈帧末尾。返回地址就是当程序从Q返回时应该继续执行的地方。Q的栈帧从保存的帧指针的值开始,后面是保存的其它寄存器的值。

非局部跳转

  使用库函数setjmp和longjmp可以执行非局部跳转,即跳转到当前函数之外某个位置。

#include <setjmp.h>

int setjmp(jmp_buf env);初始调用返回0,后续调用返回非0

void longjmp(jmp_buf env, int val);

  setjmp的初始调用为后续的longjmp跳转确定了跳转的位置。调用longjmp后,看起来就像第二次调用setjmp返回时完全一样,通过查看setjmp的返回值可以与初始返回区分开。初始调用返回0,后续返回longjmp参数中设置的val值,通过对val参数使用不同的值,能够区分程序中跳转至同一目标的不同起跳位置。
注:如果指定val为0,则longjmp实际会将其替换为1。

  参数env将setjmp和longjmp联系起来。setjmp将当前进程环境的各种信息保存到env参数中,调用longjmp时必须指定同一个env变量。因为setjmp和longjmp的调用位于不同函数中,因此通常将env定义为全局变量。

切记longjmp不能跳转到已返回的函数中。

sample code:

#include<iostream>
#include<setjmp.h>

static jmp_buf env;

void func()
{
    std::cout<<"Call func."<<std::endl;
    longjmp(env, 1);
}

int main()
{
    switch(setjmp(env))
    {
    case 0:
        std::cout<<"Initial call of setjmp."<<std::endl;
        func();
        break;
    case 1:
        std::cout<<"Jumped back from func."<<std::endl;
        break;
    default:
        break;
    }
    return 0;
}

这里写图片描述

setjmp函数的使用限制:
SUSv3和C99规定,对setjmp的调用只能在以下语境中:

  • 构成选择或迭代语句中(if、switch、while等)的整个控制表达式。
  • 作为一元操作符!的操作对象,其最终表达式构成了选择或迭代语句的整个控制表达式。
  • 作为比较操作(==、!=、<等)的一部分,另一操作对象必须是一个整数常量表达式。
  • 作为独立的函数调用,且没有嵌入到更大的表达式中。
    根据以上限制,类似s = setjmp(env)用法是不符合标准的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值