Por que não existem identificações de processo estranhas do Windows?

160

Existem várias maneiras de examinar as identificações de processo no Windows.

Por exemplo, usando o comando PowerShell:

ps | select Id, ProcessName  | Sort Id | ft -AutoSize

Vemos a seguinte saída:

  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       
...     

Todos os IDs de processo são números pares e, além disso, são múltiplos de 4 .

Não há identificações de processo ímpares em nenhuma versão do Windows baseada no Windows NT.

Qual é a razão para isto?

Peter Hahndorf
fonte
6
Possivelmente interessante: Alguns detaila sobre linux - justskins.com/forums/why-are-process-ids-204416.html
Dave
13
De fato, não há. Isso é estranho.
AndreKR

Respostas:

168

"Por que não existem IDs de processo estranhos no Windows?"

O mesmo código que aloca identificadores de kernel também é usado para alocar IDs de processos e threads. Como os identificadores do kernel são múltiplos de quatro, o mesmo acontece com os IDs de processos e threads.


Por que os IDs de processo e de thread são múltiplos de quatro?

Nos sistemas operacionais baseados no Windows NT, os IDs de processos e threads sempre são múltiplos de quatro. Será isso somente uma coincidência?

Sim, é apenas uma coincidência, e você não deve confiar nela, pois não faz parte do contrato de programação. Por exemplo, os IDs de processo e thread do Windows 95 nem sempre eram múltiplos de quatro. (Por comparação, a razão pela qual os manipuladores do kernel são sempre um múltiplo de quatro faz parte da especificação e será garantida no futuro próximo.)

Os IDs de processo e de encadeamento são múltiplos de quatro como efeito colateral da reutilização do código. O mesmo código que aloca identificadores de kernel também é usado para alocar IDs de processos e threads. Como os identificadores do kernel são múltiplos de quatro, o mesmo acontece com os IDs de processos e threads. Este é um detalhe de implementação, portanto, não escreva código que dependa dele. Só estou lhe dizendo para satisfazer sua curiosidade.

Origem Por que os IDs de processo e de thread são múltiplos de quatro?


Por que os HANDLEs do kernel sempre são múltiplos de quatro?

Não se sabe muito bem que os dois bits inferiores dos HANDLEs do kernel são sempre zero; em outras palavras, seu valor numérico é sempre um múltiplo de 4. Observe que isso se aplica apenas aos HANDLEs do kernel; não se aplica a pseudo-alças ou a qualquer outro tipo de alça (alças de USER, alças de GDI, alças de multimídia ...) Alças de kernel são coisas que você pode passar para a função CloseHandle.

A disponibilidade dos dois bits inferiores está oculta no arquivo de cabeçalho 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

Que pelo menos o bit inferior dos HANDLEs do kernel seja sempre zero é implícito pela função GetQueuedCompletionStatus, que indica que você pode definir o bit inferior do identificador de evento para suprimir a notificação da porta de conclusão. Para que isso funcione, o bit inferior normalmente deve ser zero.

Essas informações não são úteis para a maioria dos criadores de aplicativos, que devem continuar tratando os HANDLEs como valores opacos. As pessoas que estariam interessadas nos bits de tags são aquelas que estão implementando bibliotecas de classes de baixo nível ou estão agrupando objetos do kernel dentro de uma estrutura maior.

Origem Por que os HANDLEs do kernel sempre são múltiplos de quatro?


Leitura adicional


DavidPostill
fonte
3
Uma citação diz "você não deve confiar nele, pois não faz parte do contrato de programação", mas a próxima afirmação ntdef.h diz que os bits estão "disponíveis para uso pelo código do aplicativo como tag bits". A documentação em um arquivo de cabeçalho público é o mais próximo possível de um "contrato de programação" ; portanto, a primeira reivindicação está incorreta.
BlueRaja - Danny Pflughoeft
2
@BlueRaja, "Não é muito conhecido que os dois bits inferiores dos HANDLEs do kernel são sempre zero; em outras palavras, seu valor numérico é sempre um múltiplo de 4. " O código em ntdef.h também se aplica a outros tipos de identificadores (alças UTILIZADOR, GDI alças, multimídia lida ...)
DavidPostill
37
@BlueRaja: os identificadores do kernel são múltiplos de quatro e são contratuais, para que você possa confiar nele; IDs de processo (que são não o mesmo que processo alças), em vez disso, acontecerá a ser múltiplo de quatro, mas isso é apenas um detalhe de implementação, para que você não deve confiar nela.
Matteo Italia
6
@BlueRaja Acho que Raymond diria a você que quem escreveu a documentação olhou para o mundo através de óculos coloridos do kernel e, portanto, se referiu apenas às alças do kernel e não a outros tipos de alças.
CodesInChaos
1
@ Mehrdad: bem, os identificadores USER e GDI normalmente não são chamados de identificadores "kernel" (embora sejam gerados por componentes em execução no chamado modo kernel).
Matteo Italia