Portál AbcLinuxu, 28. dubna 2024 13:34

Jaderné noviny – 11. 8. 2011: Přesun TCP spojení do jiného procesu

22. 8. 2011 | Luboš Doležel
Články - Jaderné noviny – 11. 8. 2011: Přesun TCP spojení do jiného procesu  

Aktuální verze jádra: 3.1-rc1. Citáty týdne: Thomas Gleixner, Linus Torvalds, Valerie Aurora. Mel Gorman vydal MMTests 0.01. Zmocňování se TCP spojení a paraziti - jako dobrá věc.

Obsah

Aktuální verze jádra: 3.1-rc1

link

Aktuální vývojovou verzí jádra je 3.1-rc1 vydané 7. srpna. Linus k tomu řekl:

Co stojí za zmínku? To záleží na tom, co vás zajímá. Práce na zpětném zápisu VM? Je to tam. A také tam bylo trochu kontroverze kolem kódu cíle iSCSI. Jsou tam změny kolem síťování, přesun zbytku obecné podpory ACL do vrstvy VFS, zjednodušení starého kódu kolem souborových systémů, který měl často jen podobu nakopírované kostry programu. A zároveň také zrychlování naší práce. A také pročišťování rozhraní správy výkonu.

Ale není tu nic *obrovského*. Vypadá to jako docela normální vydání, jak jsem už řekl. Ledaže bych na něco zapomněl.

Všechny podrobnosti lze nalézt v kompletním seznamu změn.

Stabilní aktualizace: verze 3.0.1 byla vydána 4. srpna s dlouhým seznamem oprav. Verze 2.6.32.44 a 2.6.33.17 vyšly 8. srpna. Greg dává vědět, že údržba jádra 2.6.33 může být zanedlouho ukončena.

Citáty týdne: Thomas Gleixner, Linus Torvalds, Valerie Aurora

link

Je třeba pochopit, že preempt_disable, bh_disable, irq_disable jsou BKL pro aktuální CPU s velice nepatrnou sémantikou, která je velmi blízká původnímu hororu BKL (big kernel lock; velký zámek jádra). Všechny tyto mechanismy ovlivňují jednotlivá CPU a faktem je, že musíme doplnit nějaké anotace, které napomohou pochopitelnosti a v první řadě odladitelnosti. Vedlejším účinkem je to, že to pomůže RT toto vyřešit, což je samozřejmě žádoucí, ale nikoliv hlavním cílem tohoto snažení.

-- Thomas Gleixner

Skutečností je, že pro příští začleňovací okno chystám poměrně drsné opatření. Po otevření začleňovacího okna natáhnu strom -next a pokud dostanu něco, co není jen triviální oprava a není to v „stromu -next v momentu otevření začleňovacího okna“, budu takový požadavek na přetažení ignorovat. Protože lidé zjevně nejsou dostatečně opatrní.

-- Linus Torvalds

Neměli bychom dělat voodoo. Nebo teda, vůbec mi nebude vadit, pokud budete doma v soukromí mít voskové figurky s mou podobou – je tu ta svoboda vyznání a tak – ale prosím nedělejte to v jádře.

-- Linus Torvalds

Kdykoliv mě dostihne frustrace z papírování, tak si prostě představím, že bych měla na práci odhadovat, kolik času trvá vyřešit papírování, a hned se cítím lépe.

-- Valerie Aurora

Mel Gorman vydal MMTests 0.01

link

Jaderný hacker Mel Gorman vydal testovací sadu pro subsystém správy paměti Linuxu. Pročistil některé skripty, co používá, a učinil je méně specifickými pro konkrétní sady patchů. Zatímco nejsou „v žádném směru komplexní“, mohou být pro jiné lidi užitečné. Také zveřejnil surová data z testů, které nedávno provedl. „Vím, že struktura hlášení vypadá dost surově, ale neměl jsem zájem na tom dělat je hezké. Kvůli tomu, že některé skripty jsou velice staré, jsou kvalita a styl kódování dosti různorodé. Toto může být časem pročištěno, ale mezitím se při čtení skripů pokuste udržet obsah svých žaludků na místě.

Zmocňování se TCP spojení a paraziti – jako dobrá věc

link

Jádro 3.1 bude obsahovat řadu vylepšení systémového volání ptrace() od Tejuna Hea. Tato vylepšení mají usnadnit spolehlivé ladění programů, ale Tejun zjevně není s takhle obyčejnými cíli spokojen. Takže zveřejnil ukázkový program, který předvádí, jak mohou být nové funkce využity k řešení složitých problémů, kterým čelí implementace kontrolního bodu/restartu [checkpoint/restart]: zachycení a obnova stavu síťových spojení. Kód je ve rané fázi vývoje; je smělý a děsivý, ale předvádí, jak může být dosaženo zajímavých věcí.

Tradiční volání API ptrace() připojuje cílový program ke sledujícímu procesu příkazem PTRACE_ATTACH; tento příkaz přepne cíl do sledovaného stavu a zastaví jej. PTRACE_ATTACH nebylo nikdy dokonalé; změní to obsluhu signálů cílového procesu a nikdy proti cílovému programu nemůže být zcela transparentní. Proto jej Tejun doplnil o nový příkaz PTRACE_SEIZE; PTRACE_SEIZE se připojí k cílovému programu, ale nezastaví jej a ani nezmění jeho obsluhu signálů. Cílový program pak lze zastavit pomocí PTRACE_INTERRUPT, které opět neposílá žádné signály a nemění způsob jejich obsluhy. Toto přináší mechanismus umožňující práci s procesy transparentnějším a méně rušivým způsobem.

Toto se zdá být užitečné, ale nevypadá to nezbytně jako součást implementace kontrolního bodu/restartu. Nicméně to dokáže významným způsobem pomoci. Jedním z problémů spojených s ukládáním stavu procesu je to, že ne všechen stav je viditelný z uživatelského prostoru. Snaha obejít toto omezení vedla vždy k vytváření kontrolních bodů v jádře nebo vytváření nových rozhraní, která by požadované informace poskytovala; ani jeden z těchto přístupů nebyl idelání. Jenže v mnoha případech je možné získat požadované informace z kontextu cílového procesu; toto je situace, kdy přístup založený na ptrace() může hrát roli.

Tejun si ve své ukázkové implementaci vzal na starost ukládání a obnovu stavu otevřeného TCP spojení. Proces je zahájen použitím ptrace() pro zmocnění se a zastavení cílového vlákna (vláken); pak už je získání nezbytných informací otázkou spuštění nějakého toho kódu v kontextu daného procesu. Aby to mohl udělat, Tejunův ukázkový program se prohrabe paměťovým prostorem cílového programu a najde nějakou trochu paměti, která má právo ke spuštění; obsah této paměti je uložen a nahrazen jeho „parazitickým“ kódem. Trocha manipulace s registry umožní to, že je cílový proces spuštěn v místě vloženého kódu, které se postará po shromáždění potřebných informací. Jakmile je to hotové, původní kód a registry jsou obnoveny a cílový proces je ve stejném stavu, v jakém byl, než se tohle všechno událo.

"Parazitický" kód začíná shromážděním základních informací o otevřených spojeních: IP adresy, porty apod. Stav strany příjmu dat každého spojení je uložen 1) překopírováním jakýchkoliv příchozích dat v bufferu za použití volby MSG_PEEKrecvmsg() a 2) získáním sekvenčního čísla dalších čtených dat za pomoci nového povelu SIOCGINSEQioctl(). Na straně odesílání dat musí být sekvenční číslo každého odchozího paketu ve frontě zachyceno spolu se samotnými daty v paketu získáno pomocí dalšího nového páru příkazů ioctl(). Jakmile je toto hotové, je hotové i vytvoření kontrolního bodu síťových spojení.

Obnovení spojení – dost možná v jiném procesu a na úplně jiném stroji – je trochu zrádnější; představa jádra o spojení musí přesně odpovídat situaci v době vytvoření kontrolního bodu, aniž by byla druhá strana zmatena nebo pocítila jiné problémy. To vyžaduje, aby kód provádějící restart předstíral, že je na druhé straně spojení, dokud nebudou věci synchronizovány. Jádro už poskytuje většinu věcí nutných pro tento úkol: odchozí pakety mohou být zachyceny mechanismem „nf_queue“ a raw socket může být použit pro vložení nových paketů, které vypadají, jako by přicházely od vzdálené strany.

Takže v moment restartu se začíná jednoduše otevřením nového spojení se vzdálenou stranou. Další příkaz ioctl() (SIOCSOUTSEQ) je použit pro nastavení sekvenčního čísla před odpojením, aby odpovídalo číslu zjištěnému v době vytváření kontrolního bodu. Jakmile je zahájen proces připojování, odchozí paket SYN je odchycen – jelikož vzdálená strana na něj jistě nebude připravena – a SYN/ACK je pak vložen lokálně. Odchozí ACK musí také samozřejmě být zachycen a odhozen. Jakmile je toto hotové, jádro má za to, že má otevřené spojení ke vzdálené straně se sekvenčním číslem odpovídají stavu před vytvořením kontrolního bodu.

Pak už je to jen otázkou obnovení příchozích dat, která byla nalezena ve frontě v jádře v době vytvoření kontrolního bodu; toho je dosaženo vložením nových paketů, které obsahují tato data, a odchycením následných ACK od síťové vrstvy. Odchozí data mohou na druhou stranu být nahrazeny jednoduchými voláními send(), ale je tu jedna malá zrada. Pakety v odchozí frontě už mohly být odeslány a přijaty vzdálenou stranou. Opětovné odeslání těchto paketů není problém, pokud je velikost těchto paketů zachována. Pokud by systém použil odlišné offsety pro rozdělování odchozích dat do paketů, mohlo by to vzdálenou stranu zmást. Aby se to nestalo, Tejun přidal ještě jedno ioctl() (SIOCFORCEOUTBD), aby zajistil, že pakety odpovídají těm, které byly vytvoření před zahájením vytváření kontrolního bodu.

Jakmile je odesílací fronta obnovena, spojení je opět v původním stavu. V tento moment může zachycování odchozích paketů přestat.

Celá tahle věc může vypadat trochu komplexně a křehce, ale Tejun tvrdí, že „ve skutečnosti to funguje dosti spolehlivě“. Navzdory tomu je spousta detailů, které byly ignorovány; jde konec konců jen o důkaz toho, že je to možné. Nemá jít o kompletní řešení problému vytváření kontrolních bodů a obnovy síťových spojení; myšlenkou je předvést, že to samozřejmě je možné. Pokud práce na kontrolních bodech/restartu v uživatelském prostoru pokročí, může někdy tento přístup k věci použít. Mezitím tu ale máme zajímavý hack předvádějící, čeho může být dosaženo s novými příkazy ptrace(). Ti, kteří chtějí více podrobností o fungování celé věci, je mohou najít v souboru README v repozitáři se zdrojovým kódem příkladu.

Odkazy a zdroje

Kernel coverage at LWN.net: August 11, 2011

Další články z této rubriky

Jaderné noviny – přehled za březen 2024
Jaderné noviny – přehled za únor 2024
Jaderné noviny – přehled za leden 2024
Jaderné noviny – přehled za prosinec 2023
Jaderné noviny – přehled za listopad 2023

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.