mkinitrd

From vegard.wiki
Revision as of 06:27, 15 December 2019 by Vegard (talk | contribs) (add ftrace example)
Jump to navigation Jump to search

A handy way to run a program as init without a filesystem:

#! /bin/bash

set -e
set -u
set -x

rm -rf initrd/
mkdir initrd/
g++ -static [...] -o initrd/init main.cc

(cd initrd/ && (find | cpio -o -H newc)) \
        | gzip -c \
        > initrd.gz

Mounting filesystems

Sometimes it can be useful to have /proc, /sys, /dev, etc. around:

#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <errno.h>
#include <error.h>
#include <unistd.h>

static void mkdirp(const char *name)
{
        if (mkdir(name, 0777) == -1 && errno != EEXIST)
                error(EXIT_FAILURE, errno, "mkdir()");
}

int main(int argc, char *argv[])
{
        pid_t self = getpid();
        if (getpid() == -1)
                error(EXIT_FAILURE, errno, "getpid()");

        if (self == 1) {
                // We're init! Do some basic setup.

                mkdirp("/proc");
                if (mount("nodev", "/proc", "proc", 0, "") == -1)
                        error(EXIT_FAILURE, errno, "mount(/proc)");

                mkdirp("/sys");
                if (mount("nodev", "/sys", "sysfs", 0, "") == -1)
                        error(EXIT_FAILURE, errno, "mount(/sys)");

                mkdirp("/dev");
                if (mount("nodev", "/dev", "devtmpfs", 0, "") == -1)
                        error(EXIT_FAILURE, errno, "mount(/dev)");

                if (mount("nodev", "/sys/kernel/tracing", "tracefs", 0, "") == -1)
                        error(EXIT_FAILURE, errno, "mount(/sys/kernel/tracing)");
        }

        ...
}

ftrace

To trace something with ftrace (and dump the trace), use something like:

#define tracing_set(name, value) \
        { \
                FILE *fp = fopen("/sys/kernel/tracing/" #name, "w"); \
                if (!fp) \
                        error(EXIT_FAILURE, errno, "fopen(" #name ")"); \
                fprintf(fp, "%s\n", #value); \
                fclose(fp); \
        }

int main(int argc, char *argv[])
{
        // ...

        tracing_set(current_tracer, function_graph);
        tracing_set(tracing_on, 1);

        // insert traced code here

        tracing_set(tracing_on, 0);

        // dump trace
        {
                FILE *fp = fopen("/sys/kernel/tracing/trace", "r");
                while (fp && !feof(fp)) {
                        char buf[1024];
                        size_t len = fread(buf, 1, sizeof buf, fp);
                        fwrite(buf, 1, len, stdout);
                }
                fclose(fp);
        }
}