Linuxを完全に起動するために必要な最低限のルートファイルシステムアプリケーションは何ですか?


16

ユーザー空間アプリケーションに関する質問ですが、私に聞いてください!

Linuxの機能ディストリビューションを起動するには、いわば3つの「アプリケーション」が必要です。

  1. ブートローダー-通常は組み込み用のU-Bootですが、ハード要件ではありません。

  2. カーネル-それは非常に簡単です。

  3. ルートファイルシステム-それなしではシェルを起動できません。カーネルがブートするファイルシステムと、initフォームと呼ばれる場所が含まれます。

私の質問は#3に関してです。誰かが非常に最小限のrootfsを構築したい場合(この質問ではGUIなし、シェルのみ)、シェルを起動するにはどのファイル/プログラムが必要ですか?


最小限を定義します。superuser.com/a/991733/128124で説明されているように、他の何もない単一の実行可能ファイルのみを使用できます。すべての終了またはパニックができないため、無限ループまたは長いスリープが必要です。同様の質問:unix.stackexchange.com/questions/17122/...
チロSantilli新疆改造中心法轮功六四事件

回答:


31

それは、デバイスでどのサービスを使いたいかに完全に依存します。

プログラム

Linuxを直接シェルにブートさせることができます。本番環境ではあまり便利ではありません(シェルをそこに配置したいだけです)が、インタラクティブブートローダーがある場合の介入メカニズムとしては便利ですinit=/bin/sh。カーネルコマンドラインに渡します。すべてのLinuxシステム(およびすべてのUNIXシステム)には、Bourne / POSIXスタイルのシェルがあり/bin/shます。

シェルユーティリティのセットが必要です。BusyBoxは非常に一般的な選択肢です。それは、(ファイルとテキスト操作のためのシェルとの共通のユーティリティが含まれているcpgrepセットアップ(ネットワーキング、...、) pingifconfig、...)、プロセス操作を(psnice(、...)、および様々な他のシステムツールfdiskmountsyslogd、...)。BusyBoxは非常に柔軟に構成できます。コンパイル時に必要なツールや個々の機能を選択して、アプリケーションに適したサイズ/機能の妥協点を得ることができます。別にsh、あなたが本当にあるなしでは何もできないという最低限mountumountそしてhalt、また、持っていないように非定型だろうcatcpmvrmmkdirrmdirpssyncといくつかのより多くの。BusyBoxはbusybox、と呼ばれる単一のバイナリとしてインストールされ、各ユーティリティのシンボリックリンクが含まれます。

通常のUNIXシステムでの最初のプロセスはと呼ばれinitます。その仕事は、他のサービスを開始することです。BusyBoxには初期化システムが含まれています。initバイナリ(通常/sbinはにあります)に加えて、/etc/inittab起動するサービスを示す構成ファイル(通常は呼ばれます-いくつかの最新のinitの置換はそのファイルを廃止しますが、小さな組み込みシステムでは見つかりません)が必要です。そしていつ。BusyBoxの/etc/inittab場合、オプションです。見つからない場合は、コンソールにルートシェル/etc/init.d/rcSが表示され、ブート時にスクリプト(デフォルトの場所)が実行されます。

必要なのはこれだけです。もちろん、デバイスに何か便利なことをさせるプログラムです。たとえば、OpenWrtバリアントを実行している自宅のルーターでは、プログラムはBusyBox nvram(NVRAMの設定を読み取って変更するため)とネットワークユーティリティのみです。

すべての実行可能ファイルが静的にリンクされていない限り、ダイナミックローダー(ld.so、libcの選択とプロセッサアーキテクチャに応じて異なる名前で呼び出される場合があります)およびすべてのダイナミックライブラリ/lib/lib*.so、おそらくこれらの一部/usr/lib)が必要ですこれらの実行可能ファイル。

ディレクトリ構造

ファイルシステム階層標準は、 Linuxシステムの共通のディレクトリ構造について説明します。デスクトップおよびサーバーへのインストールを対象としています。組み込みシステムでは、その多くを省略できます。これが典型的な最小値です。

  • /bin:実行可能プログラム(/usr/bin代わりに一部のプログラムが含まれる場合があります)。
  • /dev:デバイスノード(以下を参照)
  • /etc:構成ファイル
  • /lib:ダイナミックローダーを含む共有ライブラリ(すべての実行可能ファイルが静的にリンクされていない場合)
  • /procprocファイルシステムのマウントポイント
  • /sbin:実行可能プログラム。との違い/bin/sbin、システム管理者のみに役立つプログラム向けですが、この区別は組み込みデバイスでは意味がありません。へ/sbinのシンボリックリンクを作成でき/binます。
  • /mnt:メンテナンス中に読み取り専用ルートファイルシステムをスクラッチマウントポイントとして使用すると便利です
  • /syssysfsファイルシステムのマウントポイント
  • /tmp:一時ファイルの場所(多くの場合、tmpfsマウント)
  • /usr:サブディレクトリが含まれているbinlibsbin/usrルートファイルシステム上にない余分なファイルのために存在します。持っていない場合は/usr、ルートディレクトリへのシンボリックリンクを作成できます。

