[BlueLeaf1336]> PROBLEMS> 探求其之壱>

探求其之壱 > スレッドの数と基本優先度

historyTOP

2006/02/06:作成

プロセスの列挙(別の方法)TOP

これまで、プロセスの列挙を CreateToolhelp32Snapshot とか Process32First , Process32Next を使ってやってきました。この方法のよいところは、プロセスが何個あろうとも何の問題もなくすべて列挙できるところにあります。

ところで、EnumProcesses という API があります。名前のとおり、プロセスを列挙するものです。ただし弱点があって、すべてのプロセスの数がわからない状態で、すべてのプロセスを網羅できるだけの配列を引数に渡さないといけないのです。Platform SDK にもこんなことがかいてあります。

It is a good idea to specify a large array of DWORD values, because it is hard to predict how many processes there will be at the time you call EnumProcesses. To determine how many processes were enumerated by the call to EnumProcesses, divide the resulting value in the cbNeeded parameter by sizeof(DWORD). There is no indication given when the buffer is too small to store all process identifiers.

多分「全部のプロセスの数ってよくわからないんだよね。でも、なんとかしてよ。十分にでっかいサイズにするとかね。」とかいてあります。で、実際のサンプルでは、あ、その前に、この API は、列挙したプロセスのプロセスIDを戻します。で、このプロセスIDが収められるのが、引数に渡した配列というわけです。それで、サンプルでは、

DWORD aProcesses[1024]

なんていうサイズの配列を準備してるわけで。でもまぁそんなにプロセスを動かせるほどハイスペックマッシーンを使っているわけじゃぁないので、よしとします。

実際、今のままでも十分なんですが、うお。そういいながら、Process32First を改めて Platform SDK で引いてみて、勢いで PROCESSENTRY32 構造体のメンバを見てみると、「スレッドの数」があるやん。どうやってとろうか、スレッドを全部列挙して数えるんかなぁと思っていたところの、スレッドの数がすでに取得できてるやん。EnumProcesses やめです。

それはそれとして、プロセスIDからプロセスハンドルを取り出す処理で、OpenProcess してるのに CloseHandle してなバグを見つけました。定期的に監視するタイプのサンプルじゃないので問題が表面化してなかったようです。

ProcessIdToSessionIdTOP

それから、プロセスIDからセッションID(って何?)を取得する ProcessIdToSessionId という API も使ってみました。

    function ProcessIdToSessionId(
                dwProcessId: DWORD;
                var pSessionId: DWORD
                ): Boolean stdcall; external 'Kernel32.DLL' name 'ProcessIdToSessionId';

結果は、常に 0 ? タスクマネージャを見てみても、全部 0 っぽい。Windows2000 にはなかったし、何の意味があるのかわかりません。

改めて PROCESSENTRY32TOP

今のところ、プロセスIDしか使っていないんですが、スレッドの数と基本優先度もいけそうです。でも気になるのは、基本優先度が、LONG な点です。タスクマネージャを見てみると、winlogon 他が「高」、System 他大多数が「通常」になっています。それから System Idle Process が「N/A」です。

typedef struct tagPROCESSENTRY32 {
  DWORD dwSize;
  DWORD cntUsage;
  DWORD th32ProcessID;          //  プロセスID
  ULONG_PTR th32DefaultHeapID;
  DWORD th32ModuleID;
  DWORD cntThreads;             //  スレッドの数
  DWORD th32ParentProcessID;
  LONG pcPriClassBase;          //  基本優先度
  DWORD dwFlags;
  TCHAR szExeFile[MAX_PATH];
} PROCESSENTRY32, *PPROCESSENTRY32;

試してみるとこんな感じになりました。
イメージ名PROCESSENTRY32.pcPriClassBaseタスクマネージャの基本優先度
[System Process]0N/A
System8通常
smss.exe11通常
csrss.exe13
services.exe9通常
svchost.exe9通常

まぁなんというか、おおよそで文字列表記に直しているようです。0 が N/A なのははっきりしましたが、どこから通常なのか、通常の下に「低」はあるのか、などが不明なので、数値表記で許してもらうことにします。ところで、タスクマネージャでは「System Idle Process」なのに、こっちは [System Process] になってて気持ち悪いです。でもそれを言い出したら、アクセス権限でいろんな値が取れてないところも気になってくるので目をつぶります。

その他、なんとなくいくつか修正しました。

進捗状況TOP

20060206TaskMan.zip(6,820Bytes) ソースコードと実行ファイルです。

あと少しです。

まず、CPU系は以前簡単にはじき返されたことがあるので、なんとも厳しそうですが、デルタ系(メモリ使用量デルタ・ページフォルトデルタ)は、プログラムを定期的に監視するタイプに修正したときに、直前の値からの差分を表示するだけだろうと。

また、オブジェクト系は意味不明なので放置です。

最後に、ユーザー名ですが、これは何か API がありそうに思います。

EOFTOP