単一のアプリケーションを実行するLinuxシステムを作成する方法は?


17

Linuxアプリケーションを実行しようとしていますが、実行したいのは、この1つのアプリケーションだけを起動することです。ネットワークが必要で、それだけです(ディスプレイ、周辺機器などはありません)。他のアプリケーションが実行されないようにして、実行するアプリケーションのCPUが100%になるようにします。これは可能ですか?


OSにはまだリソースが必要なので、CPUの100%を取得することはできません。
n0pe

@MaxMackie当然ですが、OSがアプリケーションの代わりにのみ引き継ぐことを望んでいます(たとえば、ネットワークの目的で)。
dschatz

1
デスクトップ環境がロードされていても、アイドル状態のままであると、CPU時間を使用していないことに気付きますか?そして、それが使用しているラムは、他のアプリケーションがそれを要求する場合、交換されることがあります。
psusi

@dschatz質問に詳細を含めると役立ちます。実行したいアプリケーション、実行したい方法、使用しているハードウェアの種類について詳しく教えてください。
NN

可能であれば、これが必要な理由を知りたいと思います。私が理解していることから、アプリを実行するためだけに、OS(コンソールを含む)からすべてを削除する必要があります。パフォーマンスの向上はわずかなものになるので、そのすべてを機能させるポイントは何ですか?
nmat

回答:


13

最小限のinitrd CPIO 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 : //unix.stackexchange.com/questions/2692/what-is-the-smallest-possible-linux-implementation/203902#203902

Ubuntu 16.10、QEMU 2.6.1でテスト済み


3

init=/path/to/myappブートローダーで定義されたパラメーターでカーネルを起動できます。


2
これはかなり極端な解決策です。スタートアップスクリプトをユーザーアプリケーションに置き換えると、アプリケーションはネットワークなしで実行され、rootfs以外のファイルシステムはマウントされず(sysfs、proc、またはtmpfsなし)、一部のデバイスノードは作成されません。
おがくず

2
@sawdust:完全に同意します。しかし、問題は... :-)また、ビット極端だった
のMichałŠrajer

2

キオスクを設置しようとしているようです。インターネットに関するほとんどのガイドは、実行する単一のアプリケーションとして、FirefoxなどのWebブラウザーに焦点を当てています。アイデアについては、このガイドをご覧ください。


2
うーん、私は本当にネットワーキングで単一のアプリケーションを実行しようとしています。Xや他のアプリケーションをできるだけ実行したくない。これにより、すべての不要なデーモンの実行がどのように制限されるかわかりません。
dschatz

Xなしでもアプリケーションを実行できますか?
ジャーニーマンオタク

2

カーネルを起動した後、確実に1つのユーザーアプリケーションのみを実行できます。ただし、他のカーネル関連プロセスが存在する必要があるため、CPUが100%になることはありません。これは一般に、組み込みのLinuxデバイス(ワイヤレスルーターなど)で行われます。また、マルチスレッドアプリケーションでこれを実際に行った経験もあります。

カーネルが起動すると、初期化または起動スクリプトが実行されます。Linuxのランレベルと初期化プロセスを読んでください。さまざまなスタートアップスキームが使用されているため、特定することはできません。ただし、Linuxでは、状況に応じて実行するアプリケーションとデーモンを正確に構成できます。ルートの起動ファイル以外に、変更が必要なファイルは/ etc、特に/etc/init.dにあります

ところで、スーパープログラマーのようなものでない場合、またはリモートGDBサーバーを実行する前に、アプリケーション用のデバッグコンソール(PCコンソールまたはシリアルポート)が必要になります。これにより、セグメンテーション違反、バスエラー、アサーションエラーを通知できます。そのため、「ネットワーキング」の他に「周辺機器」を用意することを計画してください。


1

実行する必要があるシステムアプリケーションがいくつかありますが、それらに加えて、コンピュータリソースの残りをそのアプリケーション専用にすることができます。最小限にするには、TinyCore Linuxなどの非常に小さなLinuxディストリビューションをご覧ください。

また、アプリケーション自体、ネットワーク以外で必要なサービスなどにも依存します。

より具体的な情報を提供できれば、より詳細な回答が得られると思います。

どんなアプリなどが好き


