**This is an old revision of the document!**

自定义操作系统

从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进行编程,因此您也可以从网络设备启动。

What's Available?

There are a few libraries documented on the wiki that are in fact part of OpenOS, so when you're implementing your own operation system, those won't be at your disposal. Most notably that includes the io, package and filesystem libraries. For a definite reference for what's available in an init script, check the kernel or machine.lua script for your current OpenComputers version. The following list isn't guaranteed to be complete and/or up-to-date!

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 only:
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

Accessing components in BIOS

Unlike in OpenOS you don't have the primary system for components in BIOS. That means you cannot just write component.redstone.setOutput, you have to manually create your proxy for the component first. For several reasons the proxy system is provided via the machine itself, so you can still use that. To get a proxy, use the component.proxy method. It expects the address of the component to wrap. You can either write that down manually, or get the list of components using component.list and go from there.

For example, to get the first best redstone component, you can do the following:

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

This works because component.list returns a Lua iterator: a function that can be called repeatedly to get the next element in whatever it iterates over, returning nil once there are no more elements.

A few more things

When an init script returns, the computer powers down, so you'll want to have a “main loop” in there, regardless of how you structure your OS otherwise. Signals must be processed using computer.pullSignal, you're free to use any model to provide this to programs running in your OS you please - this is what OpenOS' event.pull does, for example.

You'll also want to take care of setting up attached components during your OS' boot routine, such as binding GPUs to screens.

Aside from that, go crazy, be creative!