私はいつも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.modprobe
sysctl値からプログラムを呼び出して、モジュールロードイベント(たとえば、新しいハードウェアが見つかった場合、または特定のネットワークプロトコルが初めて使用された場合)をトリガーできます。プログラムがコアをダンプすると、カーネルはkernel.core_pattern
もしそうなら。これらのプロセスはユーザープロセスですが、彼らの親は次のように登録されています。kthreadd
。
答え2
- カーネルの構造は
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つのスレッド(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 process
pid 1とpid 2があります。kthreadd process
したがって、ppidは0です。