![]() |
Tenok
A Linux-like Real-Time Operating System for Robotics and Internet of Things
|
BusyBox is built into the firmware. busybox runs an applet by name and busybox sh starts ash:
The shell is ash, with tab completion, a history of fifteen lines, $((...)) arithmetic, aliases and getopts. Beside it are thirty four applets:
configs/busybox.config is what turns them on. Only what Tenok turns on is written there; a name that does not appear is off. The build turns everything off first and then puts the file in place of it, so the ninety lines say what the firmware holds instead of listing the thousand things it does not.
A shell elsewhere runs ls by forking a process and letting it exec the file /bin/ls. Tenok has neither fork() nor exec(), and there is no such file: ls is a C function linked into the firmware. The shell therefore calls it and it returns, on the same stack of the same task.
BusyBox is written for the other arrangement. It expects the globals of an applet to start out as the linker laid them out, and it leaves memory and descriptors behind because a process exit would have given them back. What that exit would have done is done instead by user/busybox/:
| File | What it takes back |
|---|---|
applet.c | Lays the globals of BusyBox out again before the call, and unwinds an exit() back to the caller rather than ending the task |
memory.c | Every block the applet allocated and did not free |
descriptor.c | Every descriptor and stream it left open |
A pipeline and a command substitution both want two things running at once:
A here-document works, because BusyBox writes a short one into the pipe without forking:
Ctrl+C at the prompt is handled by the line editor. Inside an applet it unwinds the applet, which is what a shell reports as a signal elsewhere.
The BusyBox submodule stays exactly as its release left it. Everything Tenok changes lives in a separate repository as a patch series, because a patch carries the surrounding lines of the file it changes and is therefore covered by the GPL, while Tenok itself is under the BSD 2-Clause licence.
To apply the patches to a fresh checkout:
Running it again is safe and always produces the same tree. To turn what you changed in lib/busybox into a patch of the series:
The two patches are the whole of what BusyBox needs:
| Patch | What it changes |
|---|---|
0001-run-the-applets-without-fork.patch | Every applet is NOFORK, and run_nofork_applet() is told when one starts and when it returns |
0002-declare-what-tenok-provides.patch | Tenok does not understand m, and has neither /dev/fd, wait3() nor clearenv() |
Turn it on in configs/busybox.config, and add its source file to BB_APPLETS in user/busybox/busybox.mk. The applet table is derived from the //applet: comments of the BusyBox sources, so nothing else has to be told about it.
An applet that asks for something Tenok does not have will say so at the link, naming the function it wanted.