WindowsでプロセスIDを調べる方法はたくさんあります。
たとえば、PowerShellコマンドを使用します。
ps | select Id, ProcessName | Sort Id | ft -AutoSize
次のような出力が表示されます。
Id ProcessName
-- -----------
0 Idle
4 System
264 svchost
388 smss
476 csrss
536 wininit
580 winlogon
620 services
628 lsass
728 svchost
828 dwm
1060 chrome
1080 rundll32
1148 vmms
1620 spoolsv
2912 taskhostex
3020 Explorer
...
すべてのプロセスIDは偶数であり、さらに、すべての4の倍数です。
Windows NTに基づくWindowsのどのバージョンにも奇妙なプロセスIDはありません。
その理由は何ですか?
カーネルハンドルを割り当てるのと同じコードが、プロセスIDとスレッドIDの割り当てにも使用されます。カーネルハンドルは4の倍数なので、プロセスIDとスレッドIDも同様です。
Windows NTベースのオペレーティングシステムでは、プロセスIDとスレッドIDは常に4の倍数になります。これは単なる偶然ですか?
はい、それは単なる偶然の一致です、そしてそれはプログラミング契約の一部ではないのであなたはそれに頼るべきではありません。たとえば、Windows 95のプロセスIDとスレッドIDは、常に4の倍数ではありませんでした。 (比較すると、カーネルハンドルが常に4の倍数であるという理由は仕様の一部であり、近い将来保証されます。)
コードの再利用の副作用として、プロセスIDとスレッドIDは4の倍数です。カーネルハンドルを割り当てるのと同じコードが、プロセスIDとスレッドIDの割り当てにも使用されます。カーネルハンドルは4の倍数なので、プロセスIDとスレッドIDも同様です。これは実装の詳細なので、それに依存するコードを書かないでください。私はただあなたの好奇心を満たすようにあなたに言っています。
出典 プロセスIDとスレッドIDが4の倍数になっているのはなぜですか?
あまり知られていませんが、カーネルHANDLEの下位2ビットは常にゼロです。言い換えると、それらの数値は常に4の倍数です。これはカーネルハンドルにのみ適用されることに注意してください。疑似ハンドルや他のタイプのハンドル(USERハンドル、GDIハンドル、マルチメディアハンドルなど)には適用されません。カーネルハンドルは、CloseHandle関数に渡すことができるものです。
下位2ビットの可用性は、ntdef.hヘッダーファイルに埋め込まれています。
// // Low order two bits of a handle are ignored by the system and available // for use by application code as tag bits. The remaining bits are opaque // and used to store a serial number and table index. // #define OBJ_HANDLE_TAGBITS 0x00000003L
少なくともカーネルHANDLEの最下位ビットが常に0であることは、完了ポート通知を抑制するためにイベントハンドルの最下位ビットを設定できることを示すGetQueuedCompletionStatus関数によって暗黙的に示されます。これが機能するためには、最下位ビットは通常ゼロでなければなりません。
この情報は、HANDLEを不透明な値として扱い続ける必要があるほとんどのアプリケーション作成者にとっては役に立ちません。タグビットに興味がある人は、低レベルのクラスライブラリを実装している人、またはより大きなフレームワークの中にカーネルオブジェクトをラップしている人です。