如何创建一个仅运行一个程序而不运行其他任何程序的定制Linux发行版?


12

我该如何创建自己的“自定义” Linux发行版,该发行版仅运行一个程序,几乎与XBMCbuntu完全相同


欢迎参加U&L,请参加引导性游览,并抽出时间学习如何提出问题,您想做什么?因为应用程序的定义很模糊,一点也不意味着什么,因为我的建议是使用,busybox但这可能不是您想要的。因此,请花一些必要的时间来表达您的需求,我们可能会为您提供帮助。请随时编辑您的问题以在其中添加任何相关元素。
2014年

1
对我来说似乎很清楚……
goldilocks

@ TAFKA'goldilocks'不好,因为我敢打赌,尽管似乎只有一个应用程序在运行,但并非只有一个应用程序在运行,但是您仍然可以访问XBMCubuntu上的终端或类似内容。我只使用内核和busybox从头开始制作了一个小型发行版,在这种情况下,即使内核启动了某些服务,您也可以说busybox是您唯一的应用程序。
2014年

@Kiwi那是一个很好的答案(比LFS好)。请记住:1)这个问题可能对通用目的相同的其他人有用,因此答案很不错; 2)虽然这里有一系列可能的解决方案,例如TIMTOWTDI,但有些可能是我比其他人更适合某些更具体的目标,我敢肯定它们都会奏效,并且决定解决方案的重要方面将是主观的(例如,由于OP的先验知识和经验,而不是任务的客观性质) 。
goldilocks 2014年

Answers:


6

我不会把LFS弄得一团糟,那是一条通往一些黑暗树林的花园小路。

从发行版开始,在发行版中,您可以对初始安装(如Arch)或无头版本(如Ubuntu服务器)进行大量控制。这样做的目的不是要节省空间而是要限制init配置的复杂性。从无头发行版开始,如果要运行的应用程序需要GUI,则可以添加所需的功能,而不必以init启动的GUI登录(也称为显示管理器或DM)和一个功能齐全的桌面为结尾与之相配的环境。

然后,您想学习如何根据自己的目的配置init系统 -请注意,没有init就无法做,这可能是实现目标的最佳方法。在Linux上常用的init有三种变体(但还有其他一些变体):

  • Debian在经典的Unix SysV样式init上使用了变体。从jessie发行版开始,Debian也已切换到systemdhttps://wiki.debian.org/systemd

  • Ubuntu和衍生产品使用新贵

  • Fedora,Arch和派生工具使用systemd

如果您还不了解其中任何一个,那么它们中的任何一个都不比其他任何一个更难使用。如果您选择后两者之一,则它们提供了一些与SysV向后兼容的机制,但是您不必担心,这并不简单。1个

这里的重点是最小化启动时的初始化,这就是您如何创建一个系统,该系统将运行最少数量的软件来支持您要关注的应用程序-本质上就是服务器的设置方式,顺便说一句,这是一项常见的任务(请注意,您实际上无法运行“仅一个”用户域进程,至少没有用处)。

如果您要运行的应用程序是GUI程序(这是一个很好的示例,说明为什么您不能只运行一个应用程序,因为GUI应用程序需要X服务器),您可以拥有一个~/.xinitrc类似于以下内容的应用程序;

#!/bin/sh

myprogram

然后startx,您的程序将是唯一运行的程序,并且将无法更改桌面或启动其他任何操作,部分原因是没有窗口管理器或桌面环境(因此,也将没有窗口框架或标题栏)。

1.稍微弄清楚这一点:在研究此问题时,您可能会从以前熟悉SysV的人那里发现对systemd和新贵的一些困扰,例如,他们太复杂了。但是,从客观上讲,它们并没有比SysV复杂(事实上,IMO systemd使用起来更简单),但是可以说,大多数狗更喜欢它们的老花样。现在这两种系统已经使用了一段时间,这种困扰开始消失了。


