web-dev-qa-db-ja.com

なぜ奇妙なWindowsプロセスIDがないのですか?

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はありません。

その理由は何ですか?

159
Peter Hahndorf

「なぜ奇妙なWindowsプロセスIDがないのですか?」

カーネルハンドルを割り当てるのと同じコードが、プロセスIDとスレッドIDの割り当てにも使用されます。カーネルハンドルは4の倍数なので、プロセスIDとスレッドIDも同様です。


プロセスIDとスレッドIDが4の倍数になるのはなぜですか?

Windows NTベースのオペレーティングシステムでは、プロセスIDとスレッドIDは常に4の倍数になります。これは単なる偶然ですか?

はい、それは単なる偶然の一致です、そしてそれはプログラミング契約の一部ではないのであなたはそれに頼るべきではありません。たとえば、Windows 95のプロセスIDとスレッドIDは、常に4の倍数ではありませんでした。 (比較すると、カーネルハンドルが常に4の倍数であるという理由は仕様の一部であり、近い将来保証されます。)

コードの再利用の副作用として、プロセスIDとスレッドIDは4の倍数です。カーネルハンドルを割り当てるのと同じコードが、プロセスIDとスレッドIDの割り当てにも使用されます。カーネルハンドルは4の倍数なので、プロセスIDとスレッドIDも同様です。これは実装の詳細なので、それに依存するコードを書かないでください。私はただあなたの好奇心を満たすようにあなたに言っています。

出典 プロセスIDとスレッドIDが4の倍数になっているのはなぜですか?


なぜカーネルハンドルは常に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を不透明な値として扱い続ける必要があるほとんどのアプリケーション作成者にとっては役に立ちません。タグビットに興味がある人は、低レベルのクラスライブラリを実装している人、またはより大きなフレームワークの中にカーネルオブジェクトをラップしている人です。

出典 カーネルハンドルが常に4の倍数になるのはなぜですか?


参考文献


167
DavidPostill