Почему нет нечетных идентификаторов процессов Windows?

160

Есть много способов проверить идентификаторы процессов в Windows.

Например, используя команду 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       
...     

Все идентификаторы процесса являются четными числами и, кроме того, все они кратны 4 .

В любой версии Windows, основанной на Windows NT, нет ни одного странного идентификатора процесса.

Что является причиной этого?

Питер Хандорф
источник
6
Возможно, интересно: некоторые подробности о Linux - justskins.com/forums/why-are-process-ids-204416.html
Дейв
13
На самом деле их нет. Это странно.
AndreKR

Ответы:

168

«Почему нет нечетных идентификаторов процессов Windows?»

Тот же код, который выделяет дескрипторы ядра, также используется для выделения идентификаторов процессов и потоков. Так как дескрипторы ядра кратны четырем, то же самое происходит с идентификаторами процессов и потоков.


Почему идентификаторы процессов и потоков кратны четырем?

В операционных системах на базе Windows NT идентификаторы процессов и потоков всегда кратны четырем. Это просто совпадение?

Да, это просто совпадение, и вы не должны полагаться на него, поскольку это не является частью контракта на программирование. Например, идентификаторы процессов и потоков в Windows 95 не всегда были кратны четырем. (Для сравнения, причина, по которой дескрипторы ядра всегда кратны четырем, является частью спецификации и будет гарантирована в обозримом будущем.)

Идентификаторы процессов и потоков кратны четырем, что является побочным эффектом повторного использования кода. Тот же код, который выделяет дескрипторы ядра, также используется для выделения идентификаторов процессов и потоков. Так как дескрипторы ядра кратны четырем, то же самое происходит с идентификаторами процессов и потоков. Это деталь реализации, поэтому не пишите код, который опирается на него. Я просто говорю вам, чтобы удовлетворить ваше любопытство.

Источник Почему идентификаторы процессов и потоков кратны четырем?


Почему РУЧКИ ядра всегда кратны четырем?

Не очень хорошо известно, что нижние два бита РУЧКИ ядра всегда равны нулю; другими словами, их числовое значение всегда кратно 4. Обратите внимание, что это относится только к РУЧКАМ ядра; он не применяется к псевдо-дескрипторам или к любому другому типу дескрипторов (дескрипторы 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

То, что по крайней мере нижний бит ядра HANDLE всегда равен нулю, подразумевается функцией GetQueuedCompletionStatus, которая указывает, что вы можете установить нижний бит дескриптора события, чтобы подавить уведомление порта завершения. Чтобы это работало, нижний бит обычно должен быть нулевым.

Эта информация бесполезна для большинства разработчиков приложений, которые должны продолжать обрабатывать HANDLE как непрозрачные значения. Люди, которые были бы заинтересованы в битах тегов, - это те, кто реализует низкоуровневые библиотеки классов или помещает объекты ядра в более крупную среду.

Источник Почему РУЧКИ ядра всегда кратны четырем?


дальнейшее чтение


ДэвидПостилл
источник
3
Одна цитата гласит: «Вы не должны полагаться на это, поскольку это не является частью контракта на программирование», но затем в следующей заявке ntdef.h говорится, что биты «доступны для использования кодом приложения в качестве битов тега». Документация в общедоступном заголовочном файле настолько близка к «контракту на программирование», насколько это возможно, поэтому первое утверждение неверно.
BlueRaja - Дэнни Пфлюгофт
2
@BlueRaja, «Не очень хорошо известно, что нижние два бита РУЧКИ ядра всегда равны нулю; другими словами, их числовое значение всегда кратно 4. » Код в ntdef.h также применим к другим типам дескрипторов (
Дескрипторы
37
@BlueRaja: дескрипторы ядра кратны четырем, и это по контракту, так что вы можете положиться на него; идентификаторы процессов (которые не так же , как обрабатывает процесс), вместо этого, случаются быть кратны четыре, но это всего лишь деталь реализации, так что вы не должны полагаться на него.
Matteo Italia
6
@BlueRaja Я думаю, что Раймонд сказал бы вам, что тот, кто писал документацию, смотрел на мир через очки цвета ядра и, следовательно, ссылался только на дескрипторы ядра, а не на другие виды дескрипторов.
CodesInChaos
1
@Mehrdad: ну, дескрипторы USER и GDI обычно не называются дескрипторами «ядра» (хотя они генерируются компонентами, работающими в так называемом режиме ядра).
Маттео Италия