c - 想要构建只有一个内核和一个二进制文件的裸 Linux 系统

标签 c linux linux-kernel kernel hardware

我想构建一个只运行一个二进制程序的专用 Linux 系统。该程序通过 OpenGL 驱动程序控制屏幕并显示图案。还需要键盘输入来配置模式。由于运行这个程序将是机器的唯一目的,我不需要任何 GUI、网络等。此外,我可能不需要在内核中进行任何进程调度,因为只会运行一个进程。

是否可以用我自己的二进制文件替换/sbin/init 来实现这一点?内核加载后,它会立即执行我自己的二进制文件,并且会在机器开启的整个过程中运行。基本上,我想模拟微 Controller 的工作方式,但好处是能够将 x86 CPU 与不同的硬件设备和驱动程序一起使用。

最佳答案

最小的 init hello world 程序分步

enter image description here

编译一个没有任何以无限循环结束的依赖项的 hello world。 init.S:

.global _start
_start:
    mov $1, %rax
    mov $1, %rdi
    mov $message, %rsi
    mov $message_len, %rdx
    syscall
    jmp .
    message: .ascii "FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n"
    .equ message_len, . - message

我们不能使用sys_exit,否则内核崩溃。

然后:

mkdir d
as --64 -o init.o init.S
ld -o init d/init.o
cd d
find . | cpio -o -H newc | gzip > ../rootfs.cpio.gz
ROOTFS_PATH="$(pwd)/../rootfs.cpio.gz"

这会在 /init 中创建一个包含我们的 hello world 的文件系统,这是内核将运行的第一个用户态程序。我们还可以向 d/ 添加更多文件,并且在内核运行时可以从 /init 程序访问它们。

然后cd进入Linux内核树,像往常一样构建,并在QEMU中运行:

git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
git checkout v4.9
make mrproper
make defconfig
make -j"$(nproc)"
qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd "$ROOTFS_PATH"

你应该看到一行:

FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR

在模拟器屏幕上!请注意,这不是最后一行,因此您必须往上看一点。

如果静态链接它们,您也可以使用 C 程序:

#include <stdio.h>
#include <unistd.h>

int main() {
    printf("FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n");
    sleep(0xFFFFFFFF);
    return 0;
}

与:

gcc -static init.c -o init

您可以在带有 USB 的真实硬件上运行 /dev/sdX 并且:

make isoimage FDINITRD="$ROOTFS_PATH"
sudo dd if=arch/x86/boot/image.iso of=/dev/sdX

关于这个主题的重要资源:http://landley.net/writing/rootfs-howto.html它还解释了如何使用 gen_initramfs_list.sh,这是一个来自 Linux 内核源代码树的脚本,用于帮助自动化该过程。

下一步:设置 BusyBox,以便您可以通过 shell 与系统交互。 Buildroot is a great way to do it .

在 Ubuntu 16.10、QEMU 2.6.1 上测试。

关于c - 想要构建只有一个内核和一个二进制文件的裸 Linux 系统,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24583614/

相关文章:

c - 你什么时候使用mmap

c - 无内存重复的可内联常量 C 数组

linux - Skype 无法打开 : "We can' t open Skype. 您已经在此计算机上登录...”

linux-kernel - sysfs 属性可以在 Linux 设备驱动程序中采用非数值吗?

c - 使用 C 中指向指针的指针删除链表中的节点

c - NetBeans 中的调试错误

linux - 计算每个文件夹的平均文件数

linux - 修改用户的 UID 不更新

Linux 中断不由包装器驱动程序处理

c - 如何知道中断是否被禁用?