initプロセス:すべてのプロセスの先祖?

initプロセス:すべてのプロセスの先祖?

私はいつもinitプロセスがすべてのプロセスの先祖であることを知っていました。プロセス2のPPIDが0の理由は何ですか?

$ ps -ef | head -n 3
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 May14 ?        00:00:01 /sbin/init
root         2     0  0 May14 ?        00:00:00 [kthreadd]

答え1

まず、「祖先」は「親」とは異なる。祖先は親の親...親の親になることができ、カーネルは1つのレベルだけを追跡します。ただし、プロセスが終了すると、その子はinitによって採用されるため、一般的なシステムでは親が1の多くのプロセスを見ることができます。

最新のLinuxシステムにはカーネルコードを実行する追加のプロセスがありますが、予約のためにユーザープロセスとして管理されています。 (カーネルコードを実行するため、一般的なメモリ管理規則に従わない。)これらのプロセスは、kthreaddカーネルスレッドの初期化によって生成される。/proc/2/exe読み取れないという事実(通常はプロセス実行可能ファイルへのシンボリックリンク)として識別できます。または、ps角かっこ内に名前を付けてリストします(通常のユーザープロセスでは可能ですが一般的ではありません)。親プロセスID 2を使用するほとんどのプロセスはカーネルプロセスですが、PPID 2を使用するいくつかのカーネルヘルパープロセスもあります(下記参照)。

プロセス1(init)と2(kthreadd)は起動時にカーネルによって直接生成されるため、親プロセスはありません。これを示すには、ppidフィールドにゼロ値を使用します。ここで、0 は「カーネル自体」を意味します。

Linuxには、カーネルが場所を決定するユーザープロセスを開始できるツールもあります。システム制御パラメータ場合によっては。たとえば、カーネルはkernel.modprobesysctl値からプログラムを呼び出して、モジュールロードイベント(たとえば、新しいハードウェアが見つかった場合、または特定のネットワークプロトコルが初めて使用された場合)をトリガーできます。プログラムがコアをダンプすると、カーネルはkernel.core_patternもしそうなら。これらのプロセスはユーザープロセスですが、彼らの親は次のように登録されています。kthreadd

答え2

  1. カーネルの構造はtask_structマクロコードによって静的に生成されます。
    struct task_struct init_task = INIT_TASK(init_task);
    EXPORT_SYMBOL(init_task);
    
    これはnrグローバルPID番号です。 0から始まります。
    #define INIT_STRUCT_PID {                                \
        .numbers     = { {                                   \
            .nr      = 0,                                    \
            .ns      = &init_pid_ns,                         \
            .pid_chain   = { .next = NULL, .pprev = NULL },  \
        }, }                                                 \
    }
    
  2. カーネル起動プロセス中に2つのスレッド(initとkthreadd)が生成されます。
    static noinline void __init_refok rest_init(void)
    {
         /* spawn init thread */
         kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
    
         /* spawn kthreadd thread */
         pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
    
         cpu_idle();
    }
    
    カーネルの自然な結果としてinit processpid 1とpid 2があります。kthreadd processしたがって、ppidは0です。

関連情報