简体   繁体   English

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

[英]Want to build bare Linux system that has only a kernel and one binary

I want to build a dedicated Linux system that only ever runs one binary program. 我想构建一个只运行一个二进制程序的专用Linux系统。 This program takes control of the screen via the OpenGL driver and displays patterns. 该程序通过OpenGL驱动程序控制屏幕并显示模式。 There needs to be keyboard input as well to configure the patterns. 还需要键盘输入来配置模式。 Since running this one program will be the sole purpose of the machine, I don't need any GUI, networking, etc. Also, I probably don't need any process scheduling in the kernel since only one process will ever run. 由于运行这一个程序将是机器的唯一目的,我不需要任何GUI,网络等。此外,我可能不需要在内核中进行任何进程调度,因为只有一个进程将运行。

Is it possible to replace /sbin/init with my own binary to achieve this? 有可能用我自己的二进制文件替换/ sbin / init来实现这个目的吗? After the kernel loads, it would then immediately execute my own binary, and that would run the entire time the machine was on. 在内核加载之后,它会立即执行我自己的二进制文件,这将在机器运行的整个时间内运行。 Basically, I want to emulate the way a microcontroller works, but with the benefit of being able to use an x86 CPU with different hardware devices and drivers. 基本上,我想模仿微控制器的工作方式,但能够使用具有不同硬件设备和驱动程序的x86 CPU。

It might be possible to replace /sbin/init by your program, but you should be aware that process 1 has some specific duties. 可能有可能用你的程序替换/sbin/init ,但你应该知道进程1有一些特定的职责。 So I think it is not advisable to replace it. 所以我认为不宜更换它。

Remember that a Linux kernel can also start some processes magically, outside of the usual fork from a process inherited by the init process. 请记住,Linux内核也可以在init进程继承的进程的通常fork之外神奇地启动某些进程。 I'm thinking of things like /sbin/modprobe or /sbin/hotplug etc. 我在/sbin/modprobe/sbin/hotplug等。

Also, udev (or systemd ) have some special roles. 此外, udev (或systemd )也有一些特殊的角色。 On some systems, fan control was related to such things (I really forgot the details). 在某些系统上,风扇控制与这些事情有关(我真的忘记了细节)。 If unlucky, you could burn your hardware if fan is not working well (but AFAIK this is no more true on recent hardware). 如果运气不好,如果风扇运行不正常,你可以烧掉你的硬件(但AFAIK在最近的硬件上并不是这样)。

By seeking with string the vmlinux in a recent 3.15.3 kernel, I find that it knows about: 通过在最近的3.15.3内核中使用string查找vmlinux ,我发现它知道:

  • /bin/init /斌/ INIT
  • /bin/sh / bin / sh的
  • /sbin/request-key / sbin目录/请求密钥
  • /sbin/tomoyo-init / sbin目录/知世-INIT
  • /sbin/modprobe / sbin目录/ modprobe的
  • /sbin/poweroff / sbin目录/关机
  • /sbin/hotplug / sbin目录/热插拔

I would recommend instead keeping some existing init program, and configure it to run only your program. 我建议改为保留一些现有的init程序,并将其配置为仅运行程序。

Minimal init hello world program step-by-step 最小的init hello world程序一步一步

在此输入图像描述

Compile a hello world without any dependencies that ends in an infinite loop. 编译一个没有任何以无限循环结束的依赖关系的hello世界。 init.S : 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

We cannot use sys_exit , or else the kernel panics. 我们不能使用sys_exit ,否则内核会发生sys_exit

Then: 然后:

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"

This creates a filesystem with our hello world at /init , which is the first userland program that the kernel will run. 这将在/init创建一个带有hello world的文件系统,这是内核将运行的第一个userland程序。 We could also have added more files to d/ and they would be accessible from the /init program when the kernel runs. 我们也可以在d/添加更多文件,并且在内核运行时可以从/init程序访问它们。

Then cd into the Linux kernel tree, build is as usual, and run it in QEMU: 然后, 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"

And you should see a line: 你应该看到一条线:

FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR

on the emulator screen! 在模拟器屏幕上! Note that it is not the last line, so you have to look a bit further up. 请注意,它不是最后一行,因此您需要进一步了解。

You can also use C programs if you link them statically: 如果您静态链接它们,也可以使用C程序:

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

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

with: 有:

gcc -static init.c -o init

You can run on real hardware with a USB on /dev/sdX and: 您可以在/dev/sdX上使用USB在真实硬件上运行,并且:

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

Great source on this subject: http://landley.net/writing/rootfs-howto.html It also explains how to use gen_initramfs_list.sh , which is a script from the Linux kernel source tree to help automate the process. 关于这个主题的很好的来源: httpgen_initramfs_list.sh它还解释了如何使用gen_initramfs_list.sh ,它是来自Linux内核源代码树的脚本,以帮助自动化该过程。

Next step: setup BusyBox so you can interact with the system through a shell. 下一步:设置BusyBox,以便您可以通过shell与系统进行交互。 Buildroot is a great way to do it . Buildroot是一个很好的方法

Tested on Ubuntu 16.10, QEMU 2.6.1. 在Ubuntu 16.10,QEMU 2.6.1上测试。

您可以将程序放到initrd ,然后从initrd的init运行它。

Simply use a boot paramter eg) init=/bin/bash 只需使用启动参数,例如init=/bin/bash

init is the process 1, used by kernel to start user space, which as a few specific duties like reaping children periodical to clean out zombies. init是进程1,由内核用来启动用户空间,作为一些特定的职责,比如收获儿童期刊来清理僵尸。 Sounds like you don't even need that. 听起来你甚至都不需要那样。

Linux Boot parameters you should know 您应该知道的Linux Boot参数

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM