Example 1 : Simple system

From Embeded Linux (and more) Wiki by Nathael
< Dev‎ | Embedded‎ | Rootfs‎ | BusyBox
Revision as of 19:28, 15 January 2025 by Drizzt (talk | contribs)
Jump to navigation Jump to search


Most of the time when you start with BusyBox as the heart of your system you do not plan for a multi-user desktop box, but rather aim for a small, single purpose embedded system, so you won't need too many stuff to get it running.

This example explains how to create a minimal Linux based base system using BusyBox as a base for the userland part of the system.

Minimal configuration

You can start with this example minimal config.
Some information about my choices :

  • This configuration is based upon the "defaultconfig", but with many modifications (not all listed here)
  • No "/usr" support (all binaries under /bin and /sbin)
  • Archival utilities limited to tar with "xz" and "bz2" support
  • Removed console utilities
  • Removed most users handling utilities : users should be known when building the system (or added by direct editting of the files)
  • Removed disk partitionning and formatting utilities save for UBIFS
  • Removed runit support
  • Removed all commands I never used on a full blown system

Compile using uClibc

The options selected for a minimal configuration should not impact the compilation process, unless you want a really small system, which is common when using BusyBox due to storage size constraints.
In this case using uClibc instead of the GNU libc is a good idea.
Most information about using uClibc in a cross-compilation toolchain can be found on uClibc website.
You will then need to use the cross-compilation prefix of your toolchain to build BusyBox.

With a stripped down BusyBox, you may well end up with :

Final link with: <none>

But note that in this case you'll still need the selected libc (uClibc) !

Directories and links

Here is a very simple set of directories for a configuration without "/usr", according to the minimal configuration given above :

mkdir -p dev etc lib/{modules,firmware} proc root run sys var/{log,spool/cron}

Then add some links :

ln -s run/tmp tmp 
ln -s ../run/tmp var/tmp

Libraries

As this is a very simple system the set of libraries should be very limited. You may need additional ones for your application binaries so I cannot give you a full list, but if you chose to have dynamically linked binaries (which is usually a good idea if your system has more than one or two binaries) you will always need these two :

  • The dynamic linker/loader (name depending on the target architecture/triplet) : ld-linux-*.so.*
  • the libc

In order to check for additional library requirements, have a look at this part in the second example below.

Once you know which libraries you need, you'll need to figure which files to put in which directory for each library.

Unless you specified an absolute or relative pathname during the linking stage of the compilation of your binaries, there is no "fixed" location for each library file, save maybe the dynamic linker/loader (ld-linux-*.so.*), which usually goes under "/lib", and the dynamic linker will end up looking for libraries in some "default" path which usually includes "/lib".

So the easy way is to create a single "/lib" directory (remember that we chose to desactivate the use of "/usr" in BusyBox configuration).

Bootup script(s)

Now Busybox seems to support two init systems : the historic one sharing similarities to SysVinit (without the runlevels) and one similar to runnit. I choose to disable runnit support in this minimal configuration, so the "init" applet will look for the "/etc/inittab" configuration file.
There is an example one under "examples/" in BusyBox source tree.
Anyway, even without this file the applet will look for a script called "/etc/init.d/rcS" and, even if it found none, start an "askfirst" shell (display the message "Please press Enter to activate this console." which would then give you a prompt). All the details are explained in the example inittab file in BusyBox sources.

So here is a short list of files for the init part of the base system :

  • /etc/inittab
  • /etc/init.d/rcS
  • Other service or configuration script(s)

What you put in each file depends on your application and your needs.

In SysVinit the rcS script (called by init according to inittab content) calls "/etc/init.d/rc" for the runlevel S, which will start all scripts from "/etc/rcS.d", and after this, init will change to the default runlevel configured in inittab, which will call "/etc/init.d/rc" for the default runlevel (usually 2) which in turn will start all scripts from the corresponding "/etc/rcN.d" directory.

In busybox there are no runlevels, and usually much less configuration to perform, with this configuration being more "static".
As such, I usually create a single "startup" script (the "/etc/init.d/rcS" one) which does all the usual system configuration and setup (hostname, mounts, hwclock, modules, sysctl, random init, ...) then the network configuration (static IP or DHCP, firewall, ...)
Having everything started sequentially by a single script which does not try to read a hundred configuration files is not that much slower than using a heavy, complicated system which tries to run everything in parallel but needs to be heavily configured to avoid race conditions and handle dependencies.

In order to start the services (sshd, inetd, ...) and the main application(s) you have some options :

  • add them at the end of the rcS script (using start-stop-daemon if need be for respawn)
  • create a separate script for them (or one for each) and call them at the end of the rcS one (still using start-stop-daemon if need be)
  • use the "wait", "once" or "respawn" actions in inittab

I usually use the inittab solution, sometimes with a wrapper script.

Configuration files

The list of configuration files depend on what you have selected in you BusyBox configuration and on what you write in your scripts.
And their content depends on your needs, of course.
In order to know which ones you'll need, there is no easy way (as far as I know).

  • Some of them are listed within BusyBox configuration menu and help for each entry, so you can start there, reading the help for each entry you have activated (save thoses you think would not need a configuration file, like archiving related utilities).
  • You can also look at the content of "/etc" on your development host
  • Another solution is to try running the system, try to start the services you want, and check the messages on the console.

Here is a short list of those I have listed/created for this simple example :

  • /etc/nologin
  • /etc/securetty
  • /etc/shells
  • /etc/{passwd,shadow,groups}
  • TO BE COMPLETED

Application binaries and related files

This part is really only up to you and your application.

As this simple BusyBox example does not include any kind of "application packaging" support there's not need (save for your mental health) to stick to any particular organisation for your files.