私のアプリケーションは、pthreadライブラリを使用してマルチスレッドワークロード(算術演算)を実行し、tcp / ipからの入力に基づいて異なる計算を行うように指示できます。TinyCore Linuxを見ると、完全なデスクトップ環境で起動しますが、これは望ましくありません。
dschatz

TinyCoreには、MicroCoreという小さな兄弟がいます。GUIはありません。チェックしてください。
n0pe

1
@MaxMackie実際には、tcp / ipスタック以外のマシン自体にはインターフェースが必要ではありません。アプリケーションはポートでブロックでき、そのポートに送信されるTCPパケットを介して制御できます。
dschatz

1
実行中のサービスがほとんどない環境(これはlinuxhelp.blogspot.com/2006/04/…で確認できます)をお勧めします。アプリケーションと依存関係がインストールされている以外はほとんどありません。
n0pe

1
@dschatzは、カーネルをハックし、他のすべてを削除して、アプリをコンパイルする必要があります。bashはありません。ただあなたのアプリ..lol。
bakytn

1

Linuxカーネル、ネットワーク、およびアプリケーションのみが本当に必要な場合、これを行う唯一の方法は次のとおりです。

  • アプリケーションをカーネルモジュールにする必要があります-デバッグされ、十分にテストされていることを確認してください。このカーネルモジュールは、インターフェイスIPアドレスの設定など、ユーザー空間を介して通常行われることを初期化する必要があります。
  • make menuconfig独自のカスタムカーネルをダウンロードして構成()し、システムの実行とネットワークに関連しないすべての機能を削除する必要があります。レイヤーをブロックするために無効にする必要がありますmake menuconfig。最近のカーネルでを使用してこれを行う方法はわかりません。
  • 次に、モジュールをカーネルに含めて、ロード可能なモジュールではなくカーネルの一部として含める必要があります。上記の手順でロード可能なモジュールを無効にする可能性があります。カーネルモジュールを作成するのに十分なC / C ++を知っている場合、これは簡単です。
  • カーネルのどの部分でもパニックをinit起こさない場合は、パニックを起こす部分を変更するか、1つの余分なユーザー空間プロセスで生きる準備をする必要があります。

カーネルモジュールがプロセスを作成する可能性があることを知っています-単純な例でps auxは、典型的なシステム上で多くが表示されます(すべて括弧で囲まれています)。モジュールでカーネルプロセスを作成したいでしょう。自分以外のすべてのカーネル作成プロセスを削除するには、スレッド[ kthreadd]、電源管理[ pm]、イベントレイヤー[ events]などを無効にする必要があります。


カーネル+ 1ユーザースペースプロセスのより実用的なセットアップが必要な場合は、可能です。

Linuxには、カーネルコマンドラインオプションと呼ばれるinit=ものがあります。これは、ロードが完了するとカーネルが起動するものです。プログラムroot=は、initrdで指定された、またはinitrd(ブートローダーによってロードされた)で指定されたルートデバイス上になければなりません。

このプログラムが終了すると、Linuxがパニックするため、終了しないようにしてください。

ので、Linuxの多くの近代的なディストリビューションでは、それを設定しているinitinitrdの中にプログラムが起動する前に、いくつかの追加のユーザー・スペースの初期化を行います/sbin/init/sbin/systemd。ここであなたのディストリビューションが何をするのかを知り(Debianの情報はこちら)、最終的な「ハンドオフ」プログラムを指定できる場所を見つけ、そこからinitまたはの代わりにアプリケーションを起動するように指示する必要がありますsystemd

systemdビルド/dev、ホスト名の設定などの多くの基本機能を管理するため、柔軟性がある場合は、代わりにsystemd単一のプロセスを生成するための構成を検討し、オプションで失敗した場合は再起動することができます。私が間違っていない場合、基本的にシングルユーザーモードまたはリカバリモードでこれを行います-シェルを起動します。

2つのプロセス(systemdおよびプログラム)が実行されますが、プログラムが終了またはクラッシュしてもシステムはパニックになりません。

また、単にDebianの軽量インストールを検討してください-「netinst」インストールは、カーネル、シェル、およびいくつかのサービス以外はあまり実行されません-またはOpenWRT / LEDEを検討してください-デフォルトで実行されるLuci用のWebサーバーと他のサービスを結合しますが、簡単に無効にできます。

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