デバイスファイル

最小限の典型的なエントリは次の/devとおりです。

  • console
  • full (それへの書き込みは、常に「デバイスにスペースが残っていません」と報告します)
  • log(プログラムがログエントリの送信に使用するソケット)、syslogdデーモン(BusyBoxなど)からの読み取りがある場合
  • null (常に空のファイルのように動作します)
  • ptmx擬似端末(つまり、コンソール以外の端末)を使用する場合は、ptsディレクトリ。たとえば、デバイスがネットワーク接続されており、telnetまたはsshで接続する場合
  • random (ランダムなバイトを返し、ブロッキングのリスクがあります)
  • tty (常にプログラムの端末を指定します)
  • urandom (ランダムなバイトを返し、ブロックすることはありませんが、新しく起動したデバイスではランダムではない場合があります)
  • zero (nullバイトの無限シーケンスを含む)

それを超えると、ハードウェアのエントリが必要になります(ネットワークインターフェイスを除き、これらはエントリを取得しません/dev):シリアルポート、ストレージなど。

組み込みデバイスの場合、通常はルートファイルシステムにデバイスエントリを直接作成します。ハイエンドシステムには、エントリMAKEDEVを作成するために呼び出される/devスクリプトがありますが、組み込みシステムでは、多くの場合、スクリプトはイメージにバンドルされていません。一部のハードウェアをホットプラグできる場合(たとえば、デバイスにUSBホストポートがある場合)、udev/devで管理する必要があります(ルートファイルシステムに最小限のセットがある場合があります)。

起動時のアクション

ルートファイルシステムを超えて、通常の操作のためにさらにいくつかをマウントする必要があります:

  • procfs on /proc(ほとんど不可欠)
  • sysfsオン/sys(ほとんど不可欠)
  • tmpfsファイルシステムオン/tmp(プログラムがフラッシュまたは読み取り専用のルートファイルシステムではなく、RAMにある一時ファイルを作成できるようにします)
  • tmpfs、devfs、またはdevtmpfsがオンの/dev場合(上記の「デバイスファイル」のudevを参照)
  • /dev/pts[擬似端末を使用する場合は、devpts on (pts上記の備考を参照)

/etc/fstabファイルを作成してを呼び出すmount -aか、mount手動で実行できます。

ログを書き込む場所がある場合は、syslogデーモンを起動します(プログラムがそれを処理しないklogd場合はカーネルログも起動しますsyslogd)。

この後、デバイスはアプリケーション固有のサービスを開始する準備が整います。

ルートファイルシステムの作り方

これは長くて多様な話ですので、ここでやるのはいくつかの指針を与えることです。

ルートファイルシステムは、RAM(ROMまたはフラッシュの(通常は圧縮された)イメージからロードされる)、またはディスクベースのファイルシステム(ROMまたはフラッシュに格納される)に保持されるか、ネットワークからロードされる(多くの場合TFTPを介して) 。ルートファイルシステムがRAMにある場合は、initramfsにします。これは、ブート時にコンテンツが作成されるRAMファイルシステムです。

組み込みシステムのルートイメージを組み立てるための多くのフレームワークが存在します。BusyBox FAQにはいくつかのポインタがあります。Buildrootは人気のあるもので、LinuxカーネルやBusyBoxに似たセットアップでルートイメージ全体を構築できます。OpenEmbeddedもそのようなフレームワークです。

ウィキペディアには、一般的な組み込みLinuxディストリビューションの(不完全な)リストがあります。近くにあるかもしれない組み込みLinuxの例は、ネットワーク機器用のオペレーティングシステムのOpenWrtファミリーです(ティンカーのホームルーターで人気があります)。経験から学びたい場合は、ScratchからLinuxを試すことができますが、組み込みデバイス向けではなく、趣味の人向けのデスクトップシステム向けです。

Linux vs Linuxカーネルに関する注意

Linuxカーネルに組み込まれている唯一の動作は、ブート時に起動される最初のプログラムです。(ここではinitrdinitramfsの微妙な点には触れません。)このプログラムは、伝統的にinitと呼ばれ、プロセスID 1を持ち、特定の特権(KILLシグナルに対する免疫)と責任(孤児を育てる)を持っています。あなたは、Linuxカーネルでシステムを実行し、最初のプロセスとして好きな開始が、その後何を持っていると、通常の「Linux」と呼ばれるものをLinuxカーネルに基づくオペレーティングシステムである、とすることはできません-  Linuxの常識では、用語の、カーネルがLinuxカーネルであるUnixライクなオペレーティングシステム。たとえば、AndroidはUnixライクではなく、Linuxカーネルに基づいたオペレーティングシステムです。


素晴らしい答え。私はブートを述べたニーズがより広範な知識であることをことを、可能性、のためにLinuxカーネル対Linuxについてそれほど大きな加えを検索されます何のタイトルB / CでのLinux。
MDMoore313

@BigHomie Free Software Foundationは、カーネルがLinux(したがってGNU / Linux)であっても、ほとんど(すべて?)の「Linuxディストリビューション」ではソフトウェアがGNUであるため、私たち全員がGNU / Linuxと呼ぶことを望んでいます。
BenjiWiebe

ああ、誰もそのための時間を持っていません。それから私のディストリビューションはBusybox / Linuxと呼ばれるべきですか?? 私は知っている、それはあなただけではない、そのストールワースではないことを知っている;)
MDMoore313

