虚拟机运行python_简介Python虚拟机中的Python运行环境

本文详细解读了Python运行环境中PyEval_EvalFrameEx函数的作用,介绍了字节码指令的执行过程,涉及堆栈初始化、指令遍历与switch/case结构,揭示了Python程序执行的底层机制。
摘要由CSDN通过智能技术生成

其实Python运行环境是一个全局性的概念,而执行环境实际就是一个栈帧,是Code Block对应的概念,两者之间存在着本质上的区别,在以后的运行操作过程中就可以了解到他们呢两者之间的不同。

运行时环境的初始化过程非常地复杂,后面将用单独的一章来剖析,这里假设初始化的动作已经完成,我们已经站在了Python虚拟机的门槛外,只需要轻轻推动一下***张骨牌,整个执行过程就像多米诺骨牌一样,一环扣一环地展开。

这个推动***张骨牌的地方在一个名叫PyEval_EvalFramEx的函数中,这个函数实际上就是Python的虚拟机的具体实现,它是一个非常巨大的函数,因此我们在列出其中的源代码时和以前有些不同。

PyEval_EvalFrameEx首先会初始化一些变量,其中PyFrameObject对象中的PyCodeObject对象包含的重要信息都被照顾到了。当然,另一个重要的动作就是初始化了堆栈的栈顶指针,使其指向f->f_stacktop:[PyEval_EvalFrameEx in ceval.c]

co=f->f_code;

names=co->co_names;

coconsts= co->co_consts;

ffastlocals= f->f_localsplus;

ffreevars= f->f_localsplus + co->co_nlocals;

first_instr= (unsigned char*)PyString_AS_STRING(co->co_code);

next_instr=first_instr+ f->f_lasti + 1;

stack_pointer=f->f_stacktop;

f->f_stacktop=NULL; /* remains NULL unless yield suspends frame */

前面我们说过,在PyCodeObject对象的co_code域中保存着字节码指令和字节码指令的参数,Python虚拟机执行字节码指令序列的过程就是从头到尾遍历整个co_code、依次执行字节码指令的过程。

next_instr永远指向下一条待执行的字节码指令的位置;f_lasti指向上一条已经执行过的字节码指令的位置。展示了这3个变量在遍历中某时刻的情形:[ceval.c]

/* Interpreter main loop */

PyObject* PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)

{

……

why=WHY_NOT;

……

for (;;) {

……

fast_next_opcode:

f->f_lasti=INSTR_OFFSET();

//获得字节码指令

opcode=NEXTOP();

oparg=0;

//如果指令需要参数,获得指令参数

if (HAS_ARG(opcode))

oparg=NEXTARG();

dispatch_opcode:

switch (opcode) {

case NOP:

goto fast_next_opcode;

case LOAD_FAST:

……

}

}

那么这个一步一步的动作是如何完成的呢,我们来看一看Python运行环境执行字节码指令的整体架构,其实就是一个for循环加上一个巨大的switch/case结构,熟悉Windows SDK编程的朋友可以想象一下Windows下那个巨大的消息循环,就是那样的结构。在对PyCodeObject对象的分析中我们说过,Python的字节码有的是带参数的,有的是没有参数的,而判断是否带参字节码是通过HAS_ARG这个宏实现的。

注意,对不同的字节码指令,由于存在是否需要指令参数的区别,所以next_instr的位移可能是不同的。但是无论如何,next_instr总是指向Python下一条要执行的字节码,这很像x86平台上的那个PC寄存器。

Python在获得了一条字节码指令和其需要的指令参数后,会对字节码指令利用switch进行判断,根据判断的结果选择不同的case语句,每一条字节码指令都会对应一个case语句。在case语句中,就是Python对字节码指令的实现。

在成功执行完一条字节码指令后,Python运行环境的执行流程会跳转到fast_next_opcode处,或者是for循环处,不管如何,Python接下来的动作都是获得下一条字节码指令和指令参数,完成对下一条指令的执行。如此一条一条地遍历co_code中包含的所有字节码指令,最终完成了对Python程序的执行。

【编辑推荐】

【责任编辑:苏越 TEL:(010)68476606】

点赞 0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值