我如何创建自己的“自定义”Linux 发行版,该发行版将只运行一个程序,与XBMC本图。
答案1
最小初始化 hello world 程序一步一步
编译一个没有任何依赖项的 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
我们不能使用 exit 系统调用,否则内核会崩溃,从 init 优雅退出的唯一方法是reboot
使用系统调用关闭机器电源。
然后:
mkdir d
as --64 -o init.o init.S # assemble
ld -o d/init init.o # link
cd d
find . | cpio -o -H newc | gzip > ../rootfs.cpio.gz
ROOTFS_PATH="$(pwd)/../rootfs.cpio.gz"
这将创建一个带有 hello world 的文件系统/init
,这是内核将运行的第一个用户态程序。我们还可以添加更多文件,并且当内核运行时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
动态链接需要设置动态链接器可执行文件,其中最常见的是 C 标准库(如 glibc)的一部分。
您可以在具有 USB 的真实硬件上运行,/dev/sdX
并且:
make isoimage FDINITRD="$ROOTFS_PATH"
sudo dd if=arch/x86/boot/image.iso of=/dev/sdX
关于这个主题的重要资料来源:技术提示:如何使用 initramfs |兰德利网它还解释了如何使用gen_initramfs_list.sh
,它是 Linux 内核源代码树中的一个脚本,可帮助自动化该过程。
在 Ubuntu 16.10、QEMU 2.6.1 上测试。
下一步
您要做的下一件事是设置忙碌盒, 也可以看看:最小的 Linux 实现是什么?
BusyBox 实现了基本的 POSIX-y CLI 实用程序,包括 POSIX-y shell,您可以通过它更轻松地以交互方式试验系统。
就我个人而言,此时我更愿意依赖构建根,这是一组令人惊奇的脚本,可以自动从源代码构建所有内容并创建根文件系统。
我已经为此上传了一个非常详细且自动化的帮助程序:https://github.com/cirosantilli/linux-kernel-module-cheat
答案2
我不会开始搞乱LFS,那是一条通往一些黑暗树林的花园小路。
从您对初始安装有很多控制权的发行版开始,例如 Arch,或无头版本,例如 Ubuntu 服务器。这样做的目的并不是为了节省空间,而是为了限制 init 配置的复杂性;从无头发行版开始,如果您要运行的应用程序需要 GUI,您可以添加所需的内容,而不必最终由 init 启动 GUI 登录(也称为显示管理器或 DM)和完整的桌面与之相配的环境。
然后您想了解如何配置初始化系统为了您的目的——请注意,您不能没有 init,它可能是实现您的目标的最佳方法。现在大多数 Linux 发行版上使用的 init 系统是系统。
这里的要点是尽量减少 init 在启动时所做的事情,这就是您如何创建一个系统,该系统将运行最少量的软件来支持您想要关注的应用程序 - 这本质上就是服务器的设置方式,顺便说一句,所以这是一项常见任务(请注意,您实际上不能让“只有一个”用户态进程运行,至少没有用处)。
如果您想要运行的应用程序是一个 GUI 程序(这是一个很好的例子,说明了为什么您不能只运行一个应用程序,因为 GUI 应用程序需要 X 服务器),您可以拥有一个~/.xinitrc
如下所示的应用程序;
#!/bin/sh
myprogram
然后startx
,您的程序将是唯一正在运行的程序,并且无法更改桌面或启动其他任何程序,部分原因是没有窗口管理器或桌面环境(因此,也不会出现窗口框架或标题栏)。
答案3
如果您对编程有一点了解并且想从头开始创建它,您可以使用 LFS ie Linux from Scratchhttp://www.linuxfromscratch.org/
如果你想定制 ubutnu,你可以使用 ubunt-builder,如果你想在 rpm 基础上使用,你可以使用 SUSE-Studio,Suse studio 将允许你定制 suse linux
干杯
答案4
你需要问的是你的“一个项目”需要什么,你有什么资源。
如果它需要多种库和支持二进制文件,您可能最好使用“常规”Linux 发行版(Debian 或类似版本),并且稍微扰乱启动过程。
如果它需要更窄的支持内容选择,但仍然需要诸如网络或使用不同内核模块或用户空间支持位的各种硬件的支持之类的内容,并且您不希望常规发行版的磁盘空间开销,那么我建议查看嵌入式发行版(buildroot 或类似)或者可能是从头开始的 Linux 方法(尽管这可能是一个令人头痛的维护问题)
如果您只需要非模块化内核可以提供的功能而无需其他任何东西,那么直接在内核上运行您自己的二进制文件可能会起作用并且是最轻量的解决方案。