PB173 - Ovladače jádra - Linux VI. Datové typy Jiri Slabý Fakulta informatiky Masarykova univerzita 5. 11. 2015 Jiri Slabý (Fakulta informatiky, MU) PB173/04 5. 11. 2015 1 /14 Obsah cvičení Q Základní typy • Chyby jako ukazatele Q Datové struktury • Seznam • FIFO Jiri Slabý (Fakulta informatiky, MU) PB173/04 5.11.2015 2/ 14 Datové typy LDD3 kap. 11 • Základní typy • Endianita (pořadí bytů) • Datové struktury (seznam, FIFO) Jiri Slabý (Fakulta informatiky, MU) PB173/04 5. 11. 2015 3/ 14 Sekce 1 Základní typy Jiri Slabý (Fakulta informatiky, MU) PB173/04 5. 11. 2015 4/14 Základní typy • char, short, int, long, long long (+ unsigned) • u8, ul6, u32, u64, __u8, __ul6, __u32, __u64 • s8, sl6, s32, s64, __s8, __sl6, __s32, __s64 sizeof základních typů pro různé architektury arch char short int long ptr long long alpha 1 2 4 8 8 8 arm 1 2 4 4 4 8 ia64 1 2 4 8 8 8 m68k 1 2 4 4 4 8 mips 1 2 4 4 4 8 ppc 1 2 4 4 4 8 spare 1 2 4 4 4 8 sparc64 1 2 4 8 8 8 x86_32 1 2 4 4 4 8 x86_64 1 2 4 8 8 8 Jiri Slabý (Fakulta informatiky, MU) PB173/04 5. 11. 2015 5/14 Základní typy sizeof dalších typů (ukazatelů) arch long virt phys x86_32 4 4 4 x86_32+PAE 4 4 4.5+ x86_64 8 8 8 Pro práci s fyzickou adresou long/ukazatel nestačí • Ale u64 může být zbytečné (čisté 32-bity) • Proto speciální typy {POZOR) • phys_addr_t (RAM, za MMU) • Anebo long, ale pak v něm uchovávat pf n (phys/PAGE_siZE) • dma_addr_t (RAM, před IOMMU) o resource_size_t (PCI prostor apod.) Úkol: opravte typy v pb173/06 (jen první TODO) Jiri Slabý (Fakulta informatiky, MU) PB173/04 5. 11. 2015 6/14 Pořadí bytů Číslo 0x12345678 reprezentované v paměti Pořadí Příklad architektury Offset v paměti 0 12 3 Big-endian Little-endian Mixed-endian arm, s390 arm, x86 PDP-11 0x12 0x34 0x56 0x78 0x78 0x56 0x34 0x12 0x34 0x12 0x78 0x56 Pro typy o velikosti větší než 1 je nutné znát pořadí • Interpretace dat z/do zařízení • Specifikace • CPU (příklady nahoře) • PCI: LE • Síťový provoz: BE • ... Jiri Slabý (Fakulta informatiky, MU) PB173/04 5.11.2015 7/ 14 Funkce pro pořadí bytů • asm/byteorder.h • __leXX, __beXX • cpu_to_leXX, cpu_to_beXX • leXX_to_cpu, beXX_to_cpu • XX G {16,32,64} • ntohs, ntohl, htons, htonl Úkol: doplňte tělo decode_and_print v pb173/06 (druhé TODO) Jiri Slabý (Fakulta informatiky, MU) PB173/04 5. 11. 2015 8/14 Chyby jako ukazatele • void *funkce() • Jak vrátit chytřejší chybu než NULL? • Díra na konci adresového prostoru • Tj. nevalidní ukazatel (dereference by způsobila pád) o Např. Oxf f f f f f f f f f f 00000-Oxf f f f f f f f f f f f f f f f (x86_64) • Lze použít k zakódování chyby • void *ptr = ERR_PTR(-Eerror) • IS_ERR(ptr) =4> int err = PTR.ERR(ptr) • IS.ERR(NULL) je false Úkol: přepište err or .handling v pb173/06 (třetí TODO) Jiri Slabý (Fakulta informatiky, MU) PB173/04 5. 11. 2015 9/14 Sekce 2 Datové struktury Jiri Slabý (Fakulta informatiky, MU) PB173/04 5. 11. 2015 10/14 Seznam I • linux/list.h • struct list_head (obsahuje prev, next) • Jak samotný seznam (počátek), tak jeho prvky • LIST_HEAD(my_list)s,INIT_LIST_HEAD(&my_list)D • list_add(co, kam), list_add_tail, list_del • list_move, list_move_tail naalokujte 20 stránek a v seznamu si je pamatujte. struct my_struct { struct listjnead list ; }; LIST_HEAD(my_list); int a; struct my_struct *s; s = kmalloc(sizeof(*s), GFP_KERNEL); if (ls) { ... } s >a = 10; list_add(&s->list, &my_list); /* list_add_tail (&s->list, &my_list); */ Jiri Slabý (Fakulta informatiky, MU) PB173/04 5. 11. 2015 11/14 Seznam II • linux/list.h • list_empty • Jedna položka: list.entry, list.first_entry • Iterace: list_f or_each_entry(. . .){ ... } (jako f or), list_for_each_entry_reverse(...){ ... } • *_saf e varianty - pokud měním aktuální člen seznamu Příklad struct my_struct *s, *s1; s = list_first_entry (&my_list, struct my_struct, list); s= list_entry (s—>list. next, struct my_struct, list); /* or */ list_for_each_entry(s, &my_list, list) { s->a;} list_for_each_entry_safe(s, s1, &my_list, list) { list_del (&s->list); } Úko předchozích 20 stránek uvolněte. Jiri Slabý (Fakulta informatiky, MU) PB173/04 5. 11. 2015 12/14 FIFO • linux/kfifo.h, samples/kfifo/* • struct kfifo • Statické: declare.kfifo + init.kfifo • Dynamické: kfifo_alloc(&fifo, size, gfp_*),kfifo.free • Zápis: kf if o_in(&f if o, buf, count) • Čtení: kf if o_out(&f if o, buf, count) • Obsazeno:kfifo_ien(&fifo) • Volno: kf ifo_avail(&fifo) Jiri Slabý (Fakulta informatiky, MU) PB173/04 5. 11. 2015 13/14 Úkol Práce s FIFO (linux/kf ifo.h) O Globální FIFO 8 intŮ (DECLARE.KFIFO) O INIT.KFIFO O Zapisovat čísla (kf if o_in) dokud je místo O Vypsat všechna čísla (kf if o_out + kf if o_ien) Pozn.: ve starších jádrech je jiné rozhraní: • jen dynamicky: my_f if o=kf if o.ailoc • __kfifo_put=kfifo_in • __kfifo_get=kfifo_out • __kfifo_len=kfifo_len • avail není Jiri Slabý (Fakulta informatiky, MU) PB173/04 5. 11. 2015 14/14