GNU/Linux >> Znalost Linux >  >> Linux

Jak mmapovat zásobník pro systémové volání clone() na linuxu?

Pro mmap byste chtěli příznak MAP_ANONYMOUS. A MAP_GROWSDOWN, protože ji chcete použít jako zásobník.

Něco jako:

void *stack = mmap(NULL,initial_stacksize,PROT_WRITE|PROT_READ,MAP_PRIVATE|MAP_GROWSDOWN|MAP_ANONYMOUS,-1,0);

Více informací naleznete na manuálové stránce mmap. A pamatujte, že klon je nízkoúrovňový koncept, který byste neměli používat, pokud opravdu nepotřebujete to, co nabízí. A nabízí spoustu kontroly - jako je nastavení vlastního zásobníku - pro případ, že byste chtěli provést nějaké triky (například mít zásobník přístupný ve všech souvisejících procesech). Pokud nemáte dobrý důvod použít klon, držte se vidlice nebo pthreads.


Hromady nejsou a nikdy nemohou být neomezené ve svém prostoru pro růst. Jako všechno ostatní žijí ve virtuálním adresovém prostoru procesu a množství, o které mohou růst, je vždy omezeno vzdáleností k sousední mapované oblasti paměti.

Když lidé mluví o dynamickém růstu zásobníku, mohou mít na mysli jednu ze dvou věcí:

  • Stránky zásobníku mohou být nulové stránky typu copy-on-write, u kterých se nevytvoří soukromé kopie, dokud není proveden první zápis.
  • Spodní části oblasti zásobníku ještě nemusí být rezervovány (a tudíž se nezapočítávají do poplatku za potvrzení procesu, tj. do množství fyzické paměti/swapu, které jádro představovalo jako rezervované pro proces), dokud není nalezena ochranná stránka , v takovém případě jádro zapíše více a přesune ochrannou stránku nebo proces ukončí, pokud nezbývá žádná paměť pro potvrzení.

Snažím se spoléhat na MAP_GROWSDOWN vlajka je nespolehlivá a nebezpečná protože vás nemůže ochránit před mmap vytvoření nového mapování těsně sousedícího s vaší hromádkou, které pak bude zablokováno. (Viz http://lwn.net/Articles/294001/) Pro hlavní vlákno si jádro automaticky vyhrazuje velikost zásobníku ulimit v hodnotě adresního prostoru (nikoli paměť ) pod zásobníkem a zabraňuje mmap od jeho přidělení. (Ale pozor! Některá nefunkční jádra opravená dodavatelem toto chování zakazují, což vede k náhodnému poškození paměti!) U ostatních vláken jednoduše musíte mmap celý rozsah adresního prostoru, který vlákno může potřebovat pro zásobník při jeho vytváření. Jinak to nejde. Mohli byste udělejte většinu z nich zpočátku tak, aby nebylo možné zapisovat/nečíst, a změňte to při poruchách, ale pak byste potřebovali obslužné nástroje signálů a toto řešení není v implementaci vláken POSIX přijatelné, protože by narušovalo obsluhu signálů aplikace. (Všimněte si, že jako rozšíření by jádro mohlo speciální nabídka MAP_ příznaky doručí jiný signál místo SIGSEGV na nelegální přístup k mapování, a pak by implementace vláken mohla zachytit tento signál a jednat podle něj. Ale Linux v současnosti žádnou takovou funkci nemá.)

Nakonec si všimněte, že clone syscall nebere argument ukazatele zásobníku, protože jej nepotřebuje. Systémové volání musí být provedeno z kódu sestavení, protože obálka uživatelského prostoru je vyžadována ke změně ukazatele zásobníku ve vlákně „podřízeného“ tak, aby ukazoval na požadovaný zásobník, a vyhnul se zápisu čehokoli do zásobníku rodiče.

Ve skutečnosti clone přebírá argument ukazatele zásobníku, protože není bezpečné čekat na změnu ukazatele zásobníku v „dítě“ po návratu do uživatelského prostoru. Pokud nejsou všechny signály blokovány, může se obsluha signálu okamžitě spustit na nesprávném zásobníku a na některých architekturách musí být ukazatel zásobníku platný a musí neustále ukazovat na oblast bezpečnou pro zápis.

Nejen, že je úprava ukazatele zásobníku z C nemožná, ale také jste se nemohli vyhnout možnosti, že kompilátor zablokuje nadřazený zásobník po systémovém volání, ale před změnou ukazatele zásobníku.


Linux
  1. Jak používat systemd-nspawn pro obnovu systému Linux

  2. Jak zkontrolovat verzi OS a Linuxu

  3. Jak nastavím velikost ukazatele myši X v subsystému Windows pro Linux

  1. Jak změnit identitu systému Linux

  2. Linux:Jak najít ovladač zařízení používaný pro zařízení?

  3. Linux – Jak zakázat pípání systému pro neprivilegované uživatele?

  1. Jak najít aplikaci pro typ mime v systému Linux?

  2. Tabulka systémových volání Linux nebo cheatsheet pro shromáždění

  3. Jak předat parametry systémovému volání Linuxu?