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

时间:2014-07-05 06:18:59

标签: c linux linux-kernel kernel hardware

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

是否可以用我自己的二进制文件替换/ sbin / init来实现这个目的?在内核加载之后,它会立即执行我自己的二进制文件,这将在机器运行的整个时间内运行。基本上,我想模仿微控制器的工作方式,但是能够使用具有不同硬件设备和驱动程序的x86 CPU。

4 个答案:

答案 0 :(得分:5)

您的程序可能会替换/sbin/init,但您应该知道进程1有一些特定的职责。所以我认为不宜替换它。

请记住,Linux内核也可以通过init进程继承的进程在通常的fork之外神奇地启动某些进程。我在想/sbin/modprobe/sbin/hotplug等等。

此外,udev(或systemd)也有一些特殊的角色。在某些系统上,风扇控制与这些事情有关(我真的忘记了细节)。如果运气不好,如果风扇运行不正常,您可能会烧坏硬件(但AFAIK在最近的硬件上并不是这样)。

通过在最近的3.15.3内核中string寻找vmlinux,我发现它知道:

  • / bin中/初始化
  • / bin / sh的
  • / sbin目录/请求密钥
  • / sbin目录/智代-INIT
  • / sbin目录/ modprobe的
  • / sbin目录/关机
  • / sbin目录/热插拔

我建议改为保留一些现有的init程序,并将其配置为仅运行程序。

答案 1 :(得分:5)

最小的初始化hello world程序

enter image description here

编译一个没有任何以无限循环结尾的依赖关系的hello世界。 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的文件系统,这是内核将运行的第一个userland程序。我们还可以向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

您可以使用/dev/sdX上的USB和

在真实硬件上运行
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上测试。

答案 2 :(得分:2)

您可以将程序设置为initrd,然后从initrd的init中运行它。

答案 3 :(得分:1)

只需使用引导参数,例如{} {}}

init是进程1,由内核用来启动用户空间,作为一些特定的职责,比如收获儿童期刊来清理僵尸。听起来你甚至都不需要它。

Linux Boot parameters you should know