題 為什麼沒有奇怪的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。

這是什麼原因?


158
2017-07-06 08:21


起源


可能有趣:關於linux的一些細節 - justskins.com/forums/why-are-process-ids-204416.html - Dave
確實沒有。那很奇怪。 - AndreKR


答案:


“為什麼沒有奇怪的Windows進程ID?”

分配內核句柄的相同代碼也被用於   分配進程和線程ID。因為內核句柄是多個   四個,進程和線程ID也是如此。


為什麼進程和線程ID是四的倍數?

在基於Windows NT的操作系統上,會發生進程和線程ID   永遠是四的倍數。這只是巧合嗎?

是的,這只是一個巧合,你不應該依賴它,因為它是   不屬於編程合同的一部分。例如,Windows 95進程   和線程ID並不總是四的倍數。 (相比之下,   內核處理的原因總是四的倍數是其中的一部分   規範並將在可預見的未來得到保證。)

進程和線程ID是四的倍數,作為代碼的副作用   再利用。分配內核句柄的相同代碼也被用於   分配進程和線程ID。因為內核句柄是多個   四個,進程和線程ID也是如此。這是一個實現   細節,所以不要編寫依賴它的代碼。我只是告訴你   滿足你的好奇心。

資源 為什麼進程和線程ID是四的倍數?


為什麼內核HANDLE總是4的倍數?

不太知名的是內核HANDLE的底部兩位是   永遠為零;換句話說,它們的數值總是一個倍數   注意,這僅適用於內核HANDLE;它不適用   偽句柄或任何其他類型的句柄(USER句柄,GDI   句柄,多媒體句柄......)內核句柄是你可以傳遞的東西   到CloseHandle函數。

底部兩位的可用性隱藏在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

至少內核HANDLEs的底部位總是為零   由GetQueuedCompletionStatus函數暗示,表示   你可以設置事件句柄的底部位來抑制   完成端口通知。為了這個工作,底部   bit通常必須為零。

此信息對大多數應用程序編寫者無用   應繼續將HANDLEs視為不透明值。那些人   對標籤位感興趣的是那些正在實施的人   低級類庫或將內核對象包裝在一個   更大的框架。

資源 為什麼內核HANDLE總是4的倍數?


進一步閱讀



166
2017-07-06 09:13



一句話說 “你不應該依賴它,因為它不是編程合同的一部分,” 然後下一個聲明ntdef.h說這些位是 “可供應用程序代碼用作標記位。”  公共頭文件中的文檔與a近似 “編程合同” 你可以得到,所以第一個索賠是不正確的。 - BlueRaja - Danny Pflughoeft
@BlueRaja,“不太知名的是底部兩位 內核HANDLE總是為零;換句話說,它們的數值總是4的倍數。“ntdef.h中的代碼也適用於其他類型的句柄(USER句柄,GDI句柄,多媒體句柄......) - DavidPostill♦
@BlueRaja:內核句柄是四個中的多個,這是合同,所以你可以依賴它; 流程ID (哪個是 不 與過程句柄相同),相反, 發生 是四的倍數,但這只是一個實現細節,所以你不應該依賴它。 - Matteo Italia
@BlueRaja我想雷蒙德會告訴你,編寫文檔的人看著這個世界 內核色眼鏡 因此只引用內核句柄而不是其他類型的句柄。 - CodesInChaos
@Mehrdad:好吧,USER和GDI句柄通常不稱為“內核”句柄(儘管它們是由在所謂的內核模式下運行的組件生成的)。 - Matteo Italia