PB173 - Ovladače jádra - Linux VII. Komunikace mezi procesy Jiri Slabý Fakulta informatiky Masarykova univerzita 1. 11. 2016 Jiri Slabý (Fakulta informatiky, MU) PB173/04 1. 11. 2016 1/13 Komunikace mezi procesy LDD3 část kap. 6 (zastaralá) Q Čekání na událost • Completion • Wait event a ostatní • Scheduler a probouzení procesů Q Vlákna Jiri Slabý (Fakulta informatiky, MU) PB173/04 1. 11. 2016 2/13 Sekce 1 Čekání na událost Jiri Slabý (Fakulta informatiky, MU) PB173/04 1. 11. 2016 3/13 Jednoduchá komunikace 2 procesy (producent-konzument) • A: čeká na nějakou hotovou práci • B: udělá nějakou práci a oznámí A dokončení A: pokračuje API • linux/completion.h, struct completion O DECLARE_COMPLETIONs, init_completionD • Cekání: wait_for_completion, wait_f or_completion_interruptible (retval) • Dokončení: complete, complete_all ' Příklad static DECLARECOMPLETION(mycomp); static char str [32]; Proces A Proces B wait_for_completion(&my_comp); strcpy(str, "Ahoj"); pr_info("%s\n", str); complete(&my_comp); Jiri Slabý (Fakulta informatiky MU) PB173/04 1. 11. 2016 4/13 Úkol Použití completion O Do pbl73/ll/events doplňte completion O číst se bude, až někdo dokončí zápis o Cekání V read bude možné přerušit Signálem (wait_f or_completion_interruptible) • V případě signálu vraťte -erestartsys O Spusťte 2 instance cat /dev/my_name O Spusťte několikrát echo XXX > /dev/my_name O Pozorujte, co se děje, když použijete • complete a potom: • complete_all Jiri Slabý (Fakulta informatiky, MU) PB173/04 1. 11. 2016 5/13 Složitější komunikace • Cekání na více místech na jinou událost • 3 procesy • A: plní buffer • B: čeká na 100 B • C: čeká na 200 B API • linux/wait.h, wait_queue_head_t O DECLARE_WAIT_QUEUE_HEADS, init_waitqueue_headD • Cekání: wait_event, wait_event_interruptible 9 Dokončení: wake_up, wake_up_all Pozn.: completion je jen wait_queue + počítadlo Jiri Slabý (Fakulta informatiky, MU) PB173/04 1.11.2016 6/13 Složitější komunikace Příklad static DECLARE_WAIT_QUEUE_HEAD(my_wait); static atomicj my_cnt = ATOMICJNIT(O); static char str [512]; A for (a = 0; a < sizeof(str) - 1; a++) { str [atomic_inc_return(&my_cnt) - 1] = 'A'; wake_up_all(&my_wait); msleep(50); } B wait_event(my_wait, atomic_read(&my_cnt) > 100); pr_info("%s\n", str); C if (wait_event_interruptible (my_wait, atomic_read(&my_cnt) > 200)) { pr_info(" interrupted\n"); return; } pr_info("%s\n", str); Jiri Slabý (Fakulta informatiky, MU) PB173/04 1.11.2016 7/13 Úkol Použití wait_queue O V pbl73/ll/events použijte namísto completion wait_queue O číst se bude, až bude v bufferu zapsáno alespoň 5 znaků O Vyzkoušejte zápisem např. 2 a 8 znaků Jiri Slabý (Fakulta informatiky MU) PB 173/04 1. 11. 2016 8/13 Scheduler • Celé je to instruování plánovače (linux/sched.h) Ve skutečnosti je wait_event: • Nastavení typu spícího stavu procesu: set_current_state • D stav: task.uninterruptible • S Stav: task_interruptible • Uspání procesu bez/S timeoutem: schedule/schedule_timeout • A wake_up: • Probuzení procesu: wake_up_process • Popř. S Obsluhou Signálů: signal_pending o completion a wait_queue ulehčuje práci Pamatováním si, koho vzbudit • Případnou kontrolou signálů • Případnou kontrolou vypršení timeoutu • completion má navíc čítač, kolik procesů vzbudit Jiri Slabý (Fakulta informatiky, MU) PB173/04 1. 11. 2016 9/13 Úkol Explicitní čekání O Místo wait.event, použijte funkce z předchozího slidu O Jako vzor prostudujte kód ve funkci af u_read O Zkopírujte jej a použijte Odstraňte zámek a ostatní irelevantní kód O Pozměňte čekací podmínku Bude se čekat alespoň na 2 „a" a 1 „b" v poli Jiri Slabý (Fakulta informatiky, MU) PB173/04 1.11. 2016 10/13 Sekce 2 Vlákna Jiri Slabý (Fakulta informatiky, MU) PB173/04 1.11. 2016 11 /13 kthread • Vytvoření vlákna (procesu) pro výpočty • Bezi v jadre 9 Chování jako uživatelský proces • linux/kthread.h • Vytvoření, zrušení: kthread_run, kthread_stop • Test na skončení ve vlákně: kthread_shouid_stop ' Příklad 1 static int my_fun(void *data) { /* data = my data */ while (1) { wait_event_interruptible (...) ; if (kthread_should_stop()) break; do some work(); } return 0; } struct task_struct *my_t; static int my init(void) { my_t = kthread_run(my_fun, my_data, "my_fun"); return IS ERR(my t) ? PTR ERR(my t) : 0; } static void my exit(void) { kthread stop (my t); } ■i Jiri Slabý (Fakulta informatiky, MU) PB173/04 1.11.2016 12/13 Úkol Vytvoření vlákna O Vytvořte vlákno O Vlákno počká na write až někdo něco zapíše O Přepíše všechny znaky „a" na „b" O Vzbudí všechny v read, kteří čekají na data Q Opakujte v cyklu dokud někdo neodebere modulu O Vyzkoušejte zápisem a čtením do/z /dev/ Jiri Slabý (Fakulta informatiky MU) PB173/04 1.11. 2016 13/13