initは正確に何をしますか?


43

Linuxディストリビューションを作成していますが、今は初期化プログラムが必要です。私はcでコードを書くことができ、Linuxについてかなりよく知っています(それほど多くはありませんが、4年前から開発にarch linuxを使用していました)。したがって、Cで独自の基本的なinitスクリプトを書いてみようと思いました。ただ疑問に思って、単純なシェル用にシステムをセットアップするためにinitはどのようなタスクを実行しますか?(「initは何をしますか?」

コードは必要なく、基本的なコマンドも必要ないかもしれませんが、実行する順序必要です。


1
Perl、awk、bash、(t)csh、ネイティブバイナリなど、SysVスタイルの初期化スクリプトに好きなインタープリターを使用できます。Bashは、そのようなスクリプトが存在するシステムで使用できることが実質的に保証されているため、通常使用されますSysVinitとbashの間に何らかのカップリングがあるためではなく、ブートプロセスの関連ポイントで展開されます。SysVinitはコントラクトを定義し、各スクリプトは、開発者が適切と考える方法でそのコントラクトを自由に実装できます。
CVn

回答:


53

システム5 initでは、ストーリーのごく一部しか表示されません。

Linuxの世界に影響を与える一種の近視があります。人々は「System 5 init」と呼ばれるものを使用していると考えています。それは伝統的なものであり、始めるのに最適な場所です。どちらも事実ではありません。

実際のところ、伝統は、そのような人々が言うように、初心者にとってはそうではありません。System 5 initとSystem 5はrc、AT&T UNIX System 5の日付です。これは、Linux-Mandrakeの最初のバージョンよりも(最初に)現在のように、最初のUNIXよりもずっと後でした。

第1版UNIXのみにありましたinit。ありませんでしたrc。第1版のアセンブリ言語initコード復元され、Warren Toomeyなどによって使用可能になりまし)は、12個のgettyプロセスを直接生成および再生成し、組み込みテーブルから3つのハードワイヤードファイルシステムをマウントし、ホームディレクトリからプログラムを直接実行しましたという名前のユーザーmelgettyテーブルには、プログラムイメージに直接でもありました。

いわゆる「伝統的な」Linux initシステムが登場したのは、UNIX System 5の10年後のことです。1992年、Miquel van SmoorenburgはLinux init+ rcおよび関連するツールを(再)書きました。initこれは、実際にはUNIX System 5のソフトウェアではありませんが(「System 5 」)init)。

System 5 init/ rcは開始するのに最適な場所ではありませんし、知っていることの半分をカバーしていないsystemdの知識を追加したとしてもです。initシステム設計(LinuxおよびBSD用)の分野では、過去20年間だけで多くの作業が行われています。あらゆる種類のエンジニアリングの決定が議論され、作られ、設計され、実装され、実践されてきました。商用Unicesも大活躍しました。

調査および学習する既存のシステム

以下にこれら2つ以外の主要な初期化システム一部の不完全なリストと、それらの(いくつかの)顕著な点の1つまたは2つを示します。

  • Joachim Nilssonのfinitは、より人間が読みやすい構成ファイルを使用するルートを取りました。
  • Felix von Leitnerのミニットは、ファイルシステムであるデータベース構成システム、小さなメモリフットプリント、および開始するものの間の開始/停止依存関係を求めましたinit
  • Gerrit Papeのrunitは、私が以前に記述した、4つのシェルスクリプトアプローチを生成するためのものです。
  • InitNGは、依存関係、名前付きターゲット、複数の構成ファイル、およびより柔軟な構成構文を持つことを目的としており、全体が子プロセスの設定をロードします。
  • upstartは完全な再設計に取り組み、システムをサービスや相互依存関係としてではなく、それらによってトリガーされるイベントやジョブとしてモデル化しました。
  • 設計間食は(さえ含む外サービス管理のすべてをプッシュ含む、getty個別のサービスマネージャに産卵し、ゾンビ刈り取りを)、そしてちょうどオペレーティング・システム固有の「API」デバイス/シンボリックリンク/ディレクトリやシステムイベントを処理します。
  • sinitは非常に単純なinitです。/bin/rc.initプログラムの起動、ファイルシステムのマウントなどのジョブを実行します。これには、minircなどを使用できます。

また、約10年前、daemontoolsのユーザーと使用のとりわけ議論があったsvscanようなプロジェクトにつながったプロセス#1、とポールJARCのsvscanプロセス1研究としてゲリット・パプのアイデア、そしてローランBercotのsvscanプロセス1とは

これにより、プログラム#1が行うプロセスがわかります。

プロセス#1プログラムが行うこと

