在 Windows 中有许多方法可以检查进程 ID。
例如,使用 PowerShell 命令:
ps | select Id, ProcessName | Sort Id | ft -AutoSize
Run Code Online (Sandbox Code Playgroud)
我们看到以下输出:
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
...
Run Code Online (Sandbox Code Playgroud)
所有进程 ID 都是偶数,而且它们都是4 的倍数。
在任何基于 Windows NT 的 Windows 版本上都没有奇怪的进程 ID。
这是什么原因?
Dav*_*ill 168
分配内核句柄的相同代码也用于分配进程和线程 ID。由于内核句柄是 4 的倍数,因此进程和线程 ID 也是如此。
在基于 Windows NT 的操作系统上,进程和线程 ID 碰巧总是四的倍数。这只是巧合吗?
是的,这只是一个巧合,您不应该依赖它,因为它不是编程合同的一部分。例如,Windows 95 进程和线程 ID 并不总是四的倍数。(相比之下,内核句柄始终是 4 的倍数的原因是规范的一部分,并且在可预见的未来将得到保证。)
作为代码重用的副作用,进程和线程 ID 是 4 的倍数。分配内核句柄的相同代码也用于分配进程和线程 ID。由于内核句柄是 4 的倍数,因此进程和线程 ID 也是如此。这是一个实现细节,所以不要编写依赖它的代码。我只是告诉你满足你的好奇心。
Source为什么进程和线程 ID 是四的倍数?
不太为人所知的是,内核 HANDLE 的底部两位总是为零;换句话说,它们的数值总是 4 的倍数。请注意,这仅适用于内核句柄;它不适用于伪句柄或任何其他类型的句柄(用户句柄、GDI 句柄、多媒体句柄...)内核句柄是您可以传递给 CloseHandle 函数的东西。
底部两位的可用性隐藏在 ntdef.h 头文件中:
Run Code Online (Sandbox Code Playgroud)// // 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
GetQueuedCompletionStatus 函数暗示至少内核句柄的底部位始终为零,这表明您可以设置事件句柄的底部位以抑制完成端口通知。为了使其工作,底部位通常必须为零。
此信息对大多数应用程序编写者没有用,他们应继续将 HANDLE 视为不透明值。对标记位感兴趣的人是那些正在实现低级类库或将内核对象包装在更大框架中的人。
归档时间: |
|
查看次数: |
19949 次 |
最近记录: |