1
@BenjiWiebeまたはGNU / X11 / Apacheの/ Linuxの/のTeX / Perlの/ Pythonの/ Freecivは。RMSとは別に、誰もが「Linux」と呼んでいます。
ジル 'SO-悪であるのをやめる'

@Gillesまあ、Debianとは別に、私は推測する。:)
CVn 14年

5

必要なのは、ファイルシステム上に分離して配置された、静的にリンクされた1つの実行可能ファイルです。他のファイルは必要ありません。その実行可能ファイルはinitプロセスです。busyboxにすることができます。これにより、シェルと他のユーティリティのホストがすべて提供されます。busyboxで手動でコマンドを実行してルートファイルシステムを読み書き可能にマウントし、/ devノードを作成し、実際のinitを実行するだけで、完全に機能するシステムに移動できます。


うん、busyboxがやってくるのは知っていた。他に何かが表示されるかどうか見てみましょう。
MDMoore313

4

シェルユーティリティが必要ない場合は、静的にリンクされたmkshバイナリ(たとえば、Linux / i386のklibc – 130Kに対して)が必要です。ループを呼び出すだけの/linuxrcor /initまたは/sbin/initスクリプトが必要ですmksh -l -T!/dev/tty1

#!/bin/mksh
while true; do
    /bin/mksh -l -T!/dev/tty1
done

この-T!$ttyオプションは最近追加されたmkshもので、指定された端末で新しいシェルを生成して待機するように指示します。(その前に、唯一のあった-T-プログラムの開発をdæmoniseとする-T$tty端末上で産卵しますが、それを待たない。これはとても素敵ではなかった。)-lオプションは、単純に(読み取るログインシェルを実行するように指示/etc/profile~/.profileおよび~/.mkshrc)。

これは、端末が/dev/tty1であると想定しています。(さらに魔法を使えば、ターミナルは自動的に検出されます。/dev/console完全なジョブ制御はできません。)

/devこれを機能させるには、いくつかのファイルが必要です。

  • / dev / console
  • / dev / null
  • / dev / tty
  • / dev / tty1

カーネルオプションを使用してブートすると、fill devtmpfs.mount=1の必要性がなくなり/dev、空のディレクトリにするだけです(マウントポイントとしての使用に適しています)。

通常、いくつかのユーティリティ(klibc、busybox、beastiebox、toybox、またはtoolbox)が必要になりますが、実際には必要ありません。

~/.mkshrcファイルを追加すると、$ PS1といくつかの基本的なシェルエイリアスと関数が設定されます。

Linux / m68k用にmksh(およびそのサンプルmkshrcファイル)とklibc-utilsのみを使用して171K圧縮(371K非圧縮)initrdを作成したことがあります。(ただし、これはシェルに-T!が追加される前だったため、/dev/tty2代わりにログインシェルを起動し、端末に切り替えるようにユーザーに伝えるメッセージをコンソールにエコーしました。)正常に動作します。

これは本当に最低限の設定です。他の回答は、より多くの機能を備えたシステムに対する優れたアドバイスを提供します。これは本当に特別な場合です。

免責事項:私はmksh開発者です。


これはすばらしい答えですmksh。共有していただきありがとうございます。
JoshuaRLi

2

最小限のinit 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

を使用することはできません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

次にcdLinuxカーネルツリーにビルドし、通常どおりビルドし、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

USBがオンの状態で実際のハードウェアで実行できます/dev/sdX

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をセットアップして、システムと対話できるようにします:https : //github.com/cirosantilli/runlinux

Ubuntu 16.10、QEMU 2.6.1でテスト済み

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.