- 大师兄的Python源码学习笔记(三十): 运行环境初始化(二)
- 大师兄的Python源码学习笔记(三十一): 运行环境初始化(三
- 大师兄的Python源码学习笔记(三十二): 运行环境初始化(四
- 大师兄的Python源码学习笔记(三十三): 运行环境初始化(五
- 大师兄的Python源码学习笔记(三十四): 模块的动态加载机制
- 大师兄的Python学习笔记(三十): 爬虫(十一)
- 大师兄的Python学习笔记(二十八): 爬虫(九)
- 大师兄的Python源码学习笔记(二十九): 运行环境初始化(一
- 大师兄的Python源码学习笔记(十一): Python的虚拟机
- 大师兄的Python源码学习笔记(四十): Python的多线程
大师兄的Python源码学习笔记(二十八): 虚拟机中的类机制(七)
大师兄的Python源码学习笔记(三十): 运行环境初始化(二)
一、线程环境初始化
1. 线程模型回顾
- Python启动后,真正有意义的初始化动作是从Py_Initialize开始的:
Python\pylifecycle.c
void
Py_Initialize(void)
{
Py_InitializeEx(1);
}
- 其中仅有一个函数Py_InitializeEx被调用,它完成的一个重要工作就是加载多个基础module,如:__builtin__,sys等。
- 此外,它还会完成Python类型系统和异常系统的初始化,以及许多其它工作。
Python\pylifecycle.c
void
Py_InitializeEx(int install_sigs)
{
if (_PyRuntime.initialized) {
/* bpo-33932: Calling Py_Initialize() twice does nothing. */
return;
}
_PyInitError err;
_PyCoreConfig config = _PyCoreConfig_INIT;
config.install_signal_handlers = install_sigs;
err = _Py_InitializeFromConfig(&config);
_PyCoreConfig_Clear(&config);
if (_Py_INIT_FAILED(err)) {
_Py_FatalInitError(err);
}
}
- 关于Python的运行模型/线程模型,可以参考大师兄的Python源码学习笔记(十一): Python的虚拟机框架中的第五章:Python的运行时环境。
2. 初始化线程环境
- 在Win32平台,当执行一个可执行文件时,操作系统会先创建一个进程内核对象。
- 在Python中也是如此,它会调用PyInterpreterState_New创建一个PyInterpreterState对象(进程对象):
Python\pystate.c
PyInterpreterState *
PyInterpreterState_New(void)
{
PyInterpreterState *interp = (PyInterpreterState *)
PyMem_RawMalloc(sizeof(PyInterpreterState));
if (interp == NULL) {
return NULL;
}
interp->id_refcount = -1;
interp->id_mutex = NULL;
interp->modules = NULL;
interp->modules_by_index = NULL;
interp->sysdict = NULL;
interp->builtins = NULL;
interp->builtins_copy = NULL;
interp->tstate_head = NULL;
interp->check_interval = 100;
interp->num_threads = 0;
interp->pythread_stacksize = 0;
interp->codec_search_path = NULL;
interp->codec_search_cache = NULL;
interp->codec_error_registry = NULL;
interp->codecs_initialized = 0;
interp->fscodec_initialized = 0;
interp->core_config = _PyCoreConfig_INIT;
interp->config = _PyMainInterpreterConfig_INIT;
interp->importlib = NULL;
interp->import_func = NULL;
interp->eval_frame = _PyEval_EvalFrameDefault;
interp->co_extra_user_count = 0;
#ifdef HAVE_DLOPEN
#if HAVE_DECL_RTLD_NOW
interp->dlopenflags = RTLD_NOW;
#else
interp->dlopenflags = RTLD_LAZY;
#endif
#endif
#ifdef HAVE_FORK
interp->before_forkers = NULL;
interp->after_forkers_parent = NULL;
interp->after_forkers_child = NULL;
#endif
interp->pyexitfunc = NULL;
interp->pyexitmodule = NULL;
HEAD_LOCK();
interp->next = _PyRuntime.interpreters.head;
if (_PyRuntime.interpreters.main == NULL) {
_PyRuntime.interpreters.main = interp;
}
_PyRuntime.interpreters.head = interp;
if (_PyRuntime.interpreters.next_id < 0) {
/* overflow or Py_Initialize() not called! */
PyErr_SetString(PyExc_RuntimeError,
"failed to get an interpreter ID");
/* XXX deallocate! */
interp = NULL;
} else {
interp->id = _PyRuntime.interpreters.next_id;
_PyRuntime.interpreters.next_id += 1;
}
HEAD_UNLOCK();
interp->tstate_next_unique_id = 0;
return interp;
}
- 在Python的运行时环境属性会通过_PyRuntimeState对象管理:
Include\internal\pystate.h
typedef struct pyruntimestate {
int initialized;
int core_initialized;
PyThreadState *finalizing;
struct pyinterpreters {
PyThread_type_lock mutex;
PyInterpreterState *head;
PyInterpreterState *main;
/* _next_interp_id is an auto-numbered sequence of small
integers. It gets initialized in _PyInterpreterState_Init(),
which is called in Py_Initialize(), and used in
PyInterpreterState_New(). A negative interpreter ID
indicates an error occurred. The main interpreter will
always have an ID of 0. Overflow results in a RuntimeError.
If that becomes a problem later then we can adjust, e.g. by
using a Python int. */
int64_t next_id;
} interpreters;
#define NEXITFUNCS 32
void (*exitfuncs[NEXITFUNCS])(void);
int nexitfuncs;
struct _gc_runtime_state gc;
struct _warnings_runtime_state warnings;
struct _ceval_runtime_state ceval;
struct _gilstate_runtime_state gilstate;
// XXX Consolidate globals found via the check-c-globals script.
} _PyRuntimeState;
- 结合上面的代码,我们可以发现_PyRuntime对象实际在管理一个PyInterpreterState对象的链表,而表头正是_PyRuntime.interpreters.head。
- 这其实正是Python对操作系统上多进程的模拟。
- 紧接着,Python会立即调用PyThreadState_New,创建一个PyThreadState对象(线程对象)
Python\pystate.c
PyThreadState *
PyThreadState_New(PyInterpreterState *interp)
{
return new_threadstate(interp, 1);
}
Python\pystate.c
static PyThreadState *
new_threadstate(PyInterpreterState *interp, int init)
{
PyThreadState *tstate = (PyThreadState *)PyMem_RawMalloc(sizeof(PyThreadState));
if (_PyThreadState_GetFrame == NULL)
_PyThreadState_GetFrame = threadstate_getframe;
if (tstate != NULL) {
tstate->interp = interp;
tstate->frame = NULL;
tstate->recursion_depth = 0;
tstate->overflowed = 0;
tstate->recursion_critical = 0;
tstate->stackcheck_counter = 0;
tstate->tracing = 0;
tstate->use_tracing = 0;
tstate->gilstate_counter = 0;
tstate->async_exc = NULL;
tstate->thread_id = PyThread_get_thread_ident();
tstate->dict = NULL;
tstate->curexc_type = NULL;
tstate->curexc_value = NULL;
tstate->curexc_traceback = NULL;
tstate->exc_state.exc_type = NULL;
tstate->exc_state.exc_value = NULL;
tstate->exc_state.exc_traceback = NULL;
tstate->exc_state.previous_item = NULL;
tstate->exc_info = &tstate->exc_state;
tstate->c_profilefunc = NULL;
tstate->c_tracefunc = NULL;
tstate->c_profileobj = NULL;
tstate->c_traceobj = NULL;
tstate->trash_delete_nesting = 0;
tstate->trash_delete_later = NULL;
tstate->on_delete = NULL;
tstate->on_delete_data = NULL;
tstate->coroutine_origin_tracking_depth = 0;
tstate->coroutine_wrapper = NULL;
tstate->in_coroutine_wrapper = 0;
tstate->async_gen_firstiter = NULL;
tstate->async_gen_finalizer = NULL;
tstate->context = NULL;
tstate->context_ver = 1;
tstate->id = ++interp->tstate_next_unique_id;
if (init)
_PyThreadState_Init(tstate);
HEAD_LOCK();
tstate->prev = NULL;
tstate->next = interp->tstate_head;
if (tstate->next)
tstate->next->prev = tstate;
interp->tstate_head = tstate;
HEAD_UNLOCK();
}
return tstate;
}
- 与PyInterpreterState_New类似,new_threadstate通过interp.tstate_head管理PyThreadState对象链表,这与Python中的多线程实现有关。
- 观察PyThreadState对象:
Include\pystate.h
typedef struct _ts {
/* See Python/ceval.c for comments explaining most fields */
struct _ts *prev;
struct _ts *next;
PyInterpreterState *interp;
struct _frame *frame;
int recursion_depth;
... ...
} PyThreadState;
- 其中设置了从线程中获得函数调用栈的方法,所谓函数调用栈也就是PyFrameObject对象链表。
- 到这里,PyInterpreterState对象和PyThreadState对象建立起了联系,也就是进程和线程建立起了联系。
- 在Python运行是环境中,有一个全局变量_PyThreadState_Current,用来维护当前活动的线程对应的PyThreadState对象:
Include\pystate.h
# define _PyThreadState_Current _PyRuntime.gilstate.tstate_current
- 可以看出_PyThreadState_Current对应_PyRuntime.gilstate.tstate_current。
- Python通过调用PyThreadState_Swap设置_PyThreadState_Current:
Python\pystate.c
PyThreadState *
PyThreadState_Swap(PyThreadState *newts)
{
PyThreadState *oldts = GET_TSTATE();
SET_TSTATE(newts);
/* It should not be possible for more than one thread state
to be used for a thread. Check this the best we can in debug
builds.
*/
#if defined(Py_DEBUG)
if (newts) {
/* This can be called from PyEval_RestoreThread(). Similar
to it, we need to ensure errno doesn't change.
*/
int err = errno;
PyThreadState *check = PyGILState_GetThisThreadState();
if (check && check->interp == newts->interp && check != newts)
Py_FatalError("Invalid thread state for this thread");
errno = err;
}
#endif
return oldts;
}
- 接着,Python的初始化动作开始转向Python类型系统的初始化,这个转折是从Py_InitializeEx中调用_Py_ReadyTypes时开始的:
Python\pylifecycle.c
void
Py_InitializeEx(int install_sigs)
{
... ...
err = _Py_InitializeFromConfig(&config);
... ...
}
Python\pylifecycle.c
_PyInitError
_Py_InitializeFromConfig(const _PyCoreConfig *config)
{
_Py_Initialize_ReadEnvVarsNoAlloc();
PyInterpreterState *interp;
_PyInitError err;
err = _Py_InitializeCore(&interp, config);
... ...
}
Python\pylifecycle.c
_PyInitError
_Py_InitializeCore(PyInterpreterState **interp_p,
const _PyCoreConfig *src_config)
{
... ...
_PyInitError err;
... ...
err = _Py_InitializeCore_impl(interp_p, &config);
... ...
}
Python\pylifecycle.c
_PyInitError
_Py_InitializeCore_impl(PyInterpreterState **interp_p,
const _PyCoreConfig *core_config)
{
PyInterpreterState *interp;
_PyInitError err;
... ...
_Py_ReadyTypes();
... ...
Python\pylifecycle.c
void
_Py_ReadyTypes(void)
{
if (PyType_Ready(&PyBaseObject_Type) < 0)
Py_FatalError("Can't initialize object type");
if (PyType_Ready(&PyType_Type) < 0)
Py_FatalError("Can't initialize type type");
if (PyType_Ready(&_PyWeakref_RefType) < 0)
Py_FatalError("Can't initialize weakref type");
if (PyType_Ready(&_PyWeakref_CallableProxyType) < 0)
Py_FatalError("Can't initialize callable weakref proxy type");
... ...
}
- 这部分的具体能容可以参考大师兄的Python源码学习笔记(二十二): 虚拟机中的类机制(一)。
- 随后,Python还会初始化一些其它边边角角的东西,并进入下一个环节:设置系统module。
网友评论