Trong thiết kế động cơ game của chúng tôi, một hệ thống tập tin ảo (Virtual File System - VFS) đã được xây dựng với khả năng tích hợp nhiều loại hệ thống tập tin thực thể khác nhau như mô-đun hệ thống tập tin địa phương, mô-đun RAM, hay thậm chí là mô-đun truy cập qua mạng. Mô hình này cũng áp dụng cho kho tài nguyên (resource repository) mà chúng tôi thảo luận trước đó - một dạng mô-đun hệ thống tập tin đặc biệt.
Điểm đặc biệt nằm ở việc toàn bộ hệ thống này được viết bằng Lua, tạo ra vòng lặp “mẹ đẻ trứng hay trứng nở mẹ” (chicken and egg problem). Mã nguồn Lua nằm trong chính hệ thống tập tin này, trong khi mô-đun mạng - phương thức cập nhật chính cho hệ thống - cũng được viết bằng Lua và lưu trữ bên trong hệ thống đó. Làm thế nào để khởi động được hệ thống khi phần mềm phụ thuộc lẫn nhau như vậy?
Giải pháp tổng thể
Chúng tôi thiết kế một cơ chế khởi động tự thân (self-bootstrapping) với các nguyên tắc sau:
Đơn giản hóa cấu trúc: Thay vì cho phép gắn kết mô-đun hệ thống tập tin bất kỳ vào bất kỳ thư mục nào, chúng tôi thiết lập một thư mục cố định .firmware để chứa mã khởi động tối thiểu. Mã này có thể được cập nhật sau khi mô-đun mạng hoạt động.
Tối ưu hóa bằng C: Dù ưu tiên sử dụng Lua, nhưng giai đoạn khởi động đầu tiên vẫn cần một lõi C tối giản để tạo môi trường ảo Lua đầu tiên. Lõi này chỉ chứa các hàm thiết yếu như truy cập tập tin qua API hệ điều hành.
Cơ chế hai lớp khởi động:
Giai đoạn 1: Khởi tạo VM Lua tối giản từ mã nguồn vật lý trong .firmware
Giai đoạn 2: Sử dụng VM này để tải phiên bản mới từ kho tài nguyên (repo), sau đó thay thế hoàn toàn VM ban đầu bằng phiên bản cập nhật
localerrlog,firmware,dir,cfuncs,V=...cfuncs=cfuncs()package.preload.lfs=cfuncs.lfs-- Khởi tạo thư viện lfslocalvfs=assert(loadfile(firmware.."/vfs.lua"))()localrepo=vfs.new(firmware,dir)-- Thử tải phiên bản vfs mới từ kholocalf=repo:open(".firmware/vfs.lua")iffthenlocalvfs_source=f:read"a"f:close()vfs=assert(load(vfs_source,"@.firmware/vfs.lua"))()repo=vfs.new(firmware,dir)endlocalfunctionreadfile(f)iffthenlocalcontent=f:read"a"f:close()returncontentendend-- Kiểm tra cập nhật bootstraplocalbootstrap=readfile(repo:open(".firmware/bootstrap.lua"))ifbootstrapthenlocalnewboot=load(bootstrap,"@.firmware/bootstrap.lua")localselfchunk=string.dump(debug.getinfo(1,"f").func,true)ifstring.dump(newboot,true)~=selfchunkthennewboot(...)-- Nạp lại phiên bản mớireturnendend-- Hàm tải tập tin cuối cùngfunction_LOAD(path)localf=repo:open(path)iffthenlocalcontent=f:read"a"f:close()returncontentendend-- Khởi tạo VFS chính thức_VFS=cfuncs.initvfs(V)
Quy trình khởi động chi tiết
Khởi tạo VM Lua cơ sở: Sử dụng C code để tải file bootstrap.lua vật lý từ thư mục firmware