【Lua知識整理】——Lua虛擬機器的初始化
1. 建立Lua虛擬機器
lua_State *lua_newstate(lua_Alloc f, void *ud) API可以為我們建立一個新的獨立的Lua虛擬機器。
引數指定了虛擬機器中的記憶體分配策略,例如我們已經在自己的程式碼中實現了記憶體池,這時候只需要寫一個符合lua_Alloc原型的介面卡,然後指定為Lua的記憶體分配器就可以了,使得記憶體分配更加靈活。當然,如果不想自定義記憶體分配策略,也可以使用luaL_newstate,這樣Lua會幫你定義預設的記憶體分配策略。
我們可以先來看一下luaL_newstate的原始碼:
// 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; // 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; }
可見,通過luaL_newstate 建立Lua虛擬機器時,第一塊申請的記憶體將用來儲存global_State(全域性狀態機)和lua_State(主執行緒)例項。為了避免記憶體碎片的產生,同時減少記憶體分配和釋放的次數,Lua採用了一個小技巧:利用一個LG結構,把分配lua_State和global_State的行為關聯在一起。這個LG結構是在C檔案內部定義,而不存在公開的H檔案中,僅供該C程式碼檔案使用,因此這種依賴資料結構記憶體佈局的用法負作用不大。
2. 關於global_State和lua_State
在一個獨立的Lua虛擬機器中,global_State是一個全域性的結構, 而lua_State可以有多個。
global_State
global_State結構,我們可以稱之為Lua全域性狀態機。從Lua的使用者角度來看,global_State結構是完全感知不到的:我們無法用Lua公開的API獲取到它的指標、控制代碼或引用,而且實際上我們也並不需要引用到它。但是對於Lua的實現來說,global_State是十分重要的部分。
它管理著Lua中全域性唯一的資訊,主要是以下功能:
(1)記憶體分配策略及其引數
在呼叫lua_newstate的時候配置它們. 也可以通過lua_getallocf和lua_setallocf隨時獲取和修改它
(2)字串的hashtable
全域性的字串雜湊表,即儲存那些短字串,使得整個虛擬機器中短字串只有一份例項。具體參見
(3)垃圾回收相關的資訊,記憶體使用統計量
(4)panic, 當無保護呼叫發生時, 會呼叫該函式, 預設是null, 可以通過lua_atpanic配置.(用於異常處理)
(5)登錄檔, 登錄檔是一個全域性唯一的table
(6)記錄lua中元方法名稱 和 基本型別的元表
[注意, lua中table和userdata每個例項可以擁有自己的獨特的元表--記錄在table和userdata的mt欄位, 其他型別是每個型別共享一個元表--就是記錄在這裡].
(7)upvalue連結串列
(8)主lua_State, 一個lua虛擬機器中, 可以有多個lua_State, lua_newstate會創建出一個lua_State(稱為主執行緒), 並邦定到global_state的主lua_State上
lua_State
執行緒,這裡執行緒的概念區別於作業系統的執行緒,實際上也是Lua中定義的一種狀態機。lua_State主要是管理一個lua虛擬機器的執行環境, 一個lua虛擬機器可以有多個執行環境。
(1)要注意的是, 和nil, string, table一樣,lua_State也是lua中的一種基本型別, lua中的表示是TValue {value = lua_State, tt = LUA_TTHREAD}
(2)lua_State的成員和功能
a. 棧的管理, 包括管理整個棧和當前函式使用的棧的情況
b. CallInfo的管理, 包括管理整個CallInfo陣列和當前函式的CallInfo
c. hook相關的, 包括hookmask, hookcount, hook函式等