web-dev-qa-db-ja.com

Linuxは次のPIDをどのように決定しますか?

Linuxはプロセスに使用する次のPIDをどのように決定しますか?この質問の目的は、Linuxカーネルをよりよく理解することです。カーネルのソースコードを投稿することを恐れないでください。 PIDが順次割り当てられる場合、Linuxはどのようにしてギャップを埋めますか?それが終わりを迎えるとどうなりますか?

たとえば、Apacheから<?php print(getmypid());?>を実行するPHPスクリプトを実行すると、ヒットリフレッシュ中に同じPIDが数分間出力されます。この期間はApacheが受け取っている要求の数の関数クライアントが1つしかない場合でも、PIDは最終的に変更されます。

PIDが変更されると、近い数字になりますが、どれくらい近いですか?番号は完全に連続しているようには見えません。 ps aux | grep Apacheかなりの数のプロセスを取得します。

enter image description here

Linuxはこの次の番号をどのように選択しますか?前のいくつかのPIDと、印刷された最新のPIDがまだ実行されています。 ApacheはこれらのPIDの再利用をどのように選択しますか?

40
rook

カーネルは(RESERVED_PIDS、PID_MAX_DEFAULT)の範囲でPIDを割り当てます。これは、各名前空間で順次行われます(異なる名前空間のタスクは同じIDを持つことができます)。範囲が使い果たされた場合、pid割り当てが循環します。

いくつかの関連コード:

Alloc_pid(...)の内部

_for (i = ns->level; i >= 0; i--) {
    nr = alloc_pidmap(tmp);
    if (nr < 0)
        goto out_free;
    pid->numbers[i].nr = nr;
    pid->numbers[i].ns = tmp;
    tmp = tmp->parent;
}
_

alloc_pidmap()

_static int alloc_pidmap(struct pid_namespace *pid_ns)
{
        int i, offset, max_scan, pid, last = pid_ns->last_pid;
        struct pidmap *map;

        pid = last + 1;
        if (pid >= pid_max)
                pid = RESERVED_PIDS;
        /* and later on... */
        pid_ns->last_pid = pid;
        return pid;
}
_

カーネルのコンテキストでのPIDは単なるint識別子ではないことに注意してください。関連する構造体は_/include/linux/pid.h_にあります。 IDの他に、そのIDを持つタスクのリスト、参照カウンター、および高速アクセス用のハッシュリストノードが含まれます。

PIDがユーザー空間で順次表示されない理由は、カーネルスケジューリングがプロセスのfork()呼び出しの間にプロセスをフォークする可能性があるためです。実際、それは非常に一般的です。

51

私はむしろあなたが見ている振る舞いを仮定したい別のソースからのステム

通常、優れたWebサーバーには、要求の負荷を分散するためにいくつかのプロセスインスタンスがあります。これらのプロセスはプールで管理され、リクエストが来るたびに特定のリクエストに割り当てられます。パフォーマンスを最適化するために、Apacheはおそらく同じプロセスを同じクライアントからの一連のリクエストに割り当てます。一定量のリクエストの後、そのプロセスは終了し、新しいリクエストが作成されます。

Linuxでは、複数のプロセスに同じPIDが連続して割り当てられているとは思いません。

新しいPIDは最後のPIDに近いとおっしゃるように、Linuxは各プロセスに最後のPID + 1を割り当てるだけだと思います。次に開始されるApacheプロセスの正確な数を予測することはできません。

これとは別に、not実装するもののベースとしてPID割り当てに関する仮定を使用する必要があります。 (sanmaiのコメントも参照してください。)

10
chiccodoro

PID 順次 ほとんどのシステム。アイドル状態のマシンで自分でいくつかのプロセスを開始することによってそれを見ることができます。

例えば上矢印履歴リコールを使用して、独自のPIDを出力するコマンドを繰り返し実行します。

$ ls -l /proc/self
lrwxrwxrwx 1 root root 0 Mar 15 19:32 /proc/self -> 21491
$ ls -l /proc/self
lrwxrwxrwx 1 root root 0 Mar 15 19:32 /proc/self -> 21492
$ ls -l /proc/self
lrwxrwxrwx 1 root root 0 Mar 15 19:32 /proc/self -> 21493
$ ls -l /proc/self
lrwxrwxrwx 1 root root 0 Mar 15 19:32 /proc/self -> 21494

これに依存しないでください。セキュリティ上の理由から、新しいPIDをランダムに選択するために余分なCPU時間を費やすカーネルを実行する人もいます。

9

PIDはランダムに割り当てることができます。そのためには いくつかの方法 があります。

4
sanmai