PB173 - Ovladače jádra - Linux II. Komunikace Jiri Slabý Fakulta informatiky Masarykova univerzita 27. 9. 2016 Jiri Slabý (Fakulta informatiky, MU) PB173/04 27.9.2016 1 /19 Důležité informace • Kolokvium za DÚ • DÚ do příštího cvičení • Login/heslo • vyvoj/vyvoj • GIT: http://github.com/jirislaby/pbl73 • git pull --rebase o Studijní materiály v isu Jiri Slabý (Fakulta informatiky, MU) PB173/04 27.9.2016 2/19 Sekce 1 Komunikace jádro <-> uživatelský prostor Jiri Slabý (Fakulta informatiky, MU) PB173/04 27.9.2016 3/19 Komunikace I. O Voláním funkce: systém call (syscall) • Skok do jádra speciální instrukcí (x86_64: syscall) • O skok se stará übe (f write-^write-^syscaii-nnstrukce) • Drahá operace (přepnutí kontextu) • Do registru se uloží číslo operace • V libc: převodní „tabulka" funkce-^číslo • V jádře: převodní tabulka číslo-^funkce • syscall(__NR_fork) • Demo:__NR_f ork V unistd.h; příklady Z pbl73/02/syscalls/ O Speciální syscall • Knihovna přilinkovaná jádrem • vdso.so Každá nová funkcionalita = nový syscall Jiri Slabý (Fakulta informatiky, MU) PB173/04 27.9.2016 4/19 Úkol V userspace: pomocí funkce syscali vypište nějakou informaci O Inspirujte se V pbl73/02/syscalls/c . c O Použijte syscall a __NR_write Je třeba znát prototypy funkcí. • Většinou jsou dokumentované: man write • Jinak použít Ixr a najít implementaci v jádře Jiri Slabý (Fakulta informatiky, MU) PB173/04 27.9.2016 5/19 Komunikace II. O Speciální soubory v /dev • Komunikace přes soubor • Standardní operace - open, read, ... • Tj. není nutný nový syscall • Identifikované trojicí blokové/znakové, major a minor číslo Většinou major=ovladač, minor=zařízení (tty: c, maj 4, min 0-63) • Blokové (disky apod.) o Komunikace po blocích Nebudeme se jimi zabývat (popsány v LDD) • Znakové (ostatní) • Komunikace po znacích (bajtech) • Zbytek tohoto cvičení • Seznam rezervovaných V Documentation/devices.txt a /proc/devices O Sockety, roury, ... Jiri Slabý (Fakulta informatiky, MU) PB173/04 27.9.2016 6/19 Sekce 2 Znaková zařízení Jiri Slabý (Fakulta informatiky, MU) PB173/04 27.9.2016 7/19 Obsluhované funkce struct f ile_operations (linux/f s .h, LDD3 3. kapitola) Funkce jako: ssize_t (*write) (struct file * file , const char_user *buf, size_t count, loff_t *offp) • f iie->private_data slouží programátorovi (libovolně) o of f p slouží programátorovi (k poznamenání průběhu) •__user značí ukazatel od uživatele (POZOR tomu nevěříme) • Návratové hodnoty (podle návratového typu funkce) • int - záporné = -Echyba, jinak 0 ssize_t - záporné = -Echyba, jinak počet zpracovaných znaků • Vždy podle standardu (např. POSIX) Jiri Slabý (Fakulta informatiky, MU) PB173/04 27.9.2016 8/19 Úkol Práce s Ixr Najděte všechny možné funkce, které lze obsluhovat Najděte struct f ile_operations v Ixr • Projděte strukturu © Najděte možné chybové návratové hodnoty • Najděte eperm v Ixr Projděte ostatní • Podívejte se do man write na možné návratové hodnoty Jiri Slabý (Fakulta informatiky MU) PB173/04 27.9.2016 9/19 Příklad operací struct file_operations my_fops = { .owner = THIS_MODULE, .open = myopen, .write = my_write, }; int my_open(struct inode *inode, struct file * filp ) { filp ->private_data = 3; return 0; } ssize_t my_write(struct file *filp, const char_user *buf, size_t count, loff_t *offp) { /* filp ->private_data is 3 here */ if (count == 0) return -EINVAL; *offp += count; /* remember position for the next time */ return count; /* we "wrote" all bytes */ } Jiri Slabý (Fakulta informatiky, MU) PB173/04 27.9.2016 10/19 Úkol Obsluha open, read, write, release (tj. Close) O Definice struct f ile_operations O Vytvořte funkce dle prototypu z f ile.operations (Ixr) • Open a release s nějakým printk a return • Read a write prozatím jen s return • Návratové hodnoty • Open a release vracejí 0 (žádná chyba) • Read též (0 znamená EOF) • Write vrací count (zapsáno vše) O Jen zkuste přeložit • Nemá smysl vkládat Jiri Slabý (Fakulta informatiky MU) PB173/04 27.9.2016 11 /19 Vytvoření znakového zařízení o LDD3 3. a 6. kapitola • 2-3 kroky O Registrace rozsahu major+minor (v moduie_init) • Buď alloc_chrdev_region (chci Čísla přidělit), anebo register_chrdev_region (Čísla mám), nakonec unregister_chrdev_region (linux/fs.h) 9 Přidání záznamu do /proc/devices O Registrace jednotlivých minorů (při připojení zařízení) • cdev_init, cdev_add, cdev_del (linux/cdev.h) • Parametr pro cdev_init je struct f ile_operations • Po odpovídajícím mknod lze zařízení používat O Podat zprávu udev (vytvoření /dev/*) - nepovinné • device_create, device_destroy (linux/device.h) • Předem je potřeba vytvořit class (v module_init) Jiri Slabý (Fakulta informatiky, MU) PB173/04 27.9.2016 12/19 Úkol Vytvoření znakového zařízení O Definujte si globální struct cdev (znakové zařízení) O V module_init Zavolejte alloc_chrdev_region(&dev, 0, 10, "jméno") • dev je návratová hodnota typu dev_t • Vypište Si MAJOR (dev) a MINOR(dev) 9 Inicializujte SVOU globální struct cdev (cdev_init) • Přidejte svoje struct cdev do systému (cdev_add a dev shora) O V module_exit • cdev_del • unregister_chrdev_region O make a insmod Q Ověřte vytvoření v /proc/devices O Podle výpisu Z 2. bodu: mknod soubor c MAJ MIN O Vyzkoušejte cat soubor Jiri Slabý (Fakulta informatiky MU) PB173/04 27.9.2016 13/19 Uživatelská paměť • Něco, čemu nelze věřit (NULL, ukazatel do tabulek oprávněn o POZOR: nutnost kontroly • copy_from_user, copy_to_user • „memcpy" S kontrolou • Vracejí počet NEzkopírovaných znaků (tj. 0 znamená OK) • get_user, put_user • „var = *buf" a „*buf = var" S kontrolou • Tzn. jen pro primitiva (char, short, int, long) • Vracejí 0 nebo chybu (záporná hodnota) • Definované V linux/uaccess .h Demo: pbl73/02/ Jiri Slabý (Fakulta informatiky MU) PB173/04 27.9.2016 14/19 Úkol Dopsat těla funkcí read a write tak, aby zpracovávala data O write vypíše uživatelský buffer pomocí printk • copy_f rom_user (při chybě return -EFAULT) • Nezapomeňte ukončit zkopírovaný řetězec použitím \o Q read bude vracet řetězec „Ahoj" • copy_to_user Jiri Slabý (Fakulta informatiky MU) PB173/04 27.9.2016 15/19 Vytvoření znakového zařízení pomocí mise Mise vrstva • Stačí-li 1 minor (málokdy) Dělá všechnu práci včetně volání udev Potřebujeme • Definici mise zařízení (struct misedevice) - minor číslo, jméno zařízení v /dev, atd. • Opět struct file_operations • struct cdev není třeba • int misc_register(struct misedevice *misc) • void misc_deregister(struct misedevice *misc) • Objeví se V /proc/misc a /dev • linux/misedevice.h Jiri Slabý (Fakulta informatiky MU) PB173/04 27.9.2016 16/19 Úkol Vytvořit mise zařízení O Definujte Si nějakou struct misedevice • minor = MISC_DYNAMIC_MINOR (automaticky přidělit) • name-jméno vytvářeného zařízení • f ops — vaše struct f ile_operations O misc_register/deregister do module_init/exit O make a insmod O Ověřte vytvoření v /proč/mise Q Vyzkoušejte cat /dev/ (jméno shora) Jiri Slabý (Fakulta informatiky MU) PB173/04 27.9.2016 17/19 Datové typy o Jádro a proces může běžet s různými bitovými šířkami (32, 64-bit) • Problém s ukazateli a long proměnnými • Jiná délka dat Jiné zarovnání struktur Uživatel (32-bit) Jádro (64-bit) data ... 4 bajty na offsetu 4 struct my { char x; void *data; }; data ... 8 bajtů na offsetu 8 Jiri Slabý (Fakulta informatiky MU) PB173/04 27.9.2016 18/19 Pevné typy v jádře z hlediska počtu bitů • linux/types.h • __u8, __ul6, __u32, __u64 • __s8, __sl6, __s32, __s64 • Ukazatele musí být v union s __u64 struct good { _u64 flags; _s16 index; union { void *data; _u64 filler ; }; } my; read(fd, &my, sizeof(my)); ioctl(fd, DO_SOMETHING, &my); struct bad { unsigned long flags; short index; void *data; } my; Jiri Slabý (Fakulta informatiky, MU) PB173/04 27.9.2016 19/19