Portál AbcLinuxu, 7. května 2025 20:27
Aktuální verze jádra: 2.6.30-rc7. Citáty týdne: Al Viro, Andi Kleen, Andrew Morton. V krátkosti: Sjednocené adresáře; Optimalizace časovačů zpětného zápisu; recvmmsg(). Vývojové statistiky 2.6.30. Compcache: Komprimované swapování do paměti. Aktualizovaná příručka debugfs.
Současné vývojové jádro je 2.6.30-rc7 vydané 23. května. Tak se odvažte. Mám podezření, že udělám -rc8, ale rozhodně se blížíme k vydání – bylo by dobré to otestovat, jak nejvíc to půjde, a mělo by být poměrně bezpečné to všechno vyzkoušet. Detaily obsahuje kompletní changelog.
Současné stabilní jádro 2.6 je stále 2.6.29.4; během minulého týdne nebyly vydány žádné stabilní verze.
-- Al Viro
-- Andi Kleen objevil POSIX
-- Andrew Morton se zříká zodpovědnosti
Zatímco mnoho vývojářů pracuje na problému kompletního sjednoceného připojení, Miklos Szeredi používá jednodušší přístup: sjednocené adresáře. Ty poskytují sjednocení pouze na úrovni nejvyššího adresáře a měnit lze pouze souborový systém na nejvyšší úrovni. To odstraňuje potřebu napsat spoustu komplexního kódu, který by zajišťoval kopírování adresářů výše, vybělení a podobných, ale také významně omezuje funkce.
Na normálním linuxovém systému se proces pdflush probouzí každých pět vteřin, aby vynutil zápis špinavých stránek na úložiště. K tomuto probuzení dochází bez ohledu na to, jestli je něco potřeba zapsat. Zbytečná probouzení jsou čím dál tím méně vítaná, obzvláště na systémech, kde záleží na spotřebě energie, takže by bylo hezké nechat pdflush spát, když není co na práci.
Artem Bityutskiy sestavil sadu patchů, která to zajistí. Mění API souborových systémů, aby se jádru VFS zjednodušilo zjišťování, jestli má daný souborový systém špinavá data. Tato informace se poté použije k rozhodnutí o tom, jestli je potřeba budit pdflush ze spánku. Tento nápad vypadá dobře, ale je zde jeden malý problém: Tato práce je v konfliktu s patchi zapisovacích vláken pro jednotlivé BDI, které připravuje Jens Axboe. Jensovy patche se zbavují časovače pdflush a dělají spoustu dalších změn, takže tyto dva projekty se v současnosti příliš nesnesou. Artem se tedy vrací k rýsovacímu prknu, aby svou práci založil na Jensových patchích místo na hlavní řadě.
Arnaldo Carvalho de Melo navrhl nové systémové volání pro API socketů:
struct mmsghdr { struct msghdr msg_hdr; unsigned msg_len; }; ssize_t recvmmsg(int socket, struct mmsghdr *mmsg, int vlen, int flags);
Rozdíl mezi tímto systémovým voláním a recvmsg() spočívá v tom, že může přijmout několik zpráv v jednom volání. To omezuje režii systémových volání u síťových aplikací s velkou propustností. Komentáře v patchi naznačují, že sendmmsg() se plánuje, ale ještě nebyla zaslána žádná implementace.
Padl návrh, že tuto funkci by bylo možné získat rozšířením recvmsg() novým příznakem zprávy místo přidáváním nového systémového volání. Jak ale upozornil David Miller, to nebude fungovat. Jádro v současnosti ignoruje příznaky, které nepoznává; z toho důvodu by uživatelský prostor neměl možnost rozpoznat, jestli specifické jádro podporuje přijímání několika zpráv naráz, nebo ne. Tato funkčnost tedy bude pravděpodobně přidána v novém systémovém volání.
Jak se vývojový cyklus 2.6.30 blíží ke svému konci, je přirozené ohlédnout se za tím, co bylo začleněno a odkud to přišlo. Zde je tedy tradiční pohled Jaderných novin na to, kdo napsal kód, který se tentokrát dostal do hlavní řady.
2.6.30 byl opět rozsáhlý vývojový cyklus; zahrnoval začlenění (i když těsně po 2.6.30-rc7) 11 733 neslučovacích sad změn od 1125 vývojářů. Počet sad změn překračuje 2.6.29, ale počet vývojářů se snížil z 1166, které jsme viděli minule. Tito vývojáři tentokrát přidali 1,14 milionů řádků kódu, přičemž odstranili 513 000, takže čistý přírůstek je 624 000 řádků.
Statistiky jednotlivých vývojářů vypadají takto:
Nejaktivnější vývojáři 2.6.30 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
Co se sad změn týče, na špičce seznamu je tentokrát Ingo Molnár; jako vždy vytvořil ohromné množství patchů – přibližně pět za den – pro kód architektury x86, ftrace a dalších. Bill Pemberton je možná známější jako správce poštovního klienta Elm; udělal spoustu pročišťovací práce na ovladačích COMEDI ve stromě -staging. Jádro práce Stephena Hemmingera spočívá v konverzi síťových ovladačů na nové API net_device_ops. Hans Verkuil pokračuje v práci na zlepšování frameworku Video4Linux2 a s ním spojených ovladačů a Takashi Iwai vytváří spousty patchů jako správce ALSA.
Linus odpálil vývojový cyklus 2.6.30 s poznámkou, že přibližně třetina změn v 2.6.30-rc1 je „svinstvo“. Není tedy překvapení, že první tři místa ve sloupečku „podle změněných řádek“ dosáhla svého umístění přispíváním do -staging ovladačů. Alex Deucher přidal podporu pro Radeon R6xx/R7xx; mnoho z jeho „změněných řádek“ je firmware mikrokódu těchto karet. A David Schleef přidal do stromu -staging další sadu ovladačů.
Příspěvky do 2.6.30 lze vysledovat k nějakým 190 zaměstnavatelům. Při pohledu na informace o nejaktivnějších zaměstnavatelích vidíme:
Nejaktivnější zaměstnavatelé v 2.6.30 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
Čísla jsou v podstatě podobná těm, která jsme viděli v předchozích vývojových cyklech. Objevuje se zde několik méně známých firem; většinou jsou přítomny díky příspěvkům do stromu -staging. Stojí za to poznamenat, že Broadcom a Atheros, dříve známé jako nespolupracující společnosti, postupem času své příspěvky rozšiřují.
Autor článku Jonathan Corbet se během posledních několika cyklů nedíval na statistiky podpisů. Na značkách Podepsáno-kým [Signed-off-by] je zajímavé to, že z nich lze usoudit, kdo jsou vrátní jádra. Obzvláště když se zanedbají podpisy autorů každého patche, zůstatkem jsou (většinou) podpisy správců subsystémů, kteří schválili začlenění patche. Pro 2.6.30 čísla vypadají takto:
Nejvíce neautorských podpisů v 2.6.30 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
Podpisy jsou vždy rozděleny mezi menší počet vývojářů než příspěvky. I tak se ale jeden podivuje nad tím, jak David Miller zvládá schválit nějakých 20 patchů každý den. Na straně zaměstnavatelů jsou záležitosti koncentrovanější než kdy jindy; více než polovina patchů, které míří do jádra, prochází pod rukama někoho z Red Hatu nebo Novellu. Vývojáři, zdá se, pracují pro velký počet společností, ale správci subsystémů mají tendence soustřeďovat se jenom v hrstce z nich.
Ve shrnutí stále vidíme dobře promazaný, rychle se pohybující vývojový proces. Také vidíme obraz stromu -staging, který roste závratnou rychlostí; Jonathan je v pokušení patche -staging z budoucích hlášení vyjmout, pokud se toto tempo trochu nesníží. I bez stromu -staging se nicméně na jádře hodně pracuje, na čemž se účastní velká skupina vývojářů; a nezdá se, že by se to mělo v blízké budoucnosti měnit.
Dodatek: Jan Engelhardt zaslal Jonathanovi odkaz na krátký skript, který použitím příkazu git blame určuje vlastnictví každého řádku v jádře. První příčky v 2.6.30-rc7 vypadají takto:
Kdo se poslední dotkl řádek kódu | ||
---|---|---|
Řádek | % | Kdo |
4063723 | 35,17 % | Linus Torvalds |
464021 | 4,02 % | Greg Kroah-Hartman |
94200 | 0,82 % | David Howells |
86031 | 0,74 % | David S. Miller |
82608 | 0,71 % | Luis R. Rodriguez |
72200 | 0,62 % | Bryan Wu |
70128 | 0,61 % | Takashi Iwai |
66859 | 0,58 % | Ralf Baechle |
55785 | 0,48 % | Hans Verkuil |
54069 | 0,47 % | Paul Mundt |
54007 | 0,47 % | Kumar Gala |
53288 | 0,46 % | David Brownell |
51640 | 0,45 % | Russell King |
50611 | 0,44 % | Paul Mackerras |
49499 | 0,43 % | Andrew Victor |
49347 | 0,43 % | Mauro Carvalho Chehab |
49256 | 0,43 % | Alan Cox |
47305 | 0,41 % | Mikael Starvik |
47040 | 0,41 % | Ben Dooks |
44307 | 0,38 % | Benjamin Herrenschmidt |
Linus vlastní velký počet řádek, protože v počátku éry gitu do něj vkládal kód. Podle přibližného odhadu se dá usoudit, že na jednu třetinu kódu se od té doby nesáhlo. Se statistikami na úrovni jednotlivých řádků se dají udělat další zajímavé věci; autor článku má v úmyslu tuto možnost někdy v budoucnu prozkoumat.
Originál tohoto článku pro LWN.net napsal Nitin Gupta
Myšlenka komprese paměti – komprimace relativně nepoužívaných stránek a jejich ukládání v samotné paměti – je jednoduchá a existuje již dlouho. Komprese je díky eliminaci drahého I/O na disk mnohem rychlejší než swapování těchto stránek na sekundární úložiště. Když je stránka opět zapotřebí, je dekomprimována a vrácena, což je – opět – mnohem rychlejší než jít pro ni do swapu.
Implementace této myšlenky v Linuxu je v současnosti ve vývoji jako projekt compcache. Vytváří virtuální blokové zařízení (nazvané ramzswap), které se chová jako swapovací disk. Stránky odswapované na tento disk jsou zkomprimovány a uloženy do paměti. Domovská stránka projektu obsahuje informace o možných použitích, číslech o výkonnosti a další údaje. Zaměření projektu není jenom výkonnost – na systémech bez swapu umožňuje běh aplikací, které by jinak jednoduše selhaly kvůli nedostatku paměti. Například Edubuntu zahrnulo compcache, aby se snížila náročnost jeho instalátoru na RAM.
Stránka o výkonnosti na wiki projektu ukazuje čísla pro konfigurace, které se blíží netbookům, tenkým klientům a embedded zařízením. Tyto počáteční výsledky vypadají slibně, například v benchmarku pro tenké klienty ramzswap poskytuje téměř stejný efekt jako zdvojnásobení paměti. Další benchmark ukazuje, že průměrný čas potřebný k dokončení požadavků na čtení nebo zápis do swapu je s ramzswap drasticky snížen. Se swap oddílem umístěným na disku s 10000 rpm se průměrný čas požadavku na čtení a zápis do swapu pohyboval okolo 168 ms a 355 ms v uvedeném pořadí. S ramzswap byly tyto hodnoty 12 µs a 7 µs – v tom je započtena i doba testu, jestli stránka obsahuje samé nuly, a komprese/dekomprese nenulových stránek.
Přístup používající virtuální blokové zařízení představuje oproti předchozím pokusům významné zjednodušení. Předchozí implementace vyžadovaly změny v cestě zápisu do swapu, obsluhy výpadku stránky a funkcích pro vyhledávání v cachích stránek (find_get_page() a spol.). Tyto patche nebyly všeobecně přijaty kvůli své rušivé povaze. Nový přístup je mnohem méně rušivý, ale za určitou cenu: Compcache ztratila schopnost komprimovat stránky z cache stránek (obsahující data ze souborového systému). Nyní je možné komprimovat jen stránky swapu (anonymní). Zároveň ale tato jednoduchost a nerušivost zajistila začlenění projektu do Ubuntu, ALT Linux, LTSP (Linux Terminal Server Project) a možná do dalších.
Mělo by být poznamenáno, že když je použit na úrovni hypervizoru, compcache dokáže komprimovat jakoukoliv část paměti hosta bez ohledu na to, o jakého hosta (Linux, Windows atd.) jde – to by mělo umožnit spouštět více virtuálních strojů pro dané množství celkové paměti hostitele. Například fyzická paměť hosta je u KVM pro hostitele (v tomto případě linuxové jádro) jednoduše anonymní paměť. S nedávnou podporou MMU notifikátoru začleněného do linuxového jádra je nyní téměř celá fyzická paměť hosta odswapovatelná [PDF].
Všechny jednotlivé komponenty jsou oddělené jaderné moduly:
Jakmile jsou tyto moduly nahrány, stačí pouze aktivovat swapovací zařízení ramzswap:
swapon /dev/ramzswap0
Všimněte si, že ramzswap není možné použít jako obecné blokové zařízení, zvládá pouze I/O zarovnané na jednotlivé stránky, což dostačuje pro použití jako swapovací zařízení. Zatím se neobjevil žádný případ, který by ospravedlnil snahu vytvořit obecné komprimující blokové zařízení pro čtení i zápis. Aby se minimalizovala režie blokové vrstvy, používá ramzswap režim práce „bez fronty“. Tím přijímá požadavky přímo z blokové vrstvy a vyhýbá se tak veškeré režii spojené s frontou požadavků.
Modul přijímá parametry určující velikost „disku“, omezení paměti a záložní swapovací oddíl. Volitelný záložní swapovací oddíl je oddíl, kam ramzswap přepošle požadavky na zápis/čtení stránek, které se zkomprimují na velikost větší než PAGE_SIZE/2 – v paměti se tak udržují jenom dobře komprimovatelné stránky. Navíc se stránky testují a pokud je nějaká zaplněná pouze nulami, nealokuje se pro ni žádná paměť. Pro „obvyklou“ zátěž desktopu (Firefox, poštovní klient, editor, přehrávač atd.) vidíme typicky 4000–5000 stránek zaplněných nulami.
Jedna z největších výzev tohoto projektu bylo spravovat komprimované kousky paměti o různých velikostech. K tomu ramzswap používá paměťový alokátor xvMalloc vyvinutý specificky pro tento projekt. Má O(1) malloc/free, velmi malou fragmentaci (do 10 % od ideální hodnoty ve všech testech) a umí využívat horní paměť (užitečné na systémech s více než 1 G paměti). Exportuje nestandardní rozhraní alokátoru:
struct xv_pool *xv_create_pool(void); void xv_destroy_pool(struct xv_pool *pool); int xv_malloc(struct xv_pool *pool, u32 size, u32 *pagenum, u32 *offset, gfp_t flags); void xv_free(struct xv_pool *pool, u32 pagenum, u32 offset);
xv_malloc() vrací pár <pagenum, offset>. Tuto stránku poté musí namapovat volající (pomocí kmap()) a tím získat platný ukazatel v jaderném prostoru.
Ospravedlnění pro využívání vlastního alokátoru paměti bylo poskytnuto, když byly do linux-kernel zaslány patche compcache. Alokátory SLOB i SLUB se ukázaly být pro tento projekt nepoužitelné. SLOB se zaměřuje na embedded zařízení a tvrdí, že má velkou prostorovou efektivitu. Ukázalo se nicméně, že má nějaké významné problémy: Chování alloc/free je O(n) a může vést k velkému množství vyplýtvaného prostoru, což je detailněji rozebráno v tomto příspěvku v LKML.
Na druhou stranu SLUB má jinou sadu problémů. První je neobvyklá záležitost s fragmentací: Data prezentovaná zde ukazují, že kmalloc používá přibližně o 43 % více paměti než xvmaloc. Další problém je, že aby omezil fragmentaci, závisí na alokací stránek vyšších řádů. To pro ramzswap není akceptovatelné, protože se používá v situacích, kdy je paměti málo, takže alokace vyšších řádů téměř jistě selžou. Alokátor xvmalloc na druhou stranu, když potřebuje rozšířit svůj fond paměti, alokuje stránky nultého řádu.
Navíc jak SLUB, tak SLOB jsou omezeny na alokace z dolní paměti. Toto omezení konkrétně platí pouze pro 32bitové systémy s více než 1 G paměti. Na takových systémech ani jeden z alokátorů není schopen alokovat z oblasti horní paměti. Toto omezení není pro projekt compcache akceptovatelné, uživatelé s takovými konfiguracemi hlásili selhání při alokaci paměti pro ramzswap (před tím, než byl vyvinut xvmalloc), i když byla k dispozici spousta horní paměti. Alokátor xvmalloc je schopen alokovat z oblasti horní paměti.
Vzhledem k výše uvedeným bodům by xvmalloc mohl potenciálně nahradit SLOB alokátor. To by nicméně zahrnovalo spoustu další práce, protože xvmalloc poskytuje nestandardní rozhraní malloc/free. Ve svém současném stavu navíc xmvalloc není škálovatelné (to není ani SLOB), takže nemůže být zvažováno jako náhrada za SLUB.
Paměť potřebná pro alokaci komprimovaných stránek není předalokována; zvětšuje se a zmenšuje podle potřeby. Při inicializaci ramzswap vytváří fond paměti xvmalloc. Když fond nemá dostatek paměti k uspokojení požadavku na alokaci, zvětší se alokací jediné stránky (nultý řád) od jaderného alokátoru stránek. Když je objekt uvolněn, xvmalloc sloučí s ním sousedící volné bloky ve stejné stránce. Jestliže je výsledná velikost volného bloku rovna PAGE_SIZE, tj. když stránka neobsahuje žádný objekt, je uvolněna zpátky jádru.
Tato alokace a uvolňování objektů může vést k fragmentaci paměti ramzswap. Uvažme případ, kde je v krátkém čase uvolněno mnoho objektů a následně je velmi málo požadavků na zápis do swapu. V takovém případě může xvmalloc skončit s mnoha částečně zaplněnými stránkami, z nichž každá bude obsahovat pouze malé množství živých objektů. Aby byl tento případ řešen, bude potřeba implementovat nějaký druh defragmentace paměti xvmalloc; to by bylo možné provést přemístěním objektů z téměř prázdných stránek do jiných stránek ve fondu xvmalloc. Je však třeba podotknout, že po měsících praktického používání na desktopových strojích plýtvání pamětí kvůli fragmentaci nikdy nepřekročilo 7 %.
Vzhledem k tomu, že jde o blokové zařízení, nemůže ramzswap vědět, že je komprimovaná stránka zastaralá – řekněme, že proces, který ji vlastní, se ukončil. Takové (komprimované) stránky jednoduše plýtvají pamětí. S nedávnou podporou zahození swapu [swap discard] to ale není tak velkým problém. Zahození swapu vysílá bio požadavek BIO_RW_DISCARD, když najde volný cluster swapu během alokace. I když compcache neobdrží zpětné volání [callback] ihned poté, co stránka zastará, je to stále lepší, než když jsou takové stránky udržovány v paměti, dokud nejsou přepsány jinou stránkou. Podpora pro mechanismus zahození swapu byla přidána do compcache-0.5.
Obecně požadavek na zahození přichází dlouho poté, co stránka zastarala. Vezměme případ, když se proces intenzivně využívající paměť ukončí a nedochází k žádnému dalšímu swapování. V takových případech v ramzswapu zůstane spousta zastaralých stránek. Vzhledem k tomu, že nedochází k dalším požadavkům na swapování, ramzswapu nepřijdou žádné požadavky na zahození swapu; lze očekávat, že pro některé z těchto zastaralých stránek přijdou požadavky k zahození, až když se znovu začne swapovat.
Aby se se tedy ramzswap zefektivnil, jsou potřeba změny v jádře (ještě neprovedeny), aby byla bitová mapa swapu prohledávána agresivněji a tak nalézány uvolněné clustery swapu – přinejmenším v případě, že je RAM zálohována swapovacím zařízením. Adaptivní politika změn velikosti komprimované cache by také byla užitečná – mohla by monitorovat přístupy ke komprimované cache a málo používané stránky přesunout na fyzické swapovací zařízení. V současnosti může ramzswap přeposlat nekomprimovatelné stránky zpět na záložní disk, ale nemůže odswapovat paměť alokovanou xvmalloc.
Další zajímavý podprojekt je infrastruktura SwapReplay. Tento nástroj je určen ke snadnějšímu testování chování paměťového alokátoru za podmínek skutečného swapování. Je to jaderný modul a sada nástrojů v uživatelském prostoru, které umí přehrát swapovací události. Jaderný modul fyzické swapovací zařízení překrývá pseudoblokovým zařízením (/dev/sr_relay). Když jádro přes toto pseudoswapovací zařízení swapuje, pošle do uživatelského prostoru kombinaci <číslo sektoru, R/W bit, zkomprimovanou délku> a pak I/O požadavek přepošle skutečnému swapovacímu zařízení (určeného parametrem swap_replay modulu). Získaná data lze potom procházet k tomu určenou knihovnou, která poskytuje rozhraní pro zpětné volání pro události swapu. Klienty používající tuto knihovnu mohou pro tyto události poskytnout jakoukoliv akci – zobrazit histogramy zkomprimované délky, simulovat chování ramzswap atd. Pro tuto funkci není nutné žádné patchování jádra.
Infrastruktura přehrávání swapu byla pro vývoj ramzswap velmi užitečná. Možnost přehrát využívání swapu umožňuje jednoduché a konzistentní simulace pro jakoukoliv zátěž bez potřeby ji nastavit a spouštět znovu a znovu. Jestliže uživatel trpí s některými druhy zátěže velkou fragmentací, může Nitinovi zaslat výpis swapování pro tuto zátěž a on tím bude mít všechna data potřebná k reprodukování stavu u sebe – bez nutnosti připravit stejnou zátěž.
Byly napsány klienty pro procházející knihovnu, které simulují chování ramzswap podle výpisů různých druhů zátěže, aby se zjednodušilo hodnocení různých alokátorů paměti a tím nakonec i vývoj a zlepšování alokátoru xvmalloc. V budoucnosti to také pomůže testování různých politik vytěsňování [eviction] při podpoře adaptivních změn velikosti cache.
Projekt compcache je v současnosti aktivně vyvíjen; některé z dalších plánovaných vlastností jsou: Adaptivní změna velikosti komprimované cache, možnost swapování paměti xvmalloc na fyzický swapovací disk, defragmentace paměti přesunutím komprimovaných kousků v paměti a komprimované swapování na disk (4–5 stránek odswapováno během jediného I/O na disk). Později by mohlo dojít k rozšíření pro komprimování cachí stránek (což dělaly starší patche) – v současnosti obsahuje pouze komponentu ramzswap, která řeší kompresi anonymní paměti.
Když byly naposledy patche ramzswap zaslány k revizi, byla jako odůvodnění této vlastnosti poskytnuta jenom výkonnostní data LTSP. Andrewu Mortonovi tato data nestačila. Nyní je na wiki stránce projektu o výkonnosti nahráno mnohem více dat, která ukazují zlepšení výkonnosti, které ramzswap poskytuje. Andrew také poukázal na nedostatek informací o případech, když ramzswap působí zhoršení výkonnosti:
Projekt pro tyto případy data stále postrádá. Měla by nicméně být k dispozici někdy v době 2.6.32, kdy budou tyto patche znovu zaslány pro možné začlenění do hlavní řady.
Na LWN se API debugfs zabývali roku 2004. V poněkud méně dávné době Shen Feng nabídl, že by článek o debugfs začlenil jako soubor v adresáři Documentation. V tomto návrhu spočíval jenom jeden malý problém: Jak by se dalo očekávat, API debugfs se od roku 2004 trochu změnilo. Následující text je pokus aktualizovat původní dokument, aby pokrýval celé API tak, jak existuje v jádře 2.6.30.
Debugfs existuje jako jednoduchý způsob, jakým mohou vývojáři jádra zpřístupnit informace uživatelskému prostoru. Na rozdíl od /proc, které má obsahovat pouze informace o procesech, či sysfs, které má striktní pravidlo „v jednom souboru jedna hodnota“, nemá debugfs pravidla žádná. Vývojáři tam mohou vložit, jaké informace chtějí. Souborový systém debugfs navíc nemá sloužit jako stabilní ABI do uživatelského prostoru; teoreticky se na soubory sem exportované nevztahují žádná omezení na stabilitu. Skutečnost nicméně není vždy tak jednoduchá; i rozhraní debugfs je nejlépe navrhovat s myšlenkou na to, že je bude potřeba spravovat navždy.
Debugfs se typicky připojuje příkazem, jako je tento:
mount -t debugfs none /sys/kernel/debug
(nebo odpovídající řádkou v /etc/fstab.) V mailových konferencích občas vzniká neshoda o tom, kde je správné místo pro připojování debugfs, a některá dokumentace se odkazuje na jiné připojovací body jako /debug. V současnosti je kód v uživatelském prostoru, který používá soubory v debugfs, přenositelnější, pokud si přípojný bod najde v /proc/mounts.
Všimněte si, že API debugfs je modulům exportováno jako pouze-GPL.
Kód používající debugfs by měl vkládat <linux/debugfs.h>. První věc, kterou je pak nutno udělat, je vytvoření alespoň jednoho adresáře, který bude obsahovat sadu souborů debugfs:
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
Toto volání, pokud uspěje, vytvoří adresář pojmenovaný name v určeném adresáři parent. Pokud je parent NULL, adresář bude vytvořen v kořeni debugfs. Při úspěchu je návratová hodnota ukazatel na struct dentry, který lze použít k vytváření souborů v daném adresáři (a k jeho vyčištění na konci). Návratová hodnota NULL indikuje, že se něco nepovedlo. Pokud je vráceno -ENODEV, znamená to, že jádro bylo přeloženo bez podpory debugfs a že žádná z funkcí popsaných níže nebude fungovat.
Nejobecnější způsob, jak v adresáři debugfs vytvořit soubor, je:
struct dentry *debugfs_create_file(const char *name, mode_t mode, struct dentry *parent, void *data, const struct file_operations *fops);
Zde je name jméno souboru, který má být vytvořen, mode popisuje oprávnění, která má soubor mít, parent udává, ve kterém adresáři má být soubor uložen, data se uloží do pole i_private výsledné struktury inode a fops je sada operací se souborem, která implementuje chování souboru. Minimálně by měly být poskytnuty operace read() a/nebo write(); další mohou být přidány podle potřeby. Návratová hodnota je opět ukazatel na dentry výsledného souboru, NULL, pokud došlo k chybě, nebo -ENODEV, pokud chybí podpora debugfs.
V mnoha případech není vytvoření sady operací se souborem zapotřebí; kód debugfs pro jednoduché situace poskytuje mnoho pomocných funkcí. Soubor obsahující jedinou celočíselnou hodnotu lze vytvořit kteroukoliv z následujících:
struct dentry *debugfs_create_u8(const char *name, mode_t mode, struct dentry *parent, u8 *value); struct dentry *debugfs_create_u16(const char *name, mode_t mode, struct dentry *parent, u16 *value); struct dentry *debugfs_create_u32(const char *name, mode_t mode, struct dentry *parent, u32 *value); struct dentry *debugfs_create_u64(const char *name, mode_t mode, struct dentry *parent, u64 *value);
Tyto soubory podporují jak čtení, tak zápis předané hodnoty; pokud do specifického souboru nemá být možné zapisovat, stačí jednoduše nastavit odpovídající bity v mode. Hodnoty v těchto souborech jsou vypsány desítkově; pokud je vhodnější šestnáctkový zápis, lze použít tyto funkce:
struct dentry *debugfs_create_x8(const char *name, mode_t mode, struct dentry *parent, u8 *value); struct dentry *debugfs_create_x16(const char *name, mode_t mode, struct dentry *parent, u16 *value); struct dentry *debugfs_create_x32(const char *name, mode_t mode, struct dentry *parent, u32 *value);
Všimněte si, že není debugfs_create_x64().
Tyto funkce jsou užitečné, pokud vývojář zná velikost hodnoty, která se exportuje. Některé typy však mohou mít na různých architekturách různé velikosti, což situaci poněkud komplikuje. Existuje funkce, která pomůže v jednom zvláštním případě:
struct dentry *debugfs_create_size_t(const char *name, mode_t mode, struct dentry *parent, size_t *value);
Jak lze odhadnout, tato funkce vytvoří v debugfs soubor, který reprezentuje proměnnou o velikosti size_t.
Pravdivostní hodnoty lze do debugfs vložit voláním:
struct dentry *debugfs_create_bool(const char *name, mode_t mode, struct dentry *parent, u32 *value);
Čtení výsledného souboru vrací buď Y (pro nenulové hodnoty) nebo N následované znakem pro nový řádek. Zapisovat je možné malá i velká písmena a hodnoty 1 a 0.
Jakákoliv jiná vstupní hodnota je v tichosti ignorována.A nakonec je takto možné exportovat libovolná binární data:
struct debugfs_blob_wrapper { void *data; unsigned long size; }; struct dentry *debugfs_create_blob(const char *name, mode_t mode, struct dentry *parent, struct debugfs_blob_wrapper *blob);
Čtení z tohoto souboru vrátí data, na která ukazuje struktura debugfs_blob_wrapper. Některé ovladače „bloby“ používají jako jednoduchý způsob, jak vrátit několik řádek (statického) formátovaného textového výstupu. Tuto funkci lze použít k exportu binárních informací, ale nezdá se, že by to v hlavní řadě nějaký kód dělal. Všimněte si, že soubory vytvořené pomocí debugfs_create_blob() jsou pouze pro čtení.
K dispozici je několik pomocných funkcí zaměřených na adresáře:
struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, struct dentry *new_dir, const char *new_name);
struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, const char *target);
Volání debugfs_rename() dá existujícímu souboru v debugfs nové jméno, které může být i v jiném adresáři; new_name nesmí před voláním existovat, návratová hodnota je old_dentry s aktualizovanou informací. Symbolické odkazy lze vytvořit pomocí debugfs_create_symlink().
Je zde jedna důležitá věc, se kterou musí všichni uživatelé debugfs počítat: Žádné adresáře vytvořené v debugfs nejsou automaticky pročišťovány. Jestliže je modul odstraněn, aniž by explicitně záznamy v debugfs smazal, výsledkem bude spousta neplatných ukazatelů a velká spousta velmi nespolečenského chování. Všichni uživatelé debugfs – nebo alespoň ti, které lze přeložit jako moduly – musí být připraveni odstranit všechny soubory a adresáře, které vytvoří. Soubor lze odstranit voláním:
void debugfs_remove(struct dentry *dentry);
Hodnota dentry může být NULL.
Bylo nebylo, uživatelé debugfs si museli pamatovat ukazatele na dentry pro všechny soubory, které vytvořili, aby je později mohli pročistit. Nyní nicméně žijeme v civilizovanějších časech, takže stačí zavolat:
void debugfs_remove_recursive(struct dentry *dentry);
Když je této funkci předán ukazatel na dentry odpovídající nejvyššímu adresáři, je celá hierarchie v tomto adresáři smazána.
Tak o té compcache jsem dosud neměl tušení a vypadá to docela zajímavě. Podařilo se mi do 4 GiB paměti nacpat 5,1 GiB a ještě je cca 100 MiB volných. Vskutku zajímavé.
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.