1
您不能没有,init但可以确定,upstart, systemd,或者可以说sysv. initinit内核挂载时调用的一个可执行文件,initramfs.在大多数情况下,这三个文件甚至都没有,init但实际上它们通常是execinit,哪个人编入的busybox.
mikeserv

@mikeserv绝对(我确实明确提到,这些不是唯一的三个选择)。另请注意,我故意排除在外,busybox因为在单独的答案中应单独对待,而不是我本人。
goldilocks 2014年

您提供的服务多么亲切!但绝不该死。
mikeserv 2014年

知道这种方法是否实际上可行,将很有趣。有人尝试过吗?
Faheem Mitha 2014年

@FaheemMitha如果您的意思是我在这里建议的内容(自定义init配置),那么它的确可以,这就是系统已经工作的方式,您只是在制作精简和简化的版本(我确定这是XBMCbutu是什么)。如果您的意思是,用一些更专业的可执行文件ala busybox替换init,除非您必须这样做,否则可能比它值得的麻烦更多。busybox的主要目的是在小型嵌入式环境中使用(例如,只有几个MB RAM)。
goldilocks 2014年

18

最小的init hello world程序逐步

在此处输入图片说明

编译一个没有任何依赖以无限循环结尾的依赖的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

我们不能使用退出系统调用,否则将无法使用内核崩溃。

然后:

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"

这会创建一个文件系统,其问候世界位于/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 | landley.net它还说明了如何使用gen_initramfs_list.sh,它是Linux内核源代码树中的一个脚本,用于帮助自动完成该过程。

已在Ubuntu 16.10,QEMU 2.6.1上测试。

下一步

接下来要做的是设置BusyBox

BusyBox实现了基本的POSIX-y CLI实用程序,包括POSIX-y shell,可让您更轻松地进行交互式系统实验。

就个人而言,在这一点上,我更喜欢仅依靠Buildroot,这是一组了不起的脚本,可自动从源代码构建所有内容并制作根文件系统。

我在以下位置上传了一个非常详细且自动化的帮助程序:https : //github.com/cirosantilli/linux-kernel-module-cheat


4
这可能是最被低估的答案:D。太棒了!
msouth


1

如果您只需要一点编程,并且想从头开始创建它,则可以使用LFS,即Scratch的Linux http://www.linuxfromscratch.org/

如果要自定义ubutnu,则可以使用ubunt-builder;如果要基于rpm,则可以使用SUsE-Studio,Suse studio将允许您自定义suse linux

干杯


1

它更多地涉及您的“一个程序”的要求。

您仍然可以通过构建LFS(又称“ Linux From Scratch ”)来了解如何将它们组合在一起。然后,您将添加程序所需的内容或进行完整分发,因为在LFS上构建沉重的子系统(如GnomeKDE)可能是真正的难题。

当然,起初向后走可能会比较容易,但是从完整的发行版中删除内容可能很麻烦:在VM中执行此操作,并在每个步骤中复制此VM。

(我的2美分)

编辑

正如SecurityBeast指出的那样,您可以从构建完整的分发工具开始,而不是像CentOSUbuntu那样从完整的分发开始:


1

您需要问的是您的“一个程序”需要什么以及您拥有什么资源。

如果它需要多种选择的库和支持二进制文件,则最好使用“常规” Linux发行版(Debian或类似版本),并稍微弄乱引导过程。

如果它需要选择的支持内容比较狭窄,但仍然需要网络或使用不同的内核模块或用户级支持位来支持各种硬件的内容,并且您不希望常规发行版的磁盘空间开销,那么我建议您看一下嵌入式发行版(buildroot或类似版本),或者是从头开始使用linux的方法(尽管这可能会给维护带来麻烦)

如果您只需要一个非模块化内核可以提供的功能,而无需其他任何东西,那么直接在内核上运行自己的二进制文件可能会起作用,并且是最简单的解决方案。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.