1. 程式人生 > >【Lua知識整理】——Lua虛擬機器的初始化

【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

全域性的字串雜湊表,即儲存那些短字串,使得整個虛擬機器中短字串只有一份例項。具體參見 

Lua字串處理

(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函式等