Acerca de las tablas atom

Una tabla atom es una tabla definida por el sistema que almacena cadenas e identificadores correspondientes. Una aplicación coloca una cadena en una tabla atom y recibe un entero de 16 bits, denominado atom, que se puede usar para tener acceso a la cadena. Una cadena que se ha colocado en una tabla atom se denomina nombre atom.

El sistema proporciona una serie de tablas atom. Cada tabla atom tiene un propósito diferente. Por ejemplo, las aplicaciones de Intercambio dinámico de datos (DDE) usan la tabla atom global para compartir cadenas de nombre de elemento y nombre de tema con otras aplicaciones. En lugar de pasar cadenas reales, una aplicación DDE pasa átomos globales a su aplicación asociada. El asociado usa los átomos para obtener las cadenas de la tabla atom.

Las aplicaciones pueden usar tablas atom locales para almacenar sus propias asociaciones de nombre de elemento.

El sistema usa tablas atom que no son directamente accesibles para las aplicaciones. Sin embargo, la aplicación usa estos átomos al llamar a una variedad de funciones. Por ejemplo, los formatos del Portapapeles registrados se almacenan en una tabla atom interna utilizada por el sistema. Una aplicación agrega átomos a esta tabla atom mediante la función RegisterClipboardFormat . Además, las clases registradas se almacenan en una tabla atom interna utilizada por el sistema. Una aplicación agrega átomos a esta tabla atom mediante la función RegisterClass o RegisterClassEx .

En esta sección se tratan los temas siguientes.

Tabla Atom global

La tabla atom global está disponible para todas las aplicaciones. Cuando una aplicación coloca una cadena en la tabla atom global, el sistema genera un átomo que es único en todo el sistema. Cualquier aplicación que tenga el átomo puede obtener la cadena que identifica consultando la tabla atom global.

Una aplicación que define un formato de datos DDE privado para compartir datos con otras aplicaciones debe colocar el nombre de formato en la tabla atom global. Esta técnica evita conflictos con los nombres de los formatos definidos por el sistema o por otras aplicaciones, y hace que los identificadores (átomos) de los mensajes o formatos estén disponibles para las demás aplicaciones.

Tabla Atom de usuario

Además de la tabla atom global, la tabla atom del usuario es otra tabla atom del sistema que también se comparte en todos los procesos. La tabla atom del usuario se usa para un pequeño número de escenarios internos a win32k; por ejemplo, nombres de módulo de Windows, cadenas conocidas en win32k, formatos OLE, etc. Aunque las aplicaciones no interactúan directamente con la tabla atom del usuario, llaman a varias API,como RegisterClass, RegisterWindowMessage y RegisterClipboardFormat, que agregan entradas a la tabla atom del usuario. Las entradas agregadas por RegisterClass se pueden eliminar mediante UnregisterClass. Sin embargo, las entradas agregadas por RegisterWindowMessage y RegisterClipboardFormat no se eliminan hasta que finaliza la sesión. Si la tabla atom del usuario no tiene más espacio y la cadena que se pasa aún no está en la tabla, se producirá un error en la llamada.

Tamaño de tabla atom

Muchas API críticas, como CreateWindow, dependen de átomos de usuario. Por lo tanto, el agotamiento del espacio en la tabla atom del usuario dará lugar a problemas graves; por ejemplo, es posible que todas las aplicaciones no se inicien. Estas son algunas recomendaciones para asegurarse de que la aplicación utiliza tablas atom de forma eficaz y conserva la confiabilidad y el rendimiento de la aplicación y el sistema:

  1. Debes limitar el uso de la aplicación de la tabla atom del usuario. El almacenamiento de cadenas únicas mediante API como RegisterClass, RegisterWindowMessageo RegisterClipboardFormat toma espacio en la tabla atom del usuario, que otras aplicaciones usan globalmente para registrar clases de ventana mediante cadenas. Si es posible, debe usar AddAtom/DeleteAtom para almacenar cadenas en una tabla atom local o GlobalAddAtom/GlobalDeleteAtom si los átomos son necesarios entre procesos.

  2. Si hay alguna preocupación sobre la aplicación que provoca problemas de tabla atom del usuario, puede investigar la causa principal mediante la conexión del depurador de kernel y la separación en el proceso en las llamadas a UserAddAtomEx (bae1 win32kbase!UserAddAtomEx /p <eprocess> "kc10;g"). user32! Busque en la pila de llamadas para ver a qué API se llama. La metodología es similar a la detección de problemas de la tabla atom global que se explica en Identificación de fugas de tabla atom global. Otra manera de volcar el contenido de la tabla atom del usuario es llamar a GetClipboardFormatName en el intervalo de posibles átomos de 0xC000 a 0xFFFF. Si el número total de átomos aumenta constantemente mientras se ejecuta la aplicación o no vuelve a la línea base cuando se cierra la aplicación, hay un problema.

Tablas atom locales

Una aplicación puede usar una tabla atom local para administrar eficazmente un gran número de cadenas que solo se usan dentro de la aplicación. Estas cadenas y los átomos asociados solo están disponibles para la aplicación que creó la tabla.

Una aplicación que requiera la misma cadena en una serie de estructuras puede reducir el uso de memoria mediante una tabla atom local. En lugar de copiar la cadena en cada estructura, la aplicación puede colocar la cadena en la tabla atom e incluir el átomo resultante en las estructuras. De esta manera, una cadena solo aparece una vez en memoria, pero se puede usar muchas veces en la aplicación.

Las aplicaciones también pueden usar tablas atom locales para ahorrar tiempo al buscar una cadena determinada. Para realizar una búsqueda, una aplicación solo necesita colocar la cadena de búsqueda en la tabla atom y comparar el átomo resultante con los átomos de las estructuras pertinentes. La comparación de átomos suele ser más rápida que la comparación de cadenas.

Las tablas Atom se implementan como tablas hash. De forma predeterminada, una tabla atom local usa 37 cubos para su tabla hash. Sin embargo, puede cambiar el número de cubos usados mediante una llamada a la función InitAtomTable . Sin embargo, si la aplicación llama a InitAtomTable, debe hacerlo antes de llamar a cualquier otra función de administración de atom.

Tipos atom

Las aplicaciones pueden crear dos tipos de átomos: átomos de cadena y átomos enteros. Los valores de átomos enteros y átomos de cadena no se superponen, por lo que ambos tipos de átomos se pueden usar en el mismo bloque de código.

Varias funciones aceptan cadenas o átomos como parámetros. Al pasar un átomo a estas funciones, una aplicación puede usar la macro MAKEINTATOM para convertir el átomo en un formulario que la función puede usar.

En las secciones siguientes se describen los tipos de átomos.

Átomos de cadena

Cuando las aplicaciones pasan cadenas terminadas en null a las funciones GlobalAddAtom, AddAtom, GlobalFindAtom y FindAtom , reciben átomos de cadena (enteros de 16 bits) a cambio. Los átomos de cadena tienen las siguientes propiedades:

  • Los valores de átomos de cadena se encuentran en el intervalo 0xC000 (MAXINTATOM) a través de 0xFFFF.
  • El caso no es significativo en las búsquedas de un nombre de átomo en una tabla atom. Además, toda la cadena debe coincidir en una operación de búsqueda; no se realiza ninguna coincidencia de subcadena.
  • La cadena asociada a un átomo de cadena no puede tener más de 255 bytes de tamaño. Esta limitación se aplica a todas las funciones atom.
  • Un recuento de referencias está asociado a cada nombre de átomo. El recuento se incrementa cada vez que el nombre del átomo se agrega a la tabla y disminuye cada vez que se elimina el nombre del átomo. Esto impide que distintos usuarios del mismo átomo de cadena destruyan los nombres de átomos entre sí. Cuando el recuento de referencias de un nombre de átomo es igual a cero, el sistema quita el átomo y el nombre del átomo de la tabla.

Átomos enteros

Los átomos enteros difieren de los átomos de cadena de las siguientes maneras:

  • Los valores de átomos enteros están en el intervalo 0x0001 a través de 0xBFFF (MAXINTATOM– 1).
  • La representación de cadena de un átomo entero es #dddd, donde los valores representados por dddd son dígitos decimales. Se omiten los ceros iniciales.
  • No hay ningún recuento de referencias ni sobrecarga de almacenamiento asociada a un átomo entero.

Recuento de uso y creación de Atom

Una aplicación crea un átomo local llamando a la función AddAtom ; crea un átomo global llamando a la función GlobalAddAtom . Ambas funciones requieren un puntero a una cadena. El sistema busca en la tabla atom adecuada la cadena y devuelve el átomo correspondiente a la aplicación. En el caso de un átomo de cadena, si la cadena ya reside en la tabla atom, el sistema incrementa el recuento de referencias de la cadena durante este proceso.

Las llamadas repetidas para agregar el mismo nombre atom devuelven el mismo átomo. Si el nombre del átomo no existe en la tabla cuando se llama a AddAtom , el nombre del átomo se agrega a la tabla y se devuelve un nuevo átomo. Si es un átomo de cadena, su recuento de referencias también se establece en uno.

Una aplicación debe llamar a la función DeleteAtom cuando ya no necesite usar un átomo local; debe llamar a la función GlobalDeleteAtom cuando ya no necesite un átomo global. En el caso de un átomo de cadena, cualquiera de estas funciones reduce el recuento de referencias del átomo correspondiente en uno. Cuando el recuento de referencias alcanza cero, el sistema elimina el nombre del átomo de la tabla.

El nombre del átomo de un átomo de cadena permanece en la tabla de átomos globales siempre que su recuento de referencias sea mayor que cero, incluso después de que finalice la aplicación que lo colocó en la tabla. Una tabla de átomos local se destruye cuando finaliza la aplicación asociada, independientemente de los recuentos de referencia de los átomos de la tabla.

consultas de Atom-Table

Una aplicación puede determinar si una cadena determinada ya está en una tabla atom mediante la función FindAtom o GlobalFindAtom . Estas funciones buscan una tabla atom para la cadena especificada y, si la cadena está allí, devuelve el átomo correspondiente.

Una aplicación puede usar la función GetAtomName o GlobalGetAtomName para recuperar una cadena atom-name de una tabla atom, siempre que la aplicación tenga el átomo correspondiente a la cadena que se busca. Ambas funciones copian la cadena atom-name del átomo especificado en un búfer y devuelven la longitud de la cadena que se copió. GetAtomName recupera una cadena atom-name de una tabla atom local y GlobalGetAtomName recupera una cadena atom-name de la tabla atom.

Formatos de cadena Atom

Las funciones AddAtom, GlobalAddAtom, FindAtom y GlobalFindAtom toman un puntero a una cadena terminada en null. Una aplicación puede especificar este puntero de una de las maneras siguientes.

Formato de cadena Descripción
# Dddd Entero especificado como una cadena decimal. Se usa para crear o buscar un átomo entero.
nombre del átomo de cadena Nombre del átomo de cadena. Se usa para agregar un nombre de átomo de cadena a una tabla atom y recibir un átomo a cambio.