我想build立一个只运行一个二进制程序的专用Linux系统。 该程序通过OpenGL驱动程序控制屏幕并显示模式。 还需要键盘input以configuration模式。 由于运行这个程序将是机器的唯一目的,我不需要任何GUI,networking等。另外,我可能不需要在内核中进行任何进程调度,因为只有一个进程会运行。
是否有可能用我自己的二进制代替/ sbin / init来达到这个目的? 内核加载后,它会立即执行我自己的二进制文件,这将运行整个机器的时间。 基本上,我想模仿微控制器的工作方式,但是能够使用具有不同硬件设备和驱动程序的x86 CPU。
你可以用你的程序替换/sbin/init
,但你应该知道进程1有一些特定的职责。 所以我认为不可取代它。
请记住,Linux内核也可以神奇地启动一些进程,而不是从init进程继承的进程的通常fork
之外。 我正在考虑像/sbin/modprobe
或/sbin/hotplug
等
此外, udev
(或systemd
)还有一些特殊的角色。 在一些系统上,风扇控制与这些事情有关(我真的忘了细节)。 如果不幸的话,如果风扇运行不正常,可能会烧毁硬件(但是在最近的硬件上,AFAIK并不是这样)。
通过在最近的3.15.3内核中寻找string
vmlinux
,我发现它知道:
我会建议,而不是保留一些现有的init程序,并配置它只运行你的程序。
最小的初始化你好世界程序一步一步
编译一个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
您可以使用/dev/sdX
上的USB在真实硬件上运行,并且:
make isoimage FDINITRD="$ROOTFS_PATH" sudo dd if=arch/x86/boot/image.iso of=/dev/sdX
关于这个主题的很好的源代码: http : gen_initramfs_list.sh
它还解释了如何使用gen_initramfs_list.sh
,它是Linux内核源代码树中的一个脚本来帮助自动化进程。
下一步:安装BusyBox,以便您可以与系统进行交互: https : //github.com/cirosantilli/runlinux
测试Ubuntu 16.10,QEMU 2.6.1。
你可以把你的程序放到initrd中 ,然后从initrd的init中运行它。
只需使用一个启动参数例如) init=/bin/bash
init是进程1,由内核用来启动用户空间,这就像收获儿童周期性清理僵尸一样具体的任务。 听起来你甚至不需要这个。
Linux引导参数你应该知道