编写自制操作系统

从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 的一部分,所以当你实现自己的操作系统时这些库无法使用。最值得注意的是,其中包括iopackagefilesystem库。要获取init脚本中可用内容的明确参考,请查看系统内核代码或[[https://github.com/MightyPirates/OpenComputers/blob/master-MC1.12/src/main/resources/assets/opencomputers/lua/machine.lua|你当前OpenComputer模组版本对应的machine.lua脚本](英文)。 以下列表不能保证完整性与/或时效性!

snippet.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来获得组件的列表并从中获取。

比如说,要获得第一个红石组件,您可以执行以下操作:

snippet.lua
local r = component.proxy(component.list("redstone")())

这行代码可以工作,因为component.list返回一个 Lua 迭代器——一个可重复调用来获得下一个元素的函数,当没有元素时返回nil

其他东西

init.lua脚本返回(结束运行)的时候,电脑将会关机,所以无论您如何构建操作系统,在脚本里都需要有一个“主循环”。
信号必须使用computer.pullSignal处理,您可以自由使用任何模块将此函数的功能提供给在操作系统中运行的程序——例如,OpenOS中的event.pull就是这么操作的。

您还需要在操作系统的启动流程中设置连接到电脑的组件,例如将GPU绑定到屏幕。

除此之外,发挥你最疯狂的想象吧!