本文內容基於版本:Lua 5.3.0
global_State概述
global_State結構,我們可以稱之為Lua全局狀態機。從Lua的使用者角度來看,global_State結構是完全感知不到的:我們無法用Lua公開的API獲取到它的指針、句柄或引用,而且實際上我們也並不需要引用到它。但是對於Lua的實現來說,global_State是十分重要的部分:它里面有對主線程(lua_State實例)的引用、有全局字符串表、有內存管理函數、有GC需要的相關信息以及一切Lua在工作時需要的工作內存等等。
global_State與lua_State結構的關聯
通過luaL_newstate函數創建虛擬機時,第一塊申請的內存將用來存儲lua_State(主線程)和global_State(全局狀態機)實例。為了避免內存碎片的產生,同時減少內存分配和釋放的次數,Lua采用了一個小技巧:利用一個LG結構,把分配lua_State和global_State的行為關聯在一起。這個LG結構是在C文件內部定義,而不存在公開的H文件中,僅供該C代碼文件使用,因此這種依賴數據結構內存布局的用法負作用不大。
// luaconf.h /* @@ LUA_EXTRASPACE defines the size of a raw memory area associated with ** a Lua state with very fast access. ** CHANGE it if you need a different size. */ #define LUA_EXTRASPACE (sizeof(void *)) // lstate.c /* ** thread state + extra space */ typedef struct LX { lu_byte extra_[LUA_EXTRASPACE]; lua_State l; } LX; /* ** Main thread combines a thread state and the global state */ typedef struct LG { LX l; global_State g; } LG;
global_State的創建和銷毀
• global_State的創建和初始化
// lstate.c
LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { int i; lua_State *L; global_State *g; LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); if (l == NULL) return NULL; L = &l->l.l; g = &l->g; ...... return L; }
• global_State的銷毀
// lstate.c LUA_API void lua_close (lua_State *L) { L = G(L)->mainthread; /* only the main thread can be closed */ lua_lock(L); close_state(L); } // lstate.c static void close_state (lua_State *L) { global_State *g = G(L); luaF_close(L, L->stack); /* close all upvalues for this thread */ luaC_freeallobjects(L); /* collect all objects */ if (g->version) /* closing a fully built state? */ luai_userstateclose(L); luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); luaZ_freebuffer(L, &g->buff); freestack(L); lua_assert(gettotalbytes(g) == sizeof(LG)); (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ }
fromstate(L)宏
fromstate(L)宏的實現源碼:
// stddef.h(Linux & Windows) #define offsetof(s,m) (size_t)&(((s *)0)->m) // llimits.h #define cast(t, exp) ((t)(exp)) // lstate.c #define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l)))
fromstate(L)宏的實現圖解: