O tabulkách Atom
Tabulka atomů je systémově definovaná tabulka, která uchovává řetězce a odpovídající identifikátory. Aplikace umístí řetězec do tabulky atomů a přijme 16bitové celé číslo označované jako atom, které lze použít pro přístup k řetězci. Řetězec umístěný v tabulce atomů se nazývá název atomu.
Systém poskytuje řadu tabulek atomů. Každá tabulka atomů slouží k jinému účelu. Aplikace DDE (Dynamic Data Exchange) například používají globální tabulku atomů ke sdílení řetězců názvu položky a názvu tématu s jinými aplikacemi. Místo předávání skutečných řetězců předá aplikace DDE globální atomy do své partnerské aplikace. Partner používá atomy k získání řetězců z tabulky atomů.
Aplikace můžou k ukládání vlastních přidružení názvů položek použít místní tabulky atomů.
Systém používá tabulky atomů, které nejsou přímo přístupné pro aplikace. Aplikace však tyto atomy používá při volání různých funkcí. Například registrované formáty schránky jsou uloženy v interní atomové tabulce používané systémem. Aplikace přidá do této tabulky atomů atomy pomocí funkce RegisterClipboardFormat. Zaregistrované třídy jsou také uloženy v interní tabulce atomů používané systémem. Aplikace přidá do této tabulky atomů atomy pomocí funkce RegisterClass nebo RegisterClassEx.
V této části jsou popsána následující témata.
- globální tabulka atomů
- tabulka atomů uživatele
- Lokální Atomové Tabulky
- typy atomů
- Vytváření atomů a počet využití
- Dotazy Atom-Table
- Formáty řetězců v atomovém formátu
Globální tabulka atomů
Globální tabulka atomů je k dispozici pro všechny aplikace. Když aplikace umístí řetězec do globální tabulky atomů, systém vygeneruje atom, který je jedinečný v celém systému. Každá aplikace, která obsahuje atom, může získat řetězec, který identifikuje dotazem na globální tabulku atomů.
Aplikace, která definuje privátní formát dat DDE pro sdílení dat s jinými aplikacemi, by měla umístit název formátu do globální tabulky atomů. Tato technika zabraňuje konfliktům s názvy formátů definovaných systémem nebo jinými aplikacemi a zpřístupňuje identifikátory (atomy) pro zprávy nebo formáty ostatním aplikacím.
Tabulka Atom uživatele
Kromě globální tabulky atomů je uživatelská tabulka atomů další systémová tabulka atomů, která je také sdílena napříč všemi procesy. Tabulka atomů uživatele se používá pro malý počet scénářů interních pro win32k; Například názvy modulů windows, dobře známé řetězce v win32k, formáty OLE atd. I když aplikace přímo nekomuagují s tabulkou atomů uživatele, volají několik rozhraní API– například RegisterClass, RegisterWindowMessagea RegisterClipboardFormat– které přidávají položky do tabulky atom uživatele. Položky přidané RegisterClass
lze odstranit pomocí UnregisterClass
. Položky přidané pomocí RegisterWindowMessage
a RegisterClipboardFormat
se však neodstraní, dokud relace neskončí. Pokud tabulka atomů uživatele nemá více místa a řetězec předaný ještě není v tabulce, volání selže.
Velikost tabulky Atom
Řada důležitých rozhraní API, včetně CreateWindow, spoléhá na atomy uživatelů. Proto vyčerpání místa v tabulce atomů uživatele způsobí vážné problémy; Například všechny aplikace se nemusí podařit spustit. Tady je několik doporučení pro efektivní využití tabulek atomů a zachování spolehlivosti a výkonu aplikace a systému:
Měli byste omezit použití vaší aplikace v uživatelské atomové tabulce. Ukládání jedinečných řetězců pomocí rozhraní API, jako jsou
RegisterClass
,RegisterWindowMessage
neboRegisterClipboardFormat
zabírá místo v tabulce atomů uživatele, která se používá globálně jinými aplikacemi k registraci tříd oken pomocí řetězců. Pokud je to možné, měli byste k ukládání řetězců v místní tabulce atomů použít AddAtom/DeleteAtom nebo GlobalAddAtom/GlobalDeleteAtom, pokud jsou atomy potřeba meziprocesově.Pokud jsou obavy, že aplikace způsobuje problémy s tabulkou atomů uživatele, můžete prozkoumat kořenovou příčinu propojením ladicího programu jádra a narušením procesu při voláních na
UserAddAtomEx
(bae1 win32kbase!UserAddAtomEx /p <eprocess> "kc10;g"
). Vyhledejteuser32!
v balíčku volání a zjistěte, které rozhraní API se volá. Metodologie se podobá detekci problému s globální tabulkou atomů vysvětlenou v Identifikace globálních úniků tabulek atomů. Dalším způsobem výpisu obsahu tabulky atomů uživatele je voláním GetClipboardFormatName přes rozsah možných atomů z 0xC000 do 0xFFFF. Pokud se celkový počet atomů neustále zvyšuje během běhu aplikace nebo se po zavření aplikace nevrátí k základní úrovni, je problém.
Místní tabulky atomů
Aplikace může pomocí místní tabulky atomů efektivně spravovat velký počet řetězců používaných pouze v rámci aplikace. Tyto řetězce a přidružené atomy jsou k dispozici pouze pro aplikaci, která tabulku vytvořila.
Aplikace vyžadující stejný řetězec v řadě struktur může snížit využití paměti pomocí místní tabulky atomů. Místo kopírování řetězce do každé struktury může aplikace umístit řetězec do tabulky atomů a zahrnout výsledný atom do struktur. Tímto způsobem se řetězec zobrazí pouze jednou v paměti, ale může být použit mnohokrát v aplikaci.
Aplikace mohou také použít místní tabulky atomů, aby ušetřily čas při hledání konkrétního řetězce. K provedení hledání potřebuje aplikace umístit hledaný řetězec pouze do tabulky atomů a porovnat výsledný atom s atomy v příslušných strukturách. Porovnání atomů je obvykle rychlejší než porovnání řetězců.
Tabulky Atom se implementují jako hashovací tabulky. Ve výchozím nastavení místní tabulka atomů používá pro svou tabulku hash 37 kbelíků. Počet kontejnerů používaných voláním funkce InitAtom Table však můžete změnit. Pokud aplikace volá InitAtomTable, musí to však provést před voláním jiných funkcí správy atomů.
Typy atomů
Aplikace mohou vytvářet dva typy atomů: řetězcové atomy a celočíselné atomy. Hodnoty celočíselných a řetězcových atomů se nepřekrývají, takže oba typy atomů lze použít v tomtéž bloku kódu.
Několik funkcí přijímá jako parametry řetězce nebo atomy. Při předávání atomu těmto funkcím může aplikace použít MAKEINTATOM makro k převodu atomu do formuláře, který může funkce použít.
Následující části popisují typy atomů.
Atomy řetězců
Když aplikace předají řetězce ukončené nulovou hodnotou GlobalAddAtom, AddAtom, GlobalFindAtoma FindAtom, obdrží atomy řetězců (16bitová celá čísla). Atomy řetězců mají následující vlastnosti:
- Hodnoty atomů řetězců jsou v rozsahu 0xC000 (MAXINTATOM) až 0xFFFF.
- Případ není při hledání názvu atomu v tabulce atomů významný. Také celý řetězec se musí shodovat v operaci hledání; neprobíhá žádná shoda podřetězce.
- Řetězec přidružený k atomu řetězce nesmí být větší než 255 bajtů velikosti. Toto omezení platí pro všechny funkce atomu.
- Počet referencí je spojený s každým názvem atomu. Počet se zvýší pokaždé, když se do tabulky přidá název atomu a při každém odstranění názvu atomu se z něj sníží. Tím zabráníte různým uživatelům stejného řetězcového atomu zničit názvy atomů ostatních. Pokud se počet odkazů pro název atomu rovná nule, systém odebere atom a název atomu z tabulky.
Celočíselné atomy
Celočíselné atomy se liší od řetězcových atomů následujícími způsoby:
- Hodnoty celočíselné atomy jsou v rozsahu 0x0001 až 0xBFFF (MAXINTATOM– 1).
- Řetězcová reprezentace celočíselného atomu je #dddd, kde hodnoty reprezentované ddddd jsou desítkové číslice. Úvodní nuly se ignorují.
- K celočíselnému atomu není přidružený žádný počet odkazů ani režijní náklady na úložiště.
Počet vytvoření a využití atomů
Aplikace vytvoří místní atom voláním funkce AddAtom; vytvoří globální atom voláním funkce GlobalAddAtom. Obě funkce vyžadují ukazatel na řetězec. Systém prohledá odpovídající tabulku atomů pro řetězec a vrátí odpovídající atom aplikaci. V případě atomu řetězce, pokud se řetězec již nachází v tabulce atomů, systém zvýší počet odkazů pro řetězec během tohoto procesu.
Opakované volání pro přidání stejného názvu atomu vrátí stejný atom. Pokud název atomu v tabulce neexistuje, když AddAtom je volána, přidá se do tabulky název atomu a vrátí se nový atom. Pokud se jedná o atom řetězce, jeho referenční počet je také nastaven na jeden.
Aplikace by měla volat funkci DeleteAtom, pokud už nepotřebuje používat místní atom; Měla by volat funkci GlobalDeleteAtom, pokud už nepotřebuje globální atom. V případě atomu řetězce některý z těchto funkcí zmenšuje počet odkazů odpovídajícího atomu o jednu. Když počet odkazů dosáhne nuly, systém odstraní název atomu z tabulky.
Název atomu řetězce zůstává v globální tabulce atomů, pokud je jeho referenční počet větší než nula, i když aplikace, která ji umístila do tabulky, ukončí. Místní tabulka atomů je zničena, když se ukončí přidružená aplikace, bez ohledu na referenční počty atomů v tabulce.
Atom-Table Dotazy
Aplikace může určit, zda je konkrétní řetězec již v tabulce atom pomocí funkce FindAtom nebo GlobalFindAtom. Tyto funkce prohledávají v tabulce atomů zadaný řetězec a pokud řetězec existuje, vrátí odpovídající atom.
Aplikace může použít funkci GetAtomName nebo GlobalGetAtomName k načtení řetězce názvu atomu z tabulky atomů za předpokladu, že aplikace má atom odpovídající požadovanému řetězci. Obě funkce zkopírují řetězec názvu určeného atomu do vyrovnávací paměti a vrátí délku zkopírovaného řetězce. GetAtomName načte řetězec názvu atomu z místní tabulky atomů a GlobalGetAtomName načte řetězec názvu atomu z globální tabulky atomů.
Formáty řetězců atomů
Funkce AddAtom, GlobalAddAtom, FindAtoma GlobalFindAtom převezmou ukazatel na řetězec ukončený hodnotou null. Aplikace může tento ukazatel zadat jedním z následujících způsobů.
Formát řetězce | Popis |
---|---|
# dddd | Celé číslo zadané jako desetinný řetězec. Slouží k vytvoření nebo vyhledání celočíselného atomu. |
název řetězce atomu | Atomový název řetězce. Slouží k přidání názvu řetězcového atomu do tabulky atomů a obdržení atomu jako výsledek. |