プロセス#1が実行する「想定」の概念は、その性質上主観的です。意味のある客観的な設計基準は、最低でもプロセス#1がしなければならないことです。カーネルにはいくつかの要件があります。そして、それがしなければならない様々な種類のいくつかのオペレーティングシステム固有のものが常にあります。プロセス#1が伝統的に行っていることになると、私たちはその最小値ではなく、実際に実行されたことはありません。

さまざまなオペレーティングシステムカーネルや他のプログラムがプロセス#1に要求するいくつかのことがあります。

人々は、fork()物事を行い、孤立したプロセスの親として行動することが、プロセス#1の主要な機能であると言うでしょう。皮肉なことに、これは真実ではありません。孤立したプロセスに対処することは(https://unix.stackexchange.com/a/177361/5132で説明されているように、最近のLinuxカーネルでは)、プロセス#1から他のプロセスに大きく組み込むことができるシステムの一部です。専用のサービスマネージャー。これらはすべてサービスマネージャーであり、プロセス#1で実行されます。

同様に、https://superuser.com/a/888936/38062で説明されているように、/dev/initctlアイデア全体がプロセス#1の近くにある必要はありません。皮肉なことに、プロセス#1から移動できることを示すのは、高度に集中化されたsystemdです。

逆に、に必須のものinit、人々は通常、彼らのオフ・トップ・オブ・ヘッド設計で忘れていることは、このような処理など、ものですSIGINTSIGPWRSIGWINCH、など、カーネルから送信され、送信される各種システム状態の変更要求を制定しますプロセス#1への特定のシグナルが特定のものを意味することを「知っている」プログラムから。(例:https : //unix.stackexchange.com/a/196471/5132 で説明されているように、BSDツールセットSIGUSR1は特定の意味を持つ「知っている」。)

また、「API」ファイルシステムのマウントやファイルシステムキャッシュのフラッシュなど、エスケープできない、または実行しないことで大幅に苦しむ1回限りの初期化およびファイナライズタスクもあります。

「API」ファイルシステムを扱う基本は、initROM 1st Edition UNIXの操作とほとんど変わりません。1つはプログラムに組み込まれた情報のリストを持ち、もう1つはリスト内mount()のすべてのエントリを単純に持ちます。このメカニズムは、BSD(sic!)initからnoshをsystem-manager経てsystemdまでの多様なシステムで見つかります。

「システムを単純なシェル用にセットアップする」

あなたが観察してきたように、init=/bin/sh1種類なしキャッシュフラッシュと不格好な形でクラッシュし、「API」fileystemsがマウントされませんexithttps://unix.stackexchange.com/a/195978/5132)、および一般的な葉のそれ(スーパー)ユーザーに、システムを最小限に使用できるようにするアクションを手動で実行します。

実際にプロセス#1プログラムで行う以外に何も選択肢がないことを確認し、指定された設計目標に向けて良いコースを設定するには、Gerrit Papeのrunit、Felix vonの操作の重複を見ることが最良の選択肢ですライトナーのミニット、およびsystem-managernoshパッケージのプログラム。前者の2つは、ミニマリストにしようとする2つの試みを示していますが、それでも避けることのできないものを処理します。

後者は、system-managerプログラムへの広範な手動入力のために役立ちます。これは、どの「API」ファイルシステムがマウントされ、どの初期化タスクが実行され、どの信号が処理されるかを正確に詳述します。システムの設計により、システム管理者にだけ産卵3つの他のもの(サービスマネージャ、付随するロガー、および状態変化を実行するためのプログラムを)持っているだけで、プロセス#1にやむを得ないを行います。


3
素晴らしい答えと非常に有益です。しかし、私はこの全体像の中でOSXがどこにあるかを自問していlaunchdます。OSXが大規模な* nixファミリーの(素晴らしい)メンバーであることを完全に忘れる場合があります。
-DavAlPi

4

Debian上のSystem V init(他のバリアントとバリエーションがあります)は次のことを行います。

  • ランレベルに入ると、/etc/rcX.d/S*英数字順にスクリプトを呼び出しますX。ここで、ランレベルがあります。これらのスクリプトはランレベルをセットアップする必要があります。典型的なセットアップはデーモンの起動で、その実行レベルのセットアップタスクを実行します。これは、ランレベルに入るときに実行される1回限りの作業です。
  • 実行レベルでは、/etc/inittabその実行レベル中にアクティブにする必要があるとしてリストされているデーモンを開始します。それらのデーモンの実行が停止すると、デーモンが再起動されます。で管理したいデーモンはどれでも持つことができますがinit、少なくとも数個gettyはログインできるようにする必要があります。 gettyログインが完了すると終了し、init再起動して新しいログインプロンプトが表示されます。
    • デーモンが短時間で何度も再起動すると、しばらくの間、デーモンの再起動の試行が停止します。
    • 実行レベルに入るときにキックオフスクリプトによって何かが開始されたinitからといって、自動的に実行を続けようとしません。で個別に指定する必要があります/etc/inittab
  • ランレベルを終了するとき、それは/etc/rcX.d/K*英数字順にスクリプトを呼び出します、ここXでランレベルです。シャットダウンまたは再起動を実装する方法は、それらのイベントのランレベルを定義し、最後のタスクにhaltor rebootコマンドを実行させることです。
  • 電源イベントやCtrl-Alt-Delなどの特定のイベントに応じて実行可能ファイルを呼び出します。
  • ソケットをリッスンし、特定のメッセージを受信するとランレベルを変更します。

したがって、必要にinit応じて初歩的なサービスマネージャーとして使用できますが、最近の主なタスクはgetty、ユーザーがログインできるようにして、ランレベルの移行を開始できるようにすることです。

単純なシェル用にシステムをセットアップするために、initはどのようなタスクを実行するのか疑問に思っていました。

あなたが望むものなら、なんでも。Debianでは、各/etc/rcX.dディレクトリにスクリプトへのシンボリックリンクがあり、/etc/init.dこれらのスクリプトを完全にカスタマイズまたは削除できます。順序は、各スクリプトの前0001、などを付けて確立されます。

シェルを生成するだけの場合は、-bオプションinit(カーネルコマンドライン経由)を指定することもできますinit。シェルを終了するとき、init死ぬときinit、そして死ぬとき、カーネルはパニックします。


2

initが実行しなければならない絶対的な最低限は、少なくとも1つの他のプログラムを実行し、決して終了しないことです。initが終了すると、システムがクラッシュします。他の1つのプログラムを実行することさえ厳密に必要ではないと思いますが、そうしないと、initはシステムが行うと期待されるすべてのことを行う必要があります。そうしないと、あまり役に立ちません。


1
PID 1がクラッシュしたバグのあるLinuxシステムがありましたが、システムは基本的に実行し続けました。PID 1のクラッシュの程度は、カーネルのバージョンによって異なります。
ジル「SO-悪であるのをやめる」

1

init 好きなことをすることができます

initは、ブートプロセスの最後にLinuxカーネルによって呼び出される任意の実行可能ファイルです(そのような実行可能ファイルは1つだけです)。

これは、通常、ELF実行ファイルとして実装されているが、それはさえでシェルスクリプトをすることができchmod +xシェルスクリプトとして初期化

sysemdのような典型的な実装は、設定ファイルofenを読み取り/etc/initrc、それらの設定に基づいてユーザーランドプロセスの束を分岐して、システムのさまざまな側面を実装します。

ただし、これは完全に実装固有であるため、特定の実装を指定せずに質問に答えることはできません。たとえば、私はinit単に教育目的でrebootシステムコールを実行するプロセスで遊んでいます。

Linuxカーネルは、/initデフォルトでパスで実行可能ファイルを検索するだけですが、これはinit=Linuxカーネルのコマンドラインパラメーターでオーバーライドできます。

init試してみるのに最適な方法は、QEMUを使用することです。QEMUコマンドラインからQEMUにカーネルコマンドラインパラメーターを渡すことができ-appendます。オプションを使用すると、デスクトップをブリックする心配がありません。

以下は、最小限の完全自動化されたBuildroot + QEMUのセットアップです。これにより、問題をわかりやすくするために、独自の初期化を簡単に操作できます。


0

モジュール化された「1つのことを行い、それをうまく行う」という原則にコミットしている場合、initプログラムはプロセスを開始する必要があります。

プロセスを開始

カーネルが正常に解凍されたら実行する必要があります。システムが動作するために必要なすべての初期プロセスの初期化に関係するすべての基本的なタスクを処理します(/ etc / fstabにあるドライブのマウント、ネットワークインターフェイスの起動、など)。

起動とシャットダウンのプロセスは基本的に互いに逆であるため、initコマンドでは、シャットダウンコマンドでプロセスが確実に停止することもよくあります。

プロセスを停止する

これは、そのプロセスのマニュアルページに従ってプロセスを停止する必要があることを意味します(言い換えれば、単に露骨なだけでなくkill -9、プロセスを終了したい方法で停止する必要があります)、ドライブをアンマウントし、最終的に最終的な電源切断コマンドを発行します。

参照資料

他の人がこれをどのように行うかについての良いリファレンスは、Slackwareの/etc/rc.dスクリプトとninitminitの後継)のような既存の単純なinitシステムを 調べることです。プロセス監視(プロセスが終了した場合は再起動される)があり、これはおそらくinitの仕事ではありませんが、それでも非常に基本的で理解しやすく、特に作成者のサンプルスクリプトを通じて理解できます。

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