Informacje o tabelach Atom
tablica atomów to tabela zdefiniowana przez system, która przechowuje ciągi i odpowiadające im identyfikatory. Aplikacja umieszcza ciąg w tabeli atomów i otrzymuje 16-bitową liczbę całkowitą o nazwie atom, która może służyć do uzyskiwania dostępu do ciągu. Ciąg umieszczony w tabeli atomów jest nazywany nazwą atomu .
System udostępnia wiele tabel atomów. Każda tabela atomów służy innemu celowi. Na przykład aplikacje dynamicznej wymiany danych (DDE) używają globalnej tabeli atomów do udostępniania ciągów nazw elementów i nazw tematów innym aplikacjom. Zamiast przekazywać rzeczywiste ciągi znaków, aplikacja DDE przekazuje atomy globalne do aplikacji partnera. Partner używa atomów do uzyskania ciągów z tabeli atomów.
Aplikacje mogą używać lokalnych tabel atomów do przechowywania własnych skojarzeń nazw elementów.
System używa tabel atomów, które nie są bezpośrednio dostępne dla aplikacji. Jednak aplikacja używa tych atomów podczas wywoływania różnych funkcji. Na przykład zarejestrowane formaty schowka są przechowywane w wewnętrznej tabeli atomów używanej przez system. Aplikacja dodaje atomy do tej tabeli atomów przy użyciu funkcji RegisterClipboardFormat. Ponadto zarejestrowane klasy są przechowywane w wewnętrznej tabeli atomów używanej przez system. Aplikacja dodaje atomy do tej tabeli atomów przy użyciu funkcji RegisterClass lub RegisterClassEx.
W tej sekcji omówiono następujące tematy.
- Globalna Tabela Atom
- Tabela Atomów Użytkownika
- Lokalnych Tabel Atomów
- typy atomów
- Tworzenie i Liczba Użycia Atomów
- Atom-Table zapytań
- formaty atomowych łańcuchów
Globalna tabela atomów
Globalna tabela atomów jest dostępna dla wszystkich aplikacji. Gdy aplikacja umieszcza ciąg w globalnej tabeli atomów, system generuje atom, który jest unikatowy w całym systemie. Każda aplikacja, która ma atom, może uzyskać ciąg, który identyfikuje, wykonując zapytanie względem globalnej tabeli atomów.
Aplikacja, która definiuje prywatny format danych DDE do udostępniania danych innym aplikacjom, powinna umieścić nazwę formatu w globalnej tabeli atomów. Ta technika zapobiega konfliktom z nazwami formatów zdefiniowanych przez system lub przez inne aplikacje oraz udostępnia identyfikatory (atomy) dla komunikatów lub formatów dostępnych dla innych aplikacji.
Tabela Atom użytkownika
Oprócz globalnej tabeli atomów tabela atomów użytkownika jest kolejną tabelą atomów systemowych, która jest również współdzielona we wszystkich procesach. Tabela atomów użytkownika jest używana dla niewielkiej liczby scenariuszy wewnętrznych w win32k; na przykład, nazwy modułów systemu Windows, dobrze znane ciągi w win32k, formaty OLE itp. Mimo że aplikacje nie współdziałają bezpośrednio z tabelą atomów użytkownika, wywołują kilka interfejsów API, takich jak RegisterClass, RegisterWindowMessagei RegisterClipboardFormat— które dodają wpisy do tabeli atomów użytkownika. Wpisy dodane przez RegisterClass
można usunąć za pomocą UnregisterClass
. Jednak wpisy dodane przez RegisterWindowMessage
i RegisterClipboardFormat
nie zostaną usunięte do momentu zakończenia sesji. Jeśli tabela atomów użytkownika nie ma więcej miejsca, a przekazywany ciąg nie znajduje się jeszcze w tabeli, wywołanie zakończy się niepowodzeniem.
Rozmiar tabeli Atom
Wiele krytycznych interfejsów API, w tym CreateWindow, polega na atomach użytkownika. W związku z tym wyczerpanie miejsca w tabeli atomów użytkownika spowoduje poważne problemy; na przykład uruchomienie wszystkich aplikacji może zakończyć się niepowodzeniem. Poniżej przedstawiono kilka zaleceń, aby zapewnić, że aplikacja efektywnie wykorzystuje tabele atomów i zachowuje niezawodność i wydajność aplikacji i systemu:
Należy ograniczyć użycie tabeli atomów użytkownika przez aplikację. Przechowywanie unikatowych ciągów przy użyciu interfejsów API, takich jak
RegisterClass
,RegisterWindowMessage
lubRegisterClipboardFormat
zajmuje miejsce w tabeli atomów użytkownika, która jest używana globalnie przez inne aplikacje do rejestrowania klas okien przy użyciu ciągów. Jeśli w ogóle jest to możliwe, należy użyć AddAtom/DeleteAtom do przechowywania ciągów w lokalnej tabeli atomów lub GlobalAddAtom/GlobalDeleteAtom, jeśli atomy są potrzebne między procesami.Jeśli występują obawy dotyczące aplikacji powodującej problemy z tabelą atomów użytkownika, możesz zbadać główną przyczynę, łącząc się z debugerem jądra i przerywając proces podczas wywołań
UserAddAtomEx
(bae1 win32kbase!UserAddAtomEx /p <eprocess> "kc10;g"
). Poszukajuser32!
na stosie wywołań, aby sprawdzić, które API jest używane. Metodologia jest podobna do wykrywania problemów z globalną tabelą atomów, co jest wyjaśnione w Identyfikowanie globalnych przecieków tabel atomów. Innym sposobem zrzutu danych z tabeli atomów użytkownika jest wywołanie funkcji GetClipboardFormatName dla zakresu atomów od 0xC000 do 0xFFFF. Jeśli łączna liczba atomów stale rośnie, gdy aplikacja jest uruchomiona lub nie wraca do punktu odniesienia po zamknięciu aplikacji, występuje problem.
Lokalne tabele atomów
Aplikacja może używać lokalnej tabeli atomów do wydajnego zarządzania dużą liczbą ciągów używanych tylko w aplikacji. Te ciągi i skojarzone atomy są dostępne tylko dla aplikacji, która utworzyła tabelę.
Aplikacja wymagająca tego samego ciągu w wielu strukturach może zmniejszyć użycie pamięci przy użyciu lokalnej tabeli atomów. Zamiast kopiować ciąg do każdej struktury, aplikacja może umieścić ciąg w tabeli atomów i dołączyć wynikowy atom do struktur. W ten sposób ciąg jest wyświetlany tylko raz w pamięci, ale może być używany wiele razy w aplikacji.
Aplikacje mogą również używać lokalnych tabel atomów, aby zaoszczędzić czas podczas wyszukiwania określonego ciągu. Aby przeprowadzić wyszukiwanie, aplikacja musi umieścić tylko ciąg wyszukiwania w tabeli atomów i porównać wynikowy atom z atomami w odpowiednich strukturach. Porównywanie atomów jest zwykle szybsze niż porównywanie ciągów.
Tabele atomów są implementowane jako tabele skrótów. Domyślnie lokalna tabela atomów używa 37 kubełków dla swojej tabeli skrótów. Można jednak zmienić liczbę zasobników używanych przez wywołanie funkcji InitAtomTable. Jeśli aplikacja wywołuje InitAtomTable, należy to jednakże zrobić przed wywołaniem jakichkolwiek innych funkcji zarządzania atomami.
Typy atomów
Aplikacje mogą tworzyć dwa typy atomów: atomy ciągów i atomy całkowite. Wartości atomów całkowitych i atomów ciągów nie nakładają się, więc oba typy atomów mogą być używane w tym samym bloku kodu.
Kilka funkcji akceptuje ciągi lub atomy jako parametry. Podczas przekazywania atomu do tych funkcji aplikacja może użyć makra MAKEINTATOM, aby przekonwertować atom na formę, która może być używana przez funkcję.
W poniższych sekcjach opisano typy atomów.
Atomy ciągów
Gdy aplikacje przekazują ciągi zakończone wartością null do funkcji GlobalAddAtom, AddAtom, GlobalFindAtomoraz FindAtom, odbierają atomy ciągów (16-bitowe liczby całkowite). Atomy ciągów mają następujące właściwości:
- Wartości atomów ciągów mieszczą się w zakresie od 0xC000 (MAXINTATOM) do 0xFFFF.
- Wielkość liter nie jest znacząca w wyszukiwaniu nazwy atomu w tabeli atomów. Ponadto cały ciąg musi być zgodny w operacji wyszukiwania; nie jest wykonywane dopasowywanie podciągów.
- Ciąg skojarzony z atomem ciągu może mieć rozmiar nie większy niż 255 bajtów. To ograniczenie dotyczy wszystkich funkcji atomów.
- Licznik referencji jest skojarzony z każdą nazwą atomu. Liczba jest zwiększana za każdym razem, gdy nazwa atomu jest dodawana do tabeli i dekrementowana za każdym razem, gdy nazwa atomu zostanie usunięta z niej. Uniemożliwia to różnym użytkownikom tego samego ciągu atomu niszczenie nazw atomów. Gdy liczba odwołań dla nazwy atomu jest równa zero, system usuwa atom i nazwę atomu z tabeli.
Atomy liczb całkowitych
Atomy liczb całkowitych różnią się od atomów ciągów na następujące sposoby:
- Wartości atomów całkowitych znajdują się w zakresie 0x0001 przez 0xBFFF (MAXINTATOM– 1).
- Reprezentacja ciągu atomu całkowitego to #dddd, gdzie wartości reprezentowane przez ddddd są cyframi dziesiętnymi. Pomijane są zera wiodące.
- Brak liczby odwołań ani obciążenia magazynu skojarzonego z atomem liczb całkowitych.
Tworzenie i liczba użycia atomów
Aplikacja tworzy lokalny atom, wywołując funkcję AddAtom; tworzy globalny atom, wywołując funkcję GlobalAddAtom. Obie funkcje wymagają wskaźnika do ciągu. System przeszukuje odpowiednią tabelę atomów dla ciągu i zwraca odpowiedni atom do aplikacji. W przypadku atomu ciągu, jeśli ciąg znajduje się już w tabeli atomów, system zwiększa liczbę odwołań dla ciągu podczas tego procesu.
Powtórzone wywołania w celu dodania tej samej nazwy atomu zwracają ten sam atom. Jeśli nazwa atomu nie istnieje w tabeli po wywołaniu AddAtom, nazwa atomu zostanie dodana do tabeli i zostanie zwrócony nowy atom. Jeśli jest to atom ciągu, jego liczba odwołań jest również ustawiona na jeden.
Aplikacja powinna wywoływać funkcję DeleteAtom, gdy nie musi już używać lokalnego atomu; powinien wywołać funkcję GlobalDeleteAtom, gdy nie potrzebuje już globalnego atomu. W przypadku atomu ciągu jedna z tych funkcji zmniejsza liczbę odwołań odpowiedniego atomu o jeden. Gdy liczba odwołań osiągnie zero, system usuwa nazwę atomu z tabeli.
Nazwa atomu dla atomu ciągu pozostaje w globalnej tabeli atomów, dopóki liczba jego odwołań jest większa niż zero, nawet po zakończeniu działania aplikacji, która umieściła go w tabeli. Lokalna tabela atomów jest usuwana, gdy skojarzona aplikacja zakończy działanie, niezależnie od liczby referencji atomów w tabeli.
zapytania Atom-Table
Aplikacja może określić, czy określony ciąg znajduje się już w tabeli atomów, używając funkcji FindAtom lub GlobalFindAtom. Te funkcje wyszukują tabelę atomów dla określonego ciągu i, jeśli tam znajduje się ciąg, zwracają odpowiedni atom.
Aplikacja może użyć funkcji GetAtomName lub GlobalGetAtomName, aby pobrać ciąg nazwy atomu z tabeli atomów, pod warunkiem że aplikacja ma atom odpowiadający poszukiwanym ciągowi. Obie funkcje kopiują ciąg atom-name określonego atomu do buforu i zwracają długość skopiowanego ciągu. GetAtomName pobiera ciąg atom-name z lokalnej tabeli atomów, a GlobalGetAtomName pobiera ciąg atom-name z globalnej tabeli atomów.
Formaty ciągów atomów
Funkcje AddAtom, GlobalAddAtom, FindAtomi GlobalFindAtom przyjmują wskaźnik do ciągu zakończonego wartością null. Aplikacja może określić ten wskaźnik na jeden z następujących sposobów.
Format ciągu | Opis |
---|---|
# dddd | Liczba całkowita określona jako ciąg dziesiętny. Służy do tworzenia lub znajdowania atomu całkowitego. |
nazwa ciągu atomu | Nazwa atomu ciągu znaków. Służy do dodawania nazwy atomu ciągu do tabeli atomów i odbierania atomu w zamian. |