Ctrl + Cがカーネルを殺さないようにする方法は? [閉鎖]

Ctrl + Cがカーネルを殺さないようにする方法は? [閉鎖]

私はYouTubeチュートリアル(https://www.youtube.com/watch?v=asnXWOUKhTA)は最小限のLinuxディストリビューションを生成しますが、Ctrl + Cを押すとカーネルがクラッシュします!

編集:ctrl + dをすると混乱します。

ベストアンサー1

これは、リンクされたチュートリアルの44:00時点から正確に発生します。

チュートリアルは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 ttyCtrlを検出することもできます-D。デフォルトでは、シェルは標準入力のファイル終了条件を「ユーザーが何らかの方法で切断しました」と解釈し、シェルが終了し、PID#1スクリプトが最後に到達します。

この「最小Linuxディストリビューション」をさらに開発するための最初のステップは、/initスクリプトをPID#1の要件を満たすプロセスに置き換えることです。

  • exec()理想的には決して終了しませんが、新しいバージョンでアップデートを有効にすることもできます。
  • コンソールセッションと他の設定済みTTYを適切に初期化します(常に存在するプロセスに関連するプロセスを監視し、gettyコンソールまたは設定済みTTYにライブプロセスがないことを確認したら、そのプロセスを開始します)。
  • wait(-1)孤児ゾンビの収穫:PID#1は、カーネルがPID#1をPPIDとして割り当てる孤立プロセスからSIGCHLD信号を取得するのにほとんどの時間を費やす必要があります。これらの孤児プロセスが死ぬたびにwait()その結果のコードを読み込み、一度完了すると、カーネルはプロセステーブルから死んだプロセスを消去することができ、ゾンビのように歩き回りません。

これは適切な設定を追加することで達成できます。忙しい箱/bin/initinitrd ファイルに追加し、最後の行を/init次に置き換えます。

exec /bin/init

ここで重要なのは、execPID#1でスクリプトを実行しているシェルが新しいバイナリを呼び出す前にシステムコールを省略して、それ自体を/init置き換えるようにすることです。したがって、PID番号は変更されず、実際のP​​ID#1の役割を引き受けることができます。/bin/initfork()exec()/bin/init

おすすめ記事