私はYouTubeチュートリアル(https://www.youtube.com/watch?v=asnXWOUKhTA)は最小限のLinuxディストリビューションを生成しますが、Ctrl + Cを押すとカーネルがクラッシュします!
編集:ctrl + dをすると混乱します。
答え1
これは、リンクされたチュートリアルの44:00時点から正確に発生します。
このチュートリアルでは、最小限のシェルスクリプトを使用します/init
。
#!/bin/sh
mount -t sysfs sysfs /sys
mount -t proc proc /proc
mount -t devtmpfs udev /dev
sysctl -w kernel.printk="2 4 1 7"
/bin/sh
このチュートリアルでは、追加された行はinitrdファイルを生成するスクリプトのpoweroff -f
最後の行/init
として追加されますが、initrdは実際にコマンドを含むように更新されません。
PID#1はスクリプトを実行するシェルで、ルートプロンプトを表示する/bin/sh
サブプロセスになるため、PID#1シェルは終了するのを待ち、終了/bin/sh
したらPID#1も同じです。それ以降は何のプロセスもありません。他の人がコメントで指摘したように、PID#1が失われると、カーネルは非常に不幸になります。これにより、次のメッセージでカーネルパニックが発生します。
Kernel panic - not syncing: Attempted to kill init!
(この場合、init
シャットダウンするのではなく、実際にはそれ自体でシャットダウンされます。PID#1は通常、システムをシャットダウンしたり、それ自体有効な後続エントリを提供したりせずにシャットダウンしないでください。)
この「最小のLinuxディストリビューション」が非常に基本的なおもちゃの設定であるという別の兆候があります。起動時に次のように/bin/sh
表示されます。
/bin/sh: can't access tty; job control turned off
/bin/sh
これは、正しく設定されたコンソールセッションで実行されておらず、通常の方法でCtrl+Cまたは+キーストロークにCtrl応答しないことを示します。Z代わりにCtrl-Cを受け取ると、/bin/sh
通常のシェルコマンドのように終了します。その後、スクリプトはファイル/init
の終わりに達するため、スクリプトを実行したシェル(PID#1)も終了します。
Ctrl-D は標準の Unix ファイル終了キーストロークなので、同じ効果を持つことができます。通常、TTYドライバはCtrl-Dを検出し、それをファイルの終了条件に変換しますが、シェルがここで述べたように、それ自体がcan't access tty
Ctrlを検出することもできます-D。デフォルトでは、シェルは標準入力のファイル終了条件を「ユーザーが何らかの方法で切断しました」と解釈し、シェルが終了し、PID#1スクリプトが最後に到達します。
この「最小Linuxディストリビューション」をさらに開発するための最初のステップは、/init
スクリプトをPID#1の要件を満たすプロセスに置き換えることです。
exec()
理想的には決して終了しませんが、新しいバージョンでアップデートを有効にすることもできます。- コンソールセッションと他の設定済みTTYを適切に初期化します(常に存在するプロセスに関連するプロセスを監視し、
getty
コンソールまたは設定済みTTYにライブプロセスがないことを確認したら、そのプロセスを開始します)。 wait(-1)
孤児ゾンビの収穫:PID#1は、カーネルがPID#1をPPIDとして割り当てる孤立プロセスからSIGCHLD信号を取得するのにほとんどの時間を費やす必要があります。これらの孤児プロセスが死ぬたびにwait()
その結果のコードを読み込み、一度完了すると、カーネルはプロセステーブルから死んだプロセスを消去することができ、ゾンビのように歩き回りません。
これは適切な設定を追加することで達成できます。忙しい箱/bin/init
initrd ファイルに追加し、最後の行を/init
次に置き換えます。
exec /bin/init
ここで重要なのは、exec
PID#1でスクリプトを実行しているシェルが新しいバイナリを呼び出す前にシステムコールを省略して、それ自体を/init
置き換えるようにすることです。したがって、PID番号は変更されず、実際のPID#1の役割を引き受けることができます。/bin/init
fork()
exec()
/bin/init