[klibc] initramfs howto

Daniel Thaler daniel at dthaler.de
Wed Aug 10 06:01:52 PDT 2005


Andreas Jellinghaus wrote:
> what about:
> the binaries in your initramfs can be linked to any libc
> and both shared and static linking will work fine. however
> if you seek limited functionality for your initramfs and
> want it to be integrated in the kernel binary, a special
> libc like klibc will work well and keep the result small.
> 
> for external initramfs files you can choose any libc,
> klibc will give you a small initramfs, but requires
> the programs to be compiled and linked against it.
> the usual glibc will also work and provide all the
> features glibc has and allow you to use standard
> applications without special recompiling or linking,
> but glibc is bigger and thus needs more memory.
> 
> ?
> 
> seriosly, glibc is 1.2 MB on my hard disk.
> many appliances these day have 32 or 64 MB ram,
> so spending one MB on glibc is not a big deal
> I think, compared to possibly many hours people
> might spend to port application XYZ to other libc.
> (sorry, I have no idea how easy it is to port to
> klibc/ulibc/dietlibc, but even simple recompiling
> and repackaging and maintaining something on your
> own, those all take time.)
> 
> 
>>"Userspace programs need a C library, but using glibc would lead to
>>(comparatively) large binaries, thereby increasing the kernel image size."
> 
> 
> I think the text should be balanced to give the disavantage (big)
> as well as the advantage (huge feature set, no need to recompile or relink).

You need to look at this in context; it's under the heading "What are klibc and 
initramfs?"
I was trying to write one paragraph that answers "What is klibc?" and "Why does 
klibc exist?" What I came up with was basically:
klibc: small, minimal featureset - glibc: big, full featureset
Maybe you have a better idea for a brief introduction to klibc? Maybe even one 
that doesn't mention glibc at all...

The text you just suggested is good, but out of place under "What is klibc".
It would fit into "Contents of the initramfs" nicely, which is where I'm going 
to put it, to replace the current brief mention of linking.

Daniel
-------------- next part --------------
INITRAMFS HOWTO


0) What are klibc and initramfs?

Initramfs is a ramfs into which an initramfs archive (a gzipped cpio archive)
is unpacked before the kernel performs the late-startup tasks like mounting
the root filesystem. Initramfs will allow such tasks to be performed in
userpace in the future. Initramfs archives can be attached to the kernel image,
so from a user's point of view things can continue to "just work"

Klibc is a means to this end: Userspace programs need a C library, but using
glibc would lead to (comparatively) large binaries, thereby increasing the
kernel image size. Klibc is a minimal C library, which contains the bare
essentials needed for the programs that will perform the userspace set-up in
future. The klibc distribution also contains a number of utilities that are useful
in an initramfs.

For more info read <http://lwn.net/Articles/14776/> (Initramfs arrives)


1) Creating an Initramfs

1.1) During the kernel build via kbuild
The easiest way to create an initramfs archive is to set INITRAMFS_SOURCE
in your kernel config. 
INITRAMFS_SOURCE should point to either
    - a directory containing the files to be included in the archive
      There is a slight problem with this, as you will need device files
      which you can only create as root.
    - a file which should contain entries according to the format described by
      the "usr/gen_init_cpio" program in the kernel tree.
      This solves the above problem, as creating device nodes only involves
      adding a line to a text file.
    - a cpio archive with a .cpio suffix
The archive created by setting INITRAMFS_SOURCE is saved as
usr/initramfs_data.cpio.gz and built into the kernel.

1.2) Calling "usr/gen_init_cpio" manually
You could also call "usr/gen_init_cpio" manually. This is the program used by
kbuild, so it takes the same list.

1.3) Using cpio
Running "find | cpio --format=newc -o | gzip > archive.cpio.gz" will create a
cpio archive of that directory's contents that can be used as an initramfs.

See also: Documentation/early-userspace/README


2) Contents of the initramfs

When an intramfs archive is found during boot, the kernel will try to start
/init. This is the only file the initramfs actually _needs_. Everything else
is optional, depending on what you want the initramfs to do.

Before starting /init the kernel will also try to open /dev/console to provide
fd0,1,2 to /init. If /dev/console does not exist /init will still be run, but
will need to be extra careful about its startup or create and open /dev/console
itself.

Typically you would want /init to be a shellscript which mounts the root and
other filesystems, loads modules and then starts the regular init via run_init;
all of which can be done with programs included in the klibc package.

However it is also possible to run an installation program or a firewall from
an initramfs and never mount any disk filesystems.

The binaries in your initramfs can be linked to any libc and both shared and
static linking will work fine. If you seek limited functionality for your
initramfs and want it to be integrated in the kernel binary, you will probably
prefer a special libc like klibc which will work well and keep the result small.

For external initramfs files you can choose any libc. Klibc will give you a
small initramfs, but requires extra effort to compile and link programs against
it. The usual glibc will also work and provide all the features glibc has and
allow you to use standard applications without special recompiling or linking,
but glibc is bigger and thus needs more memory.

To compile an app to use klibc you can use klcc as your compiler. Klcc is a
perl wrapper around gcc which will set up include and library search paths so
that your app is linked against klibc.

The only size constraint is that the initramfs archive must be less than half
the size of the machine's RAM, since the archive will be deleted _after_ it is
unpacked.


3) Booting

An Initramfs archive can either be built into the kernel, passed by the
bootloader or both; however the kernel must have CONFIG_BLK_DEV_INITRD if you
want to pass an initramfs archive via the bootloader.

During boot the kernel unpacks the built in archive first, then the one passed
by the bootloader (if either of them exist of course). Initramfs archives are
unpacked directly into the rootfs, a ramfs which is usually immediately
overmounted by the user-visible root.

If an initramfs is found the kernel does not mount a root filesystem and starts
/init in the initramfs.
/init is responsible for mounting the root and exec'ing the normal init.
Once /init has performed all necessary set-up tasks and initramfs is no longer
needed, the proper way to clean up is to use run_init (or do what it does
manually). Run_init deletes all the files on the initramfs to free up the space
and chroots into the "real" root.

DO NOT use pivot_root and try to unmount the initramfs; since initramfs is
rootfs you're pulling the rug out from under the kernel by doing so and a
kernel panic _will_ happen as a result.


4) Testing

There is no need to reboot repeatedly to test your initramfs; you can test by
building the initramfs into a UML kernel. There is no need to rebuild any
programs (or klibc) to do so.

VMWare or bochs should work too.


More information about the klibc mailing list