设为首页 收藏本站
查看: 525|回复: 0

[经验分享] Python虚拟机的初始化概览

[复制链接]

尚未签到

发表于 2017-4-30 11:11:59 | 显示全部楼层 |阅读模式
今天想跟下Python虚拟机的启动,看看以调试模式跑起python_d.exe是怎么一个过程。
1. d:\Python-2.7.2\Modules\python.c文件是main函数,直接调用Py_Main函数;
2. 在Py_Main函数中,初始化函数为Py_Initialize();,而后者直接调用Py_InitializeEx(1);函数;
3. 在Py_InitializeEx函数中,首先判断是否已经初始化过,如果有则返回,没有就改下标志,开始初始化;第一步也是十分关键的一步,是调用函数(interp=PyInterpreterState_New();)创建PyInterpreterState对象(即解释器进程,现在Python一个解释器只有一个进程,所以存在一个缺点,在多核的机子上也只能存在一个进程)。
4. 在PyInterpreterState_New()函数中,首先为PyInterpreterState对象分配内存:
PyInterpreterState*interp=(PyInterpreterState*)
malloc(sizeof(PyInterpreterState));
如果分配内存成功,执行HEAD_INIT();宏:
#ifdefWITH_THREAD
#include"pythread.h"
staticPyThread_type_lockhead_mutex=NULL;/*Protects interp->tstate_head */
#defineHEAD_INIT()(void)(head_mutex||(head_mutex=PyThread_allocate_lock()))
#defineHEAD_LOCK()PyThread_acquire_lock(head_mutex,WAIT_LOCK)
#defineHEAD_UNLOCK()PyThread_release_lock(head_mutex)
不论是从名称还是注释都可以看出head_mutex是用来保护解释器进程的tstate_head成员的。
在head_mutex为NULL的情况下会调用PyThread_allocate_lock()函数初始化head_mutex变量。
接着初始化其它成员。
于是,解释器进程就这么创建了……


接着立马创建线程:tstate=PyThreadState_New(interp);,继而调用new_threadstate(interp,1);
同样地,先为线程对象分配空间:PyThreadState*tstate=(PyThreadState*)malloc(sizeof(PyThreadState));
接着一样是对线程对象进行初始化,然后切换一下线程:(void)PyThreadState_Swap(tstate);


接下来一步是很重要的,就是初始化类型信息:_Py_ReadyTypes();
后续初始化顺序如下:
if(!_PyFrame_Init())
Py_FatalError("Py_Initialize:can't init frames");


if(!_PyInt_Init())
Py_FatalError("Py_Initialize:can't init ints");


if(!_PyLong_Init())
Py_FatalError("Py_Initialize:can't init longs");


if(!PyByteArray_Init())
Py_FatalError("Py_Initialize:can't init bytearray");


_PyFloat_Init();


第一个函数其实就是初始化变量staticPyObject*builtin_object;为字符串“__builtins__”;
第二个函数是初始化小整数的缓存链表,这里的小整数范围是可以自定义再重新编译进行设置的,过程挺有趣的;
第三个函数初始化Long类型信息,第四个函数没做什么;
接着初始化Float类型信息。


然后是初始化interp的modules和modules_reloading成员,都是简单地调用PyDict_New()函数赋值。
如果需要的话,还会初始化Unicode编码:_PyUnicode_Init();


接着是模块初始化,代码有省略:
bimod=_PyBuiltin_Init();
interp->builtins=PyModule_GetDict(bimod);
sysmod=_PySys_Init();


interp->sysdict=PyModule_GetDict(sysmod);
还有模块导入机制、异常、警告的初始化,代码有省略:
_PyImport_Init();
_PyExc_Init();
_PyWarnings_Init();




initmain();/*Module __main__ */


初始化全局锁:
/*auto-thread-state API, if available */
#ifdefWITH_THREAD
_PyGILState_Init(interp,tstate);
#endif/*WITH_THREAD */


最后是检查stdin,stdout,stderr和设置相关信息。


然后回到Py_Main,输出版本信息以及“>>>”,等用户输入。


假设输入“a = 1”,然后按Enter键:
Python会先对用户输入进行编译(co=PyAST_Compile(mod,filename,flags,arena);),生成PyCodeObject,然后再执行:v=PyEval_EvalCode(co,globals,locals);


PyObject*
PyEval_EvalCode(PyCodeObject*co,PyObject*globals,PyObject*locals)
{
returnPyEval_EvalCodeEx(co,
globals,locals,
(PyObject**)NULL,0,
(PyObject**)NULL,0,
(PyObject**)NULL,0,
NULL);
}


于是我们最终进入到PyEval_EvalFrameEx函数,在这里用大量的switch/case来执行指令。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-371142-1-1.html 上篇帖子: 服务器暂时无法响应您的请求 500 Internal Server Error 下篇帖子: [转]Python下划线完全解读
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表