web-dev-qa-db-ja.com

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

Linuxディストリビューションを作成していますが、今はinitプログラムが必要です。私はcで非常にうまくコーディングでき、linuxについてはかなり知っています(ただし、開発にArch Linuxを4年間使用しています)。したがって、Cで独自の基本的なinitスクリプトを作成する必要があると考えました。疑問に思って、単純なシェル用にシステムをセットアップするためにinitが実行するタスクは何ですか? (「initの機能は何ですか?」

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

43
DividedByZero

システム5 initは、ストーリーのほんの一部しか伝えません。

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

手始めに、伝統は実際にそのような人々がそれがそうであると言うものではありません。 System 5 initとSystem 5 rcは、AT&T UNIX System 5の日付です。これは、最初のバージョンのLinux-Mandrakeの後(現在のところ)と同じくらい、最初のUNIXのあとです。

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

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

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

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

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

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

さらに、約10年前、daemontoolsのユーザーと他の人の間で、プロセス#1としてsvscanを使用することについての議論があり、 Paul Jarcのsvscan as process 1 studyGerrit Papeのアイデア) 、および Laurent Bercotのプロセス1としてのsvscan

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

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

どのプロセス#1が「想定される」かという概念は、その性質上主観的なものです。意味のある目的設計基準は、プロセス#1で最低限実行する必要があるです。カーネルはいくつかの要件を課しています。また、オペレーティングシステム固有のさまざまな処理が常に行われています。プロセス#1が伝統的に行ったことについては、その最低限ではなく、実際に行われたことはありません。

さまざまなオペレーティングシステムカーネルや他のプログラムがプロセス#1に要求するいくつかのことがあり、それを回避することはできません。

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

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

逆に、人々が最初から頭の設計で忘れているinitの必須事項は、カーネルから送信されたSIGINTSIGPWRSIGWINCHなどの処理やさまざまなシステムの制定などです。 #1を処理する特定のシグナルが特定のことを意味することを「知っている」プログラムから送信される状態変更要求。 (例: https://unix.stackexchange.com/a/196471/5132 で説明されているように、BSDツールセットは_SIGUSR1_が特定の意味を持つことを「認識」しています。)

"API" filesystems をマウントしたり、ファイルシステムキャッシュをフラッシュしたりするなど、1回限りの初期化タスクとファイナライズタスクがあり、エスケープできないか、実行しないと大幅に影響を受けます。

「API」ファイルシステムの処理の基本は、init rom 1st Edition UNIXの操作と少し異なります。1つはプログラムに組み込まれた情報のリストを持ち、もう1つはリストのすべてのエントリを単にmount() sします。このメカニズムは、BSD(sic!)initからnosh _system-manager_を介してsystemdまで、さまざまなシステムで見つかります。

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

あなたが観察したように、_init=/bin/sh_は「API」ファイルシステムをマウントせず、exithttps://unix.stackexchange.com/a/ 195978/5132 )、そして一般に、システムを最小限にしか使用できないようにするアクションを手動で実行する(スーパー)ユーザーに任せます。

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

後者は、_system-manager_プログラムの広範な手動エントリに役立ちます。これは、どの「API」ファイルシステムがマウントされ、どの初期化タスクが実行され、どのシグナルが処理されるかを正確に示します。 設計によってシステムマネージャーがシステムマネージャーに他の3つのもの(サービスマネージャー、付随するロガー、および状態変更を実行するプログラム)を生成するシステム)そして、プロセス#1で避けられないことのみを実行します。

53
JdeBP

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

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

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

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

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

initにシェルを生成させたいだけの場合は、init-bオプションを指定することもできます(つまり、カーネルコマンドラインを介して)。シェルを終了すると、initが終了し、initが終了すると、カーネルがパニックになります。

4
LawrenceC

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

2
hildred

initはあなたがやりたいことを何でもできます

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

通常はELF実行可能ファイルとして実装されますが、chmod +xを使用したシェルスクリプトにすることもできます。 シェルスクリプトとして初期化

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

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

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

initをいじる優れた方法の1つは、QEMUを使用することです。これは、カーネルコマンドラインパラメーターを-appendオプションを使用してQEMUコマンドラインからQEMUに渡すことができるため、デスクトップ。

これが私の 最小限の完全に自動化されたBuildroot + QEMUセットアップ です。これにより、問題をわかりやすく説明するために、自分のinitを非常に簡単に操作できます。

モジュール化された「1つのことをうまく実行する」という原則に取り組んでいる場合、initプログラムがプロセスを開始するはずです。

開始プロセス

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

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

プロセスを停止

つまり、そのプロセスのmanページに従ってプロセスを停止し(つまり、露骨なkill -9ではなく、プロセスを停止したい方法で停止させる)、ドライブをアンマウントして、最終的に発行する必要があります。最後の電源切断コマンド。

参考文献

これが他の人によってどのように行われるかについての良い参照は、 Slackwareの/etc/rc.dスクリプト と、 ninit のようなすでに存在する単純なinitシステムを調べることです。 (minitの後継)。プロセスの監視(プロセスが停止すると再起動されることを意味します)があり、それは間違いなくinitの仕事ではありませんが、特に作成者のサンプルスクリプトを通して、それは非常に基本的で理解が簡単です。