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的倍数。
没有奇数个进程ID。在任何基于Windows NT的Windows版本上。
是什么原因呢?
#1 楼
“为什么没有奇怪的Windows进程ID?”分配内核句柄的相同代码也用于
分配进程和线程ID。由于内核句柄是4的倍数,所以进程和线程ID也是4。
为什么进程和线程ID是4的整数倍?
在基于Windows NT的操作系统上,进程和线程ID总是四个的倍数。是一个巧合吗?
是,这只是巧合,您不应该依赖它,因为它不是编程合同的一部分。例如,Windows 95进程
和线程ID并不总是4的倍数。 (通过比较,
内核处理的原因始终是4的倍数,这是该规范的一部分,并且在可预见的将来将得到保证。)
进程和线程ID是4的倍数。作为代码
重复使用的副作用。分配内核句柄的相同代码也用于
分配进程和线程ID。由于内核句柄是4的倍数,因此进程和线程ID也是如此。这是一个实现细节,所以不要编写依赖它的代码。我只是在告诉您
满足您的好奇心。
来源为什么进程ID和线程ID都是4的倍数?是四个吗?
内核HANDLE的后两位始终不是零,这不是很众所周知。换句话说,它们的数值始终是4的倍数。注意,这仅适用于内核HANDLE;它不适用于伪句柄或任何其他类型的句柄(用户句柄,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函数隐式暗示,它指示您可以设置事件句柄的最低位来禁止完成端口通知。为了使它起作用,最低的
位通常必须为零。对标记位感兴趣的人是那些正在实现低级类库或将内核对象包装在更大的框架中的人。
源为什么内核HANDLE总是四个的倍数? Microsoft的设计工程师)。
评论
一句名言说“您不应该依赖它,因为它不是编程合同的一部分,”然后下一个声明ntdef.h说这些位“可被应用程序代码用作标记位”。公共头文件中的文档与您可能获得的“编程合同”差不多,因此第一个声明不正确。
– BlueRaja-Danny Pflughoeft
15年7月6日在10:44
@BlueRaja,“不太了解内核HANDLE的最低两位始终为零;换句话说,它们的数值始终为4的倍数。” ntdef.h中的代码也适用于其他类型的句柄(USER句柄,GDI句柄,多媒体句柄...)
–DavidPostill♦
15年7月6日在10:45
@BlueRaja:内核句柄是四个的倍数,这是契约性的,因此您可以依靠它;相反,进程ID(与进程句柄不同)恰好是四个的倍数,但这只是一个实现细节,因此您不应依赖它。
–马特奥(意大利)
15年7月6日在11:16
@BlueRaja我想雷蒙德会告诉你,无论是谁编写的文档,都是通过有色内核的眼镜看世界的,因此仅指内核句柄,而不是其他类型的句柄。
– CodesInChaos
15年7月6日在19:53
@Mehrdad:嗯,USER和GDI句柄通常不称为“内核”句柄(尽管它们是由以所谓的内核模式运行的组件生成的)。
–马特奥(意大利)
2015年7月7日在16:27
评论
可能有趣:有关linux的一些详细信息-justskins.com/forums/why-are-process-ids-204416.html确实没有。真奇怪。