编写自制操作系统 =================== 从OpenComputers 1.3开始,电脑需要“操作系统”才能运行,OpenOS不再内置。 从1.4(.2?)开始,您甚至需要在电脑中安装EEPROM,以充当机器的BIOS。 虽然这使得组装电脑变麻烦了一点,但这也为想要编写自己的操作系统的人提供了更多可能;本文的主题就是编写操作系统! 引导启动 ------- 现在唯一还内置的是用来启动BIOS的“机器”。这个“机器”包装器是一个不可编辑的Lua脚本,负责创建沙箱和与“主机”端事物(即Java / Scala)的特别底层的交互。电脑上电后,将加载并运行该脚本。在建立完成沙箱环境后,它会查找EEPROM,并尝试将其数据作为Lua脚本运行。如果失败,计算机将崩溃。否则,将运行该BIOS。对于模组提供的Lua BIOS(使用 EEPROM +手册制作),它将执行以前由机器本身完成的操作: - 1.它将查找先前由`computer.setBootAddress`设定的地址对应的文件系统(可通过`computer.getBootAddress`读取此地址)。 - 2.在该文件系统上,它尝试加载并执行名为`init.lua`的文件。 - 3.如果成功了,那么任务完成,由用户脚本接管控制权。如果失败,它将遍历所有当前文件系统,再次执行步骤2,直到成功为止。 - 4.如果没有找到可用的`init.lua`脚本。计算机将崩溃并显示`no bootable medium found`错误. 但是,由于您可以随心所欲地对EEPROM进行编程,因此您也可以从网络设备启动。 什么可用? ----------------- Wiki 上记录了一些库,它们实际上是 OpenOS 的一部分,所以当你实现自己的操作系统时这些库无法使用。最值得注意的是,其中包括`io`、`package`和`filesystem`库。要获取init脚本中可用内容的明确参考,请查看系统内核代码或[[https://github.com/MightyPirates/OpenComputers/blob/master-MC1.12/src/main/resources/assets/opencomputers/lua/machine.lua|你当前OpenComputer模组版本对应的machine.lua脚本](英文)。 以下列表不能保证完整性与/或时效性! ```lua _G _VERSION assert error getmetatable ipairs load next pairs pcall rawequal rawget rawlen rawset select setmetatable tonumber tostring type xpcall bit32.arshift bit32.band bit32.bnot bit32.bor bit32.btest bit32.bxor bit32.extract bit32.lrotate bit32.lshift bit32.replace bit32.rrotate bit32.rshift coroutine.create coroutine.resume coroutine.running coroutine.status coroutine.wrap coroutine.yield debug.getinfo debug.traceback debug.getlocal debug.getupvalue math.abs math.acos math.asin math.atan math.atan2 math.ceil math.cos math.cosh math.deg math.exp math.floor math.fmod math.frexp math.huge math.ldexp math.log math.max math.min math.modf math.pi math.pow math.rad math.random math.randomseed math.sin math.sinh math.sqrt math.tan math.tanh os.clock os.date os.difftime os.time string.byte string.char string.dump string.find string.format string.gmatch string.gsub string.len string.lower string.match string.rep string.reverse string.sub string.upper table.concat table.insert table.pack table.remove table.sort table.unpack checkArg component.doc component.fields component.invoke component.list component.methods component.proxy component.slot component.type computer.address computer.addUser computer.beep computer.energy computer.freeMemory computer.getArchitectures computer.getArchitecture computer.getBootAddress computer.getDeviceInfo computer.getProgramLocations computer.isRobot computer.maxEnergy computer.pullSignal computer.pushSignal computer.removeUser computer.setArchitecture computer.setBootAddress computer.shutdown computer.tmpAddress computer.totalMemory computer.uptime computer.users unicode.char unicode.charWidth unicode.isWide unicode.len unicode.lower unicode.reverse unicode.sub unicode.upper unicode.wlen unicode.wtrunc -- 仅Lua 5.3: coroutine.isyieldable string.pack string.unpack string.packsize table.move math.maxinteger math.mininteger math.tointeger math.type math.ult utf8.char utf8.charpattern utf8.codes utf8.codepoint utf8.len utf8.offset ``` 在BIOS中访问组件 ----------------- 与OpenOS不同,BIOS没有首选组件系统。这意味着你不能只写`component.redstone.setOutput`,而是必须先手动为组件创建代理对象。出于多种原因,代理对象系统是通过机器本身提供的,因此您仍然可以使用它。若要获取代理对象,请使用`component.proxy`方法。此函数需要你提供打算包装的组件地址。 您可以手动写下来,或者用`component.list`来获得组件的列表并从中获取。 比如说,要获得第一个红石组件,您可以执行以下操作: ```lua local r = component.proxy(component.list("redstone")()) ``` 这行代码可以工作,因为`component.list`返回一个 Lua 迭代器——一个可重复调用来获得下一个元素的函数,当没有元素时返回`nil`。 其他东西 ----------------- 当`init.lua`脚本返回(结束运行)的时候,电脑将会关机,所以无论您如何构建操作系统,在脚本里都需要有一个“主循环”。 信号必须使用`computer.pullSignal`处理,您可以自由使用任何模块将此函数的功能提供给在操作系统中运行的程序——例如,OpenOS中的`event.pull`就是这么操作的。 您还需要在操作系统的启动流程中设置连接到电脑的组件,例如将GPU绑定到屏幕。 除此之外,发挥你最疯狂的想象吧!