Informazioni sulle tabelle Atom

Una tabella atom è una tabella definita dal sistema che archivia stringhe e identificatori corrispondenti. Un'applicazione inserisce una stringa in una tabella atom e riceve un intero a 16 bit, denominato atom, che può essere usato per accedere alla stringa. Una stringa inserita in una tabella atom è denominata nome atom.

Il sistema fornisce una serie di tabelle atom. Ogni tabella atom ha uno scopo diverso. Ad esempio, le applicazioni DDE (Dynamic Data Exchange) usano la tabella atom globale per condividere stringhe nome-elemento e nome-argomento con altre applicazioni. Invece di passare stringhe effettive, un'applicazione DDE passa atom globali all'applicazione partner. Il partner usa gli atomi per ottenere le stringhe dalla tabella atom.

Le applicazioni possono usare tabelle atom locali per archiviare le proprie associazioni di nomi di elemento.

Il sistema usa tabelle atom che non sono direttamente accessibili alle applicazioni. Tuttavia, l'applicazione usa questi atomi quando si chiama un'ampia gamma di funzioni. Ad esempio, i formati degli Appunti registrati vengono archiviati in una tabella atom interna usata dal sistema. Un'applicazione aggiunge atomi a questa tabella atom usando la funzione RegisterClipboardFormat. Inoltre, le classi registrate vengono archiviate in una tabella atom interna usata dal sistema. Un'applicazione aggiunge atom a questa tabella atom usando la funzione RegisterClass o RegisterClassEx.

In questa sezione vengono illustrati gli argomenti seguenti.

Tabella Atom globale

La tabella atom globale è disponibile per tutte le applicazioni. Quando un'applicazione inserisce una stringa nella tabella atom globale, il sistema genera un atomo univoco in tutto il sistema. Qualsiasi applicazione con l'atom può ottenere la stringa identificata eseguendo una query sulla tabella atom globale.

Un'applicazione che definisce un formato di dati DDE privato per la condivisione di dati con altre applicazioni deve inserire il nome di formato nella tabella atom globale. Questa tecnica impedisce conflitti con i nomi dei formati definiti dal sistema o da altre applicazioni e rende gli identificatori (atom) per i messaggi o i formati disponibili per le altre applicazioni.

Tabella User Atom

Oltre alla tabella atom globale, la tabella atom utente è un'altra tabella atom di sistema condivisa anche in tutti i processi. La tabella atom utente viene usata per un numero ridotto di scenari interni a win32k; ad esempio, nomi di moduli di Windows, stringhe note in win32k, formati OLE e così via. Anche se le applicazioni non interagiscono direttamente con la tabella atom dell'utente, chiamano diverse API, ad esempio RegisterClass, RegisterWindowMessage e RegisterClipboardFormat, che aggiungono voci alla tabella atom dell'utente. Le voci aggiunte da RegisterClass possono essere eliminate da UnregisterClass. Tuttavia, le voci aggiunte da RegisterWindowMessage e RegisterClipboardFormat non vengono eliminate fino al termine della sessione. Se la tabella atom dell'utente non ha più spazio e la stringa passata non è già presente nella tabella, la chiamata avrà esito negativo.

Dimensioni tabella Atom

Molte API critiche, tra cui CreateWindow, si basano su atom utente. Pertanto, l'esaurimento dello spazio nella tabella atom dell'utente causerà gravi problemi; ad esempio, l'avvio di tutte le applicazioni potrebbe non riuscire. Ecco alcuni consigli per garantire che l'applicazione usi tabelle atom in modo efficiente e mantenga l'affidabilità e le prestazioni dell'applicazione e del sistema:

  1. È consigliabile limitare l'utilizzo dell'app della tabella atom dell'utente. L'archiviazione di stringhe univoche tramite API come RegisterClass, RegisterWindowMessageo RegisterClipboardFormat occupa spazio nella tabella atom dell'utente, usata a livello globale da altre app per registrare classi di finestre usando stringhe. Se possibile, è consigliabile usare AddAtom/DeleteAtom per archiviare stringhe in una tabella atom locale o GlobalAddAtom/GlobalDeleteAtom se sono necessari processi incrociati.

  2. Se l'applicazione causa problemi relativi alla tabella atom dell'utente, è possibile esaminare la causa radice connettendo il debugger del kernel e interrompendo il processo nelle chiamate a UserAddAtomEx (bae1 win32kbase!UserAddAtomEx /p <eprocess> "kc10;g"). user32! Cercare nello stack di chiamate per vedere quale API viene chiamata. La metodologia è simile al rilevamento dei problemi di tabella atom globale illustrato in Identificazione delle perdite di tabelle Atom globali. Un altro modo per eseguire il dump del contenuto della tabella atom dell'utente consiste nel chiamare GetClipboardFormatName sull'intervallo di atomi possibili da 0xC000 a 0xFFFF. Se il conteggio totale atom aumenta costantemente mentre l'applicazione è in esecuzione o non torna alla linea di base quando l'app viene chiusa, si verifica un problema.

Tabelle Atom locali

Un'applicazione può usare una tabella atom locale per gestire in modo efficiente un numero elevato di stringhe usate solo all'interno dell'applicazione. Queste stringhe e gli atom associati sono disponibili solo per l'applicazione che ha creato la tabella.

Un'applicazione che richiede la stessa stringa in una serie di strutture può ridurre l'utilizzo della memoria usando una tabella atom locale. Anziché copiare la stringa in ogni struttura, l'applicazione può inserire la stringa nella tabella atom e includere l'atomo risultante nelle strutture. In questo modo, una stringa viene visualizzata una sola volta in memoria, ma può essere usata molte volte nell'applicazione.

Le applicazioni possono anche usare tabelle atom locali per risparmiare tempo durante la ricerca di una determinata stringa. Per eseguire una ricerca, un'applicazione deve inserire solo la stringa di ricerca nella tabella atom e confrontare l'atomo risultante con gli atomi nelle strutture pertinenti. Il confronto degli atomi è in genere più veloce rispetto al confronto delle stringhe.

Le tabelle Atom vengono implementate come tabelle hash. Per impostazione predefinita, una tabella atom locale usa 37 bucket per la tabella hash. È tuttavia possibile modificare il numero di bucket usati chiamando la funzione InitAtomTable. Se l'applicazione chiama InitAtomTable, tuttavia, deve farlo prima di chiamare qualsiasi altra funzione di gestione atom.

Tipi atom

Le applicazioni possono creare due tipi di atomi: atomi di stringa e atomi interi. I valori degli atomi interi e degli atomi di stringa non si sovrappongono, quindi entrambi i tipi di atomi possono essere usati nello stesso blocco di codice.

Diverse funzioni accettano stringhe o atomi come parametri. Quando si passa un atomo a queste funzioni, un'applicazione può utilizzare la macro MAKEINTATOM per convertire l'atomo in una maschera che può essere utilizzata dalla funzione .

Le sezioni seguenti descrivono i tipi atom.

Atom di stringa

Quando le applicazioni passano stringhe con terminazione Null alle funzioni GlobalAddAtom, AddAtom, GlobalFindAtom e FindAtom, ricevono atomi di stringa (interi a 16 bit) in restituzione. Gli atomi di stringa hanno le proprietà seguenti:

  • I valori degli atomi di stringa si trovano nell'intervallo 0xC000 (MAXINTATOM) tramite 0xFFFF.
  • La distinzione tra maiuscole e minuscole non è significativa nelle ricerche di un nome atom in una tabella atom. Inoltre, l'intera stringa deve corrispondere in un'operazione di ricerca; non viene eseguita alcuna corrispondenza di sottostringa.
  • La stringa associata a un atomo di stringa non può essere maggiore di 255 byte. Questa limitazione si applica a tutte le funzioni atom.
  • Un conteggio dei riferimenti è associato a ogni nome atom. Il conteggio viene incrementato ogni volta che il nome atomo viene aggiunto alla tabella e decrementato ogni volta che il nome dell'atomo viene eliminato. Ciò impedisce a utenti diversi dello stesso atomo di stringa di distruggere i nomi atom dell'altro. Quando il conteggio dei riferimenti per un nome atom è uguale a zero, il sistema rimuove l'atomo e il nome dell'atomo dalla tabella.

Atom interi

Gli atomi interi differiscono dagli atomi di stringa nei modi seguenti:

  • I valori degli atomi interi si trovano nell'intervallo 0x0001 attraverso 0xBFFF (MAXINTATOM– 1).
  • La rappresentazione di stringa di un atomo intero è #dddd, dove i valori rappresentati da dddd sono cifre decimali. Gli zeri iniziali vengono ignorati.
  • Nessun conteggio dei riferimenti o sovraccarico di archiviazione associato a un atomo intero.

Creazione e conteggio utilizzo atom

Un'applicazione crea un atomo locale chiamando la funzione AddAtom. Crea un atomo globale chiamando la funzione GlobalAddAtom. Entrambe le funzioni richiedono un puntatore a una stringa. Il sistema cerca nella tabella atom appropriata la stringa e restituisce l'atom corrispondente all'applicazione. Nel caso di un atomo di stringa, se la stringa risiede già nella tabella atom, il sistema incrementa il conteggio dei riferimenti per la stringa durante questo processo.

Le chiamate ripetute per aggiungere lo stesso nome atom restituiscono lo stesso atomo. Se il nome atom non esiste nella tabella quando viene chiamato AddAtom , il nome atom viene aggiunto alla tabella e viene restituito un nuovo atom. Se si tratta di un atomo di stringa, anche il conteggio dei riferimenti viene impostato su uno.

Un'applicazione deve chiamare la funzione DeleteAtom quando non deve più usare un atomo locale. Deve chiamare la funzione GlobalDeleteAtom quando non ha più bisogno di un atomo globale. Nel caso di un atomo di stringa, una di queste funzioni riduce il numero di riferimenti dell'atomo corrispondente di uno. Quando il conteggio dei riferimenti raggiunge zero, il sistema elimina il nome atomo dalla tabella.

Il nome atom di un atomo di stringa rimane nella tabella atom globale, purché il numero di riferimenti sia maggiore di zero, anche dopo che l'applicazione che l'ha inserita nella tabella termina. Una tabella atom locale viene eliminata definitivamente quando l'applicazione associata termina, indipendentemente dal numero di riferimenti degli atomi nella tabella.

Query atom-table

Un'applicazione può determinare se una determinata stringa si trova già in una tabella atom usando la funzione FindAtom o GlobalFindAtom. Queste funzioni cercano una tabella atom per la stringa specificata e, se la stringa è presente, restituiscono l'atom corrispondente.

Un'applicazione può usare la funzione GetAtomName o GlobalGetAtomName per recuperare una stringa atom-name da una tabella atom, purché l'applicazione abbia l'atom corrispondente alla stringa ricercata. Entrambe le funzioni copiano la stringa atom-name dell'atom specificato in un buffer e restituiscono la lunghezza della stringa copiata. GetAtomName recupera una stringa atom-name da una tabella atom locale e GlobalGetAtomName recupera una stringa atom-name dalla tabella atom globale.

Formati di stringa Atom

Le funzioni AddAtom, GlobalAddAtom, FindAtom e GlobalFindAtom accettano un puntatore a una stringa con terminazione Null. Un'applicazione può specificare questo puntatore in uno dei modi seguenti.

Formato stringa Descrizione
#dddd Intero specificato come stringa decimale. Usato per creare o trovare un atomo intero.
nome atom di stringa Nome atom di stringa. Usato per aggiungere un nome atom di stringa a una tabella atom e ricevere un atomo in cambio.