it-swarm-eu.dev

Jak najdu implementace systémových volání jádra systému Linux?

Snažím se pochopit, jak funkce, řekněme mkdir, pracuje při pohledu na zdroj jádra. Toto je pokus pochopit jádro jádra a navigovat mezi různými funkcemi. Vím, že mkdir je definováno v sys/stat.h. Našel jsem prototyp:

/* Create a new directory named PATH, with permission bits MODE.  */
extern int mkdir (__const char *__path, __mode_t __mode)
     __THROW __nonnull ((1));

Teď musím zjistit, ve kterém C souboru je tato funkce implementována. Ze zdrojového adresáře jsem to zkusil

ack "int mkdir"

které se zobrazily

security/inode.c
103:static int mkdir(struct inode *dir, struct dentry *dentry, int mode)

tools/perf/util/util.c
4:int mkdir_p(char *path, mode_t mode)

tools/perf/util/util.h
259:int mkdir_p(char *path, mode_t mode);

Ale žádný z nich neodpovídá definici v sys/stat.h.

Otázky

  1. Který soubor má implementaci mkdir?
  2. Jak lze pomocí definice funkce, jako je výše, zjistit, který soubor má implementaci? Existuje nějaký vzorec, který jádro sleduje při definování a implementaci metod?

POZNÁMKA: Používám jádro 2.6.36-rc1 .

376
Navaneeth K N

Systémová volání nejsou zpracovávána jako běžná volání funkcí. Přechod z uživatelského prostoru do prostoru jádra vyžaduje speciální kód, v zásadě trochu vloženého kódu sestavy vloženého do vašeho programu v místě volání. Boční kód jádra, který „zachycuje“ systémové volání, je také nízkoúrovňový materiál, který pravděpodobně nebudete muset hluboce pochopit, alespoň na začátku.

V include/linux/syscalls.h ve vašem zdrojovém adresáři jádra najdete toto:

asmlinkage long sys_mkdir(const char __user *pathname, int mode);

Pak v /usr/include/asm*/unistd.h Najdete toto:

#define __NR_mkdir                              83
__SYSCALL(__NR_mkdir, sys_mkdir)

Tento kód říká mkdir(2) je systémové volání # 83. To znamená, že systémová volání jsou volána číslem, nikoli adresou jako při normálním volání funkce ve vašem vlastním programu nebo na funkci v knihovně spojené s vaším programem. Inline kód lepidla sestavy, který jsem zmínil výše, používá tento způsob k přechodu z prostoru uživatele do prostoru jádra, přičemž vezme vaše parametry spolu s ním.

Dalším důkazem o tom, že věci jsou zde trochu divné, je to, že pro systémová volání není vždy seznam přísných parametrů: open(2), například, může mít 2 nebo 3 parametry. To znamená, že open(2) je přetíženo , funkce C++, nikoli C, přesto je rozhraní syscall kompatibilní s C. (Toto není totéž jako u C's funkce varargs , což umožňuje jedné funkci vzít proměnný počet argumentů.)

K zodpovězení první otázky neexistuje žádný soubor, kde mkdir() existuje. Linux podporuje mnoho různých systémů souborů a každý z nich má vlastní implementaci operace „mkdir“. Abstrakční vrstva, která umožňuje jádru skrýt vše, co stojí za jediným systémovým voláním, se nazývá VFS . Pravděpodobně tedy budete chtít začít kopat fs/namei.c Pomocí vfs_mkdir(). Skutečné implementace kódu pro úpravu systému souborů na nízké úrovni jsou jinde. Například implementace ext4 se nazývá ext4_mkdir(), definovaná v fs/ext4/namei.c .

Pokud jde o vaši druhou otázku, ano, existují zde všechny vzorce, ale ne jediné pravidlo. To, co skutečně potřebujete, je poměrně široké pochopení toho, jak jádro funguje, aby zjistilo, kde byste měli hledat nějaké konkrétní systémové volání. Ne všechna systémová volání zahrnují VFS, takže jejich řetězce hovorů na jádře se nezačínají v fs/namei.c. Například mmap(2) začíná v mm/mmap.c , protože je součástí subsystému správy paměti („mm“) jádra.

Doporučuji vám získat kopii " Porozumění jádru Linux " od Boveta a Cesatiho.

388
Warren Young

Pravděpodobně to neodpovídá přímo na vaši otázku, ale zjistil jsem, že strace je opravdu super, když se snažím pochopit základní systémová volání v akci, která jsou vytvořena i pro nejjednodušší příkazy Shell. např.

strace -o trace.txt mkdir mynewdir

Systém volá po příkazu mkdir mynewdir bude za účelem potěšení z výpisu uloženo do trace.txt.

86
Banjer

Dobré místo pro čtení zdroje Linuxového jádra je Linuxový křížový odkaz (LXR) ¹. Hledání vrátí zadané shody (prototypy funkcí, deklarace proměnných atd.) Kromě výsledků hledání volného textu, takže je to chytřejší než pouhá grep (a také rychlejší).

LXR nerozšiřuje definice preprocesoru. Systémová volání mají všude své jméno přepracováno preprocesorem. Většina systémových volání (všech?) Je však definována jedním z SYSCALL_DEFINEx rodiny maker. Protože mkdir bere dva argumenty, hledání SYSCALL_DEFINE2(mkdir vede k deklarace mkdir syscall :

SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode)
{
    return sys_mkdirat(AT_FDCWD, pathname, mode);
}

oK, sys_mkdirat znamená, že se jedná o mkdirat syscall, takže kliknutí na něj vede pouze k deklaraci v include/linux/syscalls.h, ale definice je těsně nad.

Hlavní úlohou mkdirat je volat vfs_mkdir (VFS je obecná vrstva souborového systému). Když na to klikneme, zobrazí se dva výsledky vyhledávání: prohlášení v include/linux/fs.h a definice o několik řádků výše. Hlavní práce vfs_mkdir má volat implementaci specifickou pro souborový systém: dir->i_op->mkdir. Chcete-li zjistit, jak je implementováno , musíte se obrátit na implementaci individuálního souborového systému a neexistuje pevné a rychlé pravidlo - dokonce to může být modul mimo jádro. strom.

¹ LXR je program indexování. Existuje několik webových stránek, které poskytují rozhraní pro LXR, s mírně odlišnými sadami známých verzí a mírně odlišnými webovými rozhraními. Mají tendenci přicházet a odcházet, takže pokud ten, na který jste zvyklí, není k dispozici, vyhledejte na webu odkaz „linux křížový odkaz“.

Systémová volání jsou obvykle zabalena do makra SYSCALL_DEFINEx(), a proto je prostá grep nenajde:

fs/namei.c:SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode)

Konečný název funkce po rozbalení makra končí sys_mkdir. Makro SYSCALL_DEFINEx() přidá položky typu „plateplate“, jako je kód sledování, který musí mít každá definice syscall.

22
stefanha

Poznámka: .h soubor nebude definovat funkci. Je to deklarováno v tom .h souboru a definováno (implementováno) jinde. To umožňuje kompilátoru zahrnout informace o podpisu funkce (prototyp), který umožní kontrolu typů argumentů a přiřazení návratových typů k libovolným volajícím kontextům v kódu.

Obecně .h (záhlaví) soubory v C se používají k deklarování funkcí a definování maker.

Konkrétně mkdir je systémové volání. Okolo tohoto systémového volání může být obálka GNU libc) (ve skutečnosti je to téměř jistě). Pravou implementaci jádra mkdir lze nalézt hledáním zdrojů jádra a zejména systémových volání.

Všimněte si, že pro každý souborový systém bude také implementována nějaká forma kódu vytváření adresářů. Vrstva VFS (virtuální souborový systém) poskytuje běžné API, do kterého může zavolat vrstva systémových volání. Každý souborový systém musí zaregistrovat funkce pro vrstvu VFS, do které se má zavolat. To umožňuje různým souborovým systémům implementovat vlastní sémantiku, jak jsou adresáře strukturovány (například pokud jsou ukládány pomocí nějakého schématu hašování, aby bylo vyhledávání konkrétních položek efektivnější). Zmíním se o tom, protože pokud prohledáváte zdrojový strom jádra systému Linux, pravděpodobně budete procházet tyto funkce vytváření adresářů specifické pro souborový systém.

17
Jim Dennis

Žádná implementace, kterou jste našli, neodpovídá prototypu v sys/stat.h Možná by hledání úspěšného příkazu zahrnutí s tímto souborem záhlaví bylo úspěšnější?

8
greg0ire

Zde je několik opravdu skvělých blogových příspěvků popisujících různé techniky lovu nízkoúrovňového zdrojového kódu jádra.

6
An̲̳̳drew