zoukankan      html  css  js  c++  java
  • pvm虚拟机基本原理

    零、绪论:特别鸣谢下文博客,自己博客是对这篇博客的学习笔记:

    大佬webber博客:https://www.cnblogs.com/webber1992/p/6597166.html

    一、三种文件:

      1、pyc文件:py文件编译后的二进制文件。

      2、pyo文件:优化后的py编译的文件。

      3、pyd文件:其他语言编程的py库。

    二、python编译的过程:

      python不单纯是一种解释性语言,也需要编译,需要编译成字节码。然后模仿可执行文件的入栈出栈调用顺序执行。pyc文件中保存这编译而成的字节码,PVM从PyCodeObject读取字节码一条一条执行。PyCodeObject保存字节码以及进程上下文信息。pyc文件在import事后创建PyCodeObject对象,一般是由py_compile模块操作的。直接执行py文件不会生成pyc,但是可以通过python -m xxx.py生成pyc文件。

    从整体上看:OS中执行程序离不开两个概念:进程和线程。python中模拟了这两个概念,模拟进程和线程的分别是PyInterpreterStatePyTreadState。即:每个PyThreadState都对应着一个帧栈,python虚拟机在多个线程上切换。当python虚拟机开始执行时,它会先进行一些初始化操作,最后进入PyEval_EvalFramEx函数,它的作用是不断读取编译好的字节码,并一条一条执行,类似CPU执行指令的过程。函数内部主要是一个switch结构,根据字节码的不同执行不同的代码。

    三、PyCodeObject的结构:

     1 typedef struct {
     2     PyObject_HEAD
     3     int co_argcount;        /* 位置参数个数 */
     4     int co_nlocals;         /* 局部变量个数 */
     5     int co_stacksize;       /* 栈大小 */
     6     int co_flags;   
     7     PyObject *co_code;      /* 字节码指令序列 */
     8     PyObject *co_consts;    /* 所有常量集合 */
     9     PyObject *co_names;     /* 所有符号名称集合 */
    10     PyObject *co_varnames;  /* 局部变量名称集合 */
    11     PyObject *co_freevars;  /* 闭包用的变量名集合 */
    12     PyObject *co_cellvars;  /* 内部嵌套函数引用的变量名集合 */
    13     /* The rest doesn’t count for hash/cmp */
    14     PyObject *co_filename;  /* 代码所在文件名 */
    15     PyObject *co_name;      /* 模块名|函数名|类名 */
    16     int co_firstlineno;     /* 代码块在文件中的起始行号 */
    17     PyObject *co_lnotab;    /* 字节码指令和行号的对应关系 */
    18     void *co_zombieframe;   /* for optimization only (see frameobject.c) */
    19 } PyCodeObject;

    引用的C语言的PyCodeObject的结构体

    四、执行过程:

    Python虚拟机的原理就是模拟可执行程序再X86机器上的运行,X86的运行时栈帧如下图:

                               

    假如test.py用C语言来实现,会是下面这个样子:

    复制代码
    const char *s = “hello”;
     
    void func() {
        printf(“%s
    ”, s);
    }
     
    int main() {
        func();
        return 0;
    }
    复制代码

    Python虚拟机的原理就是模拟上述行为。当发生函数调用时,创建新的栈帧,对应Python的实现就是PyFrameObject对象。

    PyFrameObject对象创建程序运行时的动态信息,即执行环境,相关源码大致如下:

    复制代码
    typedef struct _frame{  
        PyObject_VAR_HEAD //"运行时栈"的大小是不确定的  
        struct _frame *f_back; //执行环境链上的前一个frame,很多个PyFrameObject连接起来形成执行环境链表  
        PyCodeObject *f_code; //PyCodeObject 对象,这个frame就是这个PyCodeObject对象的上下文环境  
        PyObject *f_builtins; //builtin名字空间  
        PyObject *f_globals;  //global名字空间  
        PyObject *f_locals;   //local名字空间  
        PyObject **f_valuestack; //"运行时栈"的栈底位置  
        PyObject **f_stacktop;   //"运行时栈"的栈顶位置  
        //...  
        int f_lasti;  //上一条字节码指令在f_code中的偏移位置  
        int f_lineno; //当前字节码对应的源代码行  
        //...  
          
        //动态内存,维护(局部变量+cell对象集合+free对象集合+运行时栈)所需要的空间  
        PyObject *f_localsplus[1];    
    } PyFrameObject; 
  • 相关阅读:
    关闭编辑easyui datagrid table
    sql 保留两位小数+四舍五入
    easyui DataGrid 工具类之 util js
    easyui DataGrid 工具类之 后台生成列
    easyui DataGrid 工具类之 WorkbookUtil class
    easyui DataGrid 工具类之 TableUtil class
    easyui DataGrid 工具类之 Utils class
    easyui DataGrid 工具类之 列属性class
    oracle 卸载
    “云时代架构”经典文章阅读感想七
  • 原文地址:https://www.cnblogs.com/KevinGeorge/p/8245875.html
Copyright © 2011-2022 走看看