PB173 - Ovladače jádra - Linux XI. Komunikace mezi procesy Jiri Slabý Fakulta informatiky Masarykova univerzita 10. 12. 2015 Jiri Slabý (Fakulta informatiky, MU) PB173/04 10. 12. 2015 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 10.12.2015 2/ 13 Sekce 1 Čekání na událost Jiri Slabý (Fakulta informatiky, MU) PB173/04 10. 12. 2015 3/ 13 Jednoduchá komunikace 2 procesy (producent-konzument) • A: čeká na nějakou hotovou práci o B: udělá nějakou práci a oznámí A dokončení • A: pokračuje API • linux/completion.h, struct completion • DECLARE_COMPLETIONs, init_completionD • Cekání: wait_for_completion, wait_f or_completion_interruptible (retval) • Dokončení: complete, complete_all Příklad static DECLARE_COMPLETION(my_comp); static char str [32]; A B wait_for_completion(&my_comp); strcpy(str, "Ahoj"); pr_info("%s\n", str); complete(&my_comp); Jiri Slabý (Fakulta informatiky, MU) PB173/04 10. 12. 2015 4/ 13 Úkol Použití completion O Do pbl73/ll/events doplňte completion O číst se bude, až někdo dokončí zápis • Čekání v read bude možné přerušit signálem (wait_for_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 10. 12. 2015 5/ 13 Složitější komunikace • Čeká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 • DECLARE_WAIT_QUEUE_HEADS, init_waitqueue_headD • Cekání: wait_event, wait_event_interruptible • Dokončení: wake_up, wake_up_all Pozn.: completion je jen wait_queue + počítadlo Jiri Slabý (Fakulta informatiky, MU) PB173/04 10. 12. 2015 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); 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 10. 12. 2015 7/ 13 Úkol Použití wait_queue O V pbl73/ll/events použijte namísto completion wait.queue Q Číst se bude, až bude v bufferu zapsáno alespoň 5 znaků Jiri Slabý (Fakulta informatiky, MU) PB173/04 10. 12. 2015 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 • 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 10. 12. 2015 9/ 13 Úkol Explicitní čekání O Místo wait.event, použijte funkce z předchozího slidu Q Jako vzor prostudujte kód ve funkci af u.read Q 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 10. 12. 2015 10/13 Sekce 2 Vlákna Jiri Slabý (Fakulta informatiky, MU) PB173/04 10. 12. 2015 11/13 kthread • Vytvoření vlákna (procesu) pro výpočty • Bezi v jadre • 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 static int my_fun(void *data) struct task_struct *my_t; static int my_init(void) { /* data = my_data */ while (1) { wait_event_interruptible (...) ; if (kthread_should_stop()) break; do_some_work(); static void my_exit(void) my_t = kthread_run(my_fun, my_data, "my_fun"); return IS_ERR(my_t) ? PTR_ERR(my_t) : 0; return 0; kthread_stop(my_t); Jiri Slabý (Fakulta informatiky, MU) PB173/04 10. 12. 2015 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 0 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 10. 12. 2015 13/13