Sobre as tabelas Atom

Uma tabela atom é uma tabela definida pelo sistema que armazena cadeias de caracteres e identificadores correspondentes. Um aplicativo coloca uma cadeia de caracteres em uma tabela atom e recebe um inteiro de 16 bits, chamado atom, que pode ser usado para acessar a cadeia de caracteres. Uma cadeia de caracteres que foi colocada em uma tabela de átomos é chamada de nome de átomo.

O sistema fornece uma série de tabelas de átomos. Cada tabela de átomos serve a um propósito diferente. Por exemplo, os aplicativos DDE (Dynamic Data Exchange) usam a tabela atom global para compartilhar cadeias de caracteres de nome de item e nome de tópico com outros aplicativos. Em vez de passar cadeias de caracteres reais, um aplicativo DDE passa átomos globais para seu aplicativo parceiro. O parceiro usa os átomos para obter as cordas da tabela de átomos.

Os aplicativos podem usar tabelas atom locais para armazenar suas próprias associações de nome de item.

O sistema usa tabelas atom que não são diretamente acessíveis aos aplicativos. No entanto, o aplicativo usa esses átomos ao chamar uma variedade de funções. Por exemplo, os formatos de área de transferência registrados são armazenados em uma tabela atom interna usada pelo sistema. Um aplicativo adiciona átomos a essa tabela atom usando a função RegisterClipboardFormat. Além disso, as classes registradas são armazenadas em uma tabela atom interna usada pelo sistema. Um aplicativo adiciona átomos a essa tabela de átomos usando a função RegisterClass ou RegisterClassEx.

Os tópicos a seguir são discutidos nesta seção.

Tabela global de átomos

A tabela atom global está disponível para todos os aplicativos. Quando um aplicativo coloca uma cadeia de caracteres na tabela atom global, o sistema gera um átomo que é exclusivo em todo o sistema. Qualquer aplicativo que tenha o atom pode obter a cadeia de caracteres que ele identifica consultando a tabela atom global.

Um aplicativo que define um formato de dados DDE privado para compartilhar dados com outros aplicativos deve colocar o nome do formato na tabela atom global. Essa técnica evita conflitos com os nomes de formatos definidos pelo sistema ou por outros aplicativos, e disponibiliza os identificadores (átomos) das mensagens ou formatos para as demais aplicações.

Tabela Atom do usuário

Além da tabela atom global, a tabela atom do usuário é outra tabela de átomos do sistema que também é compartilhada em todos os processos. A tabela atom do usuário é usada para um pequeno número de cenários internos ao win32k; por exemplo, nomes de módulos do Windows, cadeias de caracteres bem conhecidas no win32k, formatos OLE, etc. Embora os aplicativos não interajam diretamente com a tabela atom do usuário, eles chamam várias APIs — como RegisterClass, RegisterWindowMessage e RegisterClipboardFormat — que adicionam entradas à tabela atom do usuário. As entradas adicionadas por RegisterClass podem ser excluídas pelo UnregisterClass. No entanto, as entradas adicionadas por RegisterWindowMessage e RegisterClipboardFormat não são excluídas até que a sessão termine. Se a tabela atom do usuário não tiver mais espaço e a cadeia de caracteres que está sendo passada ainda não estiver na tabela, a chamada falhará.

Tamanho da tabela Atom

Muitas APIs críticas, incluindo CreateWindow, dependem de átomos de usuário. Portanto, a exaustão de espaço na tabela de átomos do usuário resultará em sérios problemas; Por exemplo, todos os aplicativos podem falhar ao iniciar. Aqui estão algumas recomendações para garantir que seu aplicativo utilize tabelas atom de forma eficiente e preserve a confiabilidade e o desempenho do aplicativo e do sistema:

  1. Você deve limitar o uso da tabela atom do usuário pelo seu aplicativo. O armazenamento de cadeias de caracteres exclusivas usando APIs como RegisterClass, ou RegisterClipboardFormat ocupa espaço na tabela atom do usuário, RegisterWindowMessageque é usada globalmente por outros aplicativos para registrar classes de janela usando cadeias de caracteres. Se possível, você deve usar AddAtom DeleteAtom para armazenar cadeias de caracteres em uma tabela atom local ou GlobalAddAtom GlobalDeleteAtom// se os átomos forem necessários entre processos.

  2. Se houver preocupação com o aplicativo causando problemas na tabela atom do usuário, você pode investigar a causa raiz conectando o depurador do kernel e invadindo o processo em chamadas para UserAddAtomEx (bae1 win32kbase!UserAddAtomEx /p <eprocess> "kc10;g"). Procure user32! na pilha de chamadas para ver qual API está sendo chamada. A metodologia é semelhante à detecção de problemas de tabela de átomos global explicada em Identificando vazamentos globais de tabela de átomos. Outra maneira de despejar o conteúdo da tabela atom do usuário é chamando GetClipboardFormatName sobre o intervalo de átomos possíveis de 0xC000 a 0xFFFF. Se a contagem total de átomos aumentar constantemente enquanto o aplicativo estiver em execução ou não retornar à linha de base quando o aplicativo for fechado, haverá um problema.

Tabelas Atom Locais

Um aplicativo pode usar uma tabela atom local para gerenciar com eficiência um grande número de cadeias de caracteres usadas somente dentro do aplicativo. Essas cadeias de caracteres e os átomos associados estão disponíveis somente para o aplicativo que criou a tabela.

Um aplicativo que requer a mesma cadeia de caracteres em várias estruturas pode reduzir o uso de memória usando uma tabela atom local. Em vez de copiar a cadeia de caracteres em cada estrutura, o aplicativo pode colocar a cadeia de caracteres na tabela atom e incluir o átomo resultante nas estruturas. Dessa forma, uma cadeia de caracteres aparece apenas uma vez na memória, mas pode ser usada muitas vezes no aplicativo.

Os aplicativos também podem usar tabelas atom locais para economizar tempo ao procurar uma cadeia de caracteres específica. Para realizar uma pesquisa, um aplicativo precisa apenas colocar a cadeia de pesquisa na tabela de átomos e comparar o átomo resultante com os átomos nas estruturas relevantes. Comparar átomos é tipicamente mais rápido do que comparar cordas.

As tabelas Atom são implementadas como tabelas de hash. Por padrão, uma tabela atom local usa 37 buckets para sua tabela de hash. No entanto, você pode alterar o número de buckets usados chamando a função InitAtomTable. No entanto, se o aplicativo chamar InitAtomTable, ele deverá fazer isso antes de chamar quaisquer outras funções de gerenciamento de átomos.

Tipos de átomos

Os aplicativos podem criar dois tipos de átomos: átomos de cadeia de caracteres e átomos inteiros. Os valores de átomos inteiros e átomos de cadeia de caracteres não se sobrepõem, portanto, ambos os tipos de átomos podem ser usados no mesmo bloco de código.

Várias funções aceitam cadeias de caracteres ou átomos como parâmetros. Ao passar um átomo para essas funções, um aplicativo pode usar a macro MAKEINTATOM para converter o átomo em um formulário que pode ser usado pela função.

As seções a seguir descrevem os tipos de átomos.

Átomos de corda

Quando os aplicativos passam cadeias de caracteres terminadas em nulo para as funções GlobalAddAtom, AddAtom, GlobalFindAtom e FindAtom, eles recebem átomos de cadeia de caracteres (inteiros de 16 bits) em troca. Os átomos de cadeia de caracteres têm as seguintes propriedades:

  • Os valores dos átomos de cadeia estão no intervalo 0xC000 (MAXINTATOM) até 0xFFFF.
  • O caso não é significativo nas buscas por um nome de átomo em uma tabela de átomos. Além disso, a cadeia de caracteres inteira deve corresponder em uma operação de pesquisa; nenhuma correspondência de subcadeia de caracteres é executada.
  • A cadeia de caracteres associada a um átomo de cadeia de caracteres não pode ter mais de 255 bytes de tamanho. Essa limitação se aplica a todas as funções do átomo.
  • Uma contagem de referência é associada a cada nome de átomo. A contagem é incrementada cada vez que o nome do átomo é adicionado à tabela e diminuída cada vez que o nome do átomo é excluído dela. Isso impede que diferentes usuários do mesmo átomo de cadeia de caracteres destruam os nomes de átomos uns dos outros. Quando a contagem de referência para um nome de átomo é igual a zero, o sistema remove o átomo e o nome do átomo da tabela.

Átomos inteiros

Os átomos inteiros diferem dos átomos de cadeia de caracteres das seguintes maneiras:

  • Os valores dos átomos inteiros estão no intervalo 0x0001 até 0xBFFF (MAXINTATOM– 1).
  • A representação de cadeia de caracteres de um átomo inteiro é #dddd, onde os valores representados por dddd são dígitos decimais. Os zeros à esquerda são ignorados.
  • Não há contagem de referência ou sobrecarga de armazenamento associada a um átomo inteiro.

Criação do Atom e contagem de uso

Um aplicativo cria um átomo local chamando a função AddAtom, ele cria um átomo global chamando a função GlobalAddAtom. Ambas as funções exigem um ponteiro para uma cadeia de caracteres. O sistema procura a tabela atom apropriada para a cadeia de caracteres e retorna o átomo correspondente ao aplicativo. No caso de um átomo de cadeia de caracteres, se a cadeia de caracteres já reside na tabela atom, o sistema incrementa a contagem de referência para a cadeia de caracteres durante esse processo.

Chamadas repetidas para adicionar o mesmo nome de átomo retornam o mesmo átomo. Se o nome do átomo não existir na tabela quando AddAtom for chamado, o nome do átomo será adicionado à tabela e um novo átomo será retornado. Se for um átomo de cadeia de caracteres, sua contagem de referência também será definida como um.

Um aplicativo deve chamar a função DeleteAtom quando não precisa mais usar um átomo local, ele deve chamar a função GlobalDeleteAtom quando não precisa mais de um átomo global. No caso de um átomo de corda, qualquer uma dessas funções reduz a contagem de referência do átomo correspondente em um. Quando a contagem de referência atinge zero, o sistema exclui o nome do átomo da tabela.

O nome do átomo de um átomo de cadeia de caracteres permanece na tabela de átomos global desde que sua contagem de referência seja maior que zero, mesmo depois que o aplicativo que o colocou na tabela terminar. Uma tabela de átomos local é destruída quando o aplicativo associado termina, independentemente das contagens de referência dos átomos na tabela.

Consultas de tabela atômica

Um aplicativo pode determinar se uma determinada cadeia de caracteres já está em uma tabela atom usando a função FindAtom ou GlobalFindAtom. Essas funções pesquisam uma tabela atom para a cadeia de caracteres especificada e, se a cadeia de caracteres estiver lá, retornam o átomo correspondente.

Um aplicativo pode usar a função GetAtomName ou GlobalGetAtomName para recuperar uma cadeia de caracteres atom-name de uma tabela atom, desde que o aplicativo tenha o atom correspondente à cadeia de caracteres que está sendo procurada. Ambas as funções copiam a cadeia de caracteres atom-name do átomo especificado para um buffer e retornam o comprimento da cadeia de caracteres que foi copiada. GetAtomName recupera uma cadeia de caracteres atom-name de uma tabela atom local e GlobalGetAtomName recupera uma cadeia de caracteres atom-name da tabela atom global.

Formatos de cadeia de caracteres Atom

As funções AddAtom, GlobalAddAtom, FindAtom e GlobalFindAtom levam um ponteiro para uma cadeia de caracteres terminada em nulo. Um aplicativo pode especificar esse ponteiro de uma das seguintes maneiras.

Formato da cadeia de caracteres Descrição
#dddd Um inteiro especificado como uma cadeia decimal. Usado para criar ou localizar um átomo inteiro.
nome do átomo da cadeia de caracteres Um nome de átomo de cadeia de caracteres. Usado para adicionar um nome de átomo de cadeia de caracteres a uma tabela de átomos e receber um átomo em troca.