PB173 - Ovladače jádra - Linux II. Komunikace Jiri Slabý ITI, Fakulta informatiky 24. 9. 2013 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 • Studijní materiály v iSu J. Slabý (ITI, Fl) PB173/02 24.9.2013 2/ 19 Část I Komunikace jádro ^ uživatelský prostor J. Slabý (ITI, Fl) PB173/02 24.9.2013 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á NbC (f write^write^syscall^instrukce) • Drahá operace (přepnutí kontextu) • Do registru se uloží číslo operace • V jádře: tabulka číslo-funkce syscall(__NR_fork) • Demo: Ixr ->•__NR_f ork; příklady O Speciální syscall • vdso.so Každá nová funkcionalita = nový syscall J. Slabý (ITI, Fl) PB173/02 24.9.2013 4/ 19 Úkol V userspace: pomocí syscali vypsat nějakou informaci syscall a __NR_write Je třeba znát prototypy funkcí, a Většinou jsou dokumentované: man write • Jinak použít Ixr J. Slabý (ITI, Fl) PB173/02 24.9.2013 5/ 19 Komunikace II. Q Speciální soubory v /dev • Komunikace přes soubor (není nutný nový syscall) • Seznam V Documentation/devices .txt a/proc/devices • Identifikované jako major a minor čísla • Většinou major=ovladač, minor=zařízení (tty: 4, 0-63) • Blokové (disky apod.) • Komunikace po blocích • Nebudeme se jimi zabývat (popsány v LDD) • Znakové (ostatní) • Komunikace po znacích (bajtech) • Viz následující slidy 0 Sockety, roury, ... J. Slabý (ITI, Fl) PB173/02 24.9.2013 6/ 19 Část II Znaková zařízení J. Slabý (ITI, Fl) PB173/02 24.9.2013 7/ 19 Obsluhované funkce struct file_operations (linux/fs.h) • Funkce jako: ssize.t (* write) (struct file * file , const char ..user *buf, size.t count, loff.t * of f p) a f ile->private_data slouží programátorovi (libovolně) • offp slouží programátorovi (k poznamenání průběhu) •__user značí ukazatel od uživatele (tomu nevěříme) a Návratové hodnoty 9 int - záporné = -Echyba, jinak 0 • ssize_t - záporné = -Echyba, jinak počet zpracovaných znaků • Vždy podle standardu (např. POSIX) J. Slabý (ITI, Fl) PB173/02 24.9.2013 8/ 19 Úkol O Najděte všechny možné funkce, které lze obsluhovat • Najděte struct f ile_operations V Ixr 9 Projděte strukturu O 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 J. Slabý (ITI, Fl) PB173/02 24.9.2013 9/ 19 Příklad operací struct file-operations my.fops = { .owner = THIS.MODULE, .open = my.open, . 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 * off p) { /* filp ->private.data is 3 here */ if (count == 0) return -EINVAL; return 0; } J. Slaby (ITI, Fl) PB173/02 24.9.2013 10/ 19 Úkol Obsluha open, read, write, release (tj. Close) O Definice struct f ile_operations O Vytvoření funkcí dle prototypu z f iie_operations (Ixr) • Open a release s nějakým printk • Read a write prozatím prázdná těla • Návratové hodnoty • Open a release vracejí 0 (žádná chyba) • Read též (0 = EOF) • Write vrací count (zapsáno vše) J. Slabý (ITI, Fl) PB173/02 24.9.2013 11 / 19 Vytvoření znakového zařízení • LDD3 3. a 6. kapitola a 2-3 kroky O Registrace rozsahu major+minor (v module_init) • alloc_chrdev_region, register_chrdev_region, unregister_chrdev_region (linux/fs.h) • Přidání záznamu do /proc/devices O Registrace jednotlivých minorů (při objevení 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 0 Podat zprávu udev (vytvoření /dev/*) - nepovinné • device_create, device_destroy(linux/device.h) • Předem je potřeba vytvořit class (moduie_init) J. Slabý (ITI, Fl) PB173/02 24.9.2013 12/ 19 Úkol Vytvoření znakového zařízení O Globální struct cdev O V module_init alloc_chrdev_region(&dev, 0, 1, "jméno") • Vypište MAJOR(dev) a MINOR(dev) • cdev_init • cdev_add O V module_exit • cdev_del 9 unregister_chrdev_region O insmod 0 Ověřte vytvoření v /proc/devices O Podle výpisu Shora: mknod soubor c MAJ MIN O Vyzkoušejte cat soubor J. Slabý (ITI, Fl) PB173/02 24.9.2013 13/ 19 Vytvoření znakového zařízení pomocí mise Mise vrstva • Stačí-li 1 minor • Dělá všechnu práci včetně volání udev • Potřebujeme • Definici mise zařízení (struct misedevice) • Opět struct file_operations • misc_register, misc_deregister • Objeví se V /proc/misc a /dev • linux/miscdevice.h J. Slabý (ITI, Fl) PB173/02 24.9.2013 14/ 19 Úkol Vytvořit mise zařízení O Definice struct misedevice • minor = MISC_DYNAMIC_MINOR • name - jméno vytvářeného zařízení • fops - předchozí O misc_register/deregister do module_init/exit O insmod O Ověřte vytvoření v /proc/misc 0 Vyzkoušejte cat /dev/name (name je shora) J. Slabý (ITI, Fl) PB173/02 24.9.2013 15/ 19 Uživatelská paměť • Něco, čemu nelze věřit (NULL, ukazatel do tabulek oprávnění,...) • Nutnost kontroly POZOR • copy_from_user, copy_to_user • „memcpy" S kontrolou • Vracejí počet NEzkopírovaných znaků (0 = OK) • get_user, put_user 9 Jen primitiva (char, short, int, long) • „var = *buf" a „*buf = var" S kontrolou • Vracejí 0 nebo chybu (záporná hodnota) • Definované V linux/uaccess.h Demo: pb173/02 J. Slabý (ITI, Fl) PB173/02 24.9.2013 16/ 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) • Ukončit zkopírovaný řetězec použitím \o Q read bude vracet „Ahoj" • copy_to_user J. Slabý (ITI, Fl) PB173/02 24.9.2013 17/ 19 Datové typy • 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 J. Slabý (ITI, Fl) PB173/02 24.9.2013 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 bad { unsigned long flags; short index; void *data; } my; struct good { _.u64 flags; „s16 index; union { void *data; „u64 filler }; } my; read(fd, &my, sizeof(my)); ioctl(fd, DO.SOMETHING, &my); J. Slaby (ITI, Fl)