mkinitrd: Difference between revisions

From vegard.wiki
Jump to navigation Jump to search
Content added Content deleted
(new page)
 
(add ftrace example)
(One intermediate revision by the same user not shown)
Line 15: Line 15:
| gzip -c \
| gzip -c \
> initrd.gz
> initrd.gz
</source>

=== Mounting filesystems ===

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

<source lang="C">
#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)");
}

...
}
</source>

=== ftrace ===

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

<source lang="C">
#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);
}
}
</source>
</source>



Revision as of 06:27, 15 December 2019

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);
        }
}