Ïîòîêè Îïåðàöèîííûå ñèñòåìû 2011/12 Òàòüÿíà Ðîìàíîâà 24 ñåíòÿáðÿ 2011 ã. 1 / 29 Ïëàí íà ñåãîäíÿ I I I I I I ×óòü-÷óòü ïðî IPC. Ïîòîêè. Ïðèìåðû ìíîãîïîòî÷íûõ ïðèëîæåíèé. Óïðàâëåíèå ïîòîêàìè. Âîçìîæíûå âàðèàíòû ðåàëèçàöèè (ïîòîêè ÿäðà, ëåãêîâåñíûå ïðîöåññû, ïîòîêè â ïðîñòðàíñòâå ïîëüçîâàòåëÿ). Ïðèìåðû ðåàëèçàöèé. 2 / 29 Ìàòåðèàëû I I I I I I CS 162, ëåêöèè 3, 4, 5 (âèäåî ëåêöèè íà YouTube). Þ. Âàõàëèÿ, UNIX èçíóòðè, ãëàâà 3. Ý. Òàíåíáàóì, Ñîâðåìåííûå îïåðàöèîííûå ñèñòåìû, ãëàâà 2 (îò ïîòîêîâ äî ìåæïðîöåññíîãî âçàèìîäåéñòâèÿ) http://en.wikipedia.org/wiki/Thread_(computer_science) Anderson et al. Scheduler Activations: Eective Kernel Support for the User-Level Management of Parallelism, 1991. Drepper, Molnar. The Native POSIX Thread Library for Linux, 2005. 3 / 29 Ïîòîêè è ïðîöåññû Ïîòîêè è ïðîöåññû 4 / 29 Ïîòîêè è ïðîöåññû Ìåæïðîöåññíîå âçàèìîäåéñòâèå Îãðàíè÷åíèÿ ïðîöåññîâ Ïðîáëåìû: I Ñîçäàâàòü íîâûé ïðîöåññ äîðîãî. I Òðåáóåòñÿ ïåðåêëþ÷åíèå êîíòåêñòà. I Âñå îïåðàöèè ÷åðåç ñèñòåìíûå âûçîâû. I Ó êàæäîãî ïðîöåññà ñâî¼ àäðåñíîå ïðîñòðàíñòâî. 5 / 29 Ïîòîêè è ïðîöåññû Ìåæïðîöåññíîå âçàèìîäåéñòâèå Ìåæïðîöåññíîå âçàèìîäåéñòâèå I I I I Ñèãíàëû Ôàéëû è êàíàëû (pipe) Ïåðåäà÷à ñîîáùåíèé (â ò. ÷. ïî ñåòè) Ðàçäåëÿåìàÿ ïàìÿòü, îòîáðàæåíèå ôàéëîâ â ïàìÿòü (mmap) 6 / 29 Ïîòîêè è ïðîöåññû Ïîíÿòèå ïîòîêà Ïîíÿòèå ïîòîêà ðåñóðñû I I I I Ïðîöåññ: àäðåñíîå ïðîñòðàíñòâî îòêðûòûå ôàéëû èíôîðìàöèÿ î ïðèâèëåãèÿõ îáðàáîò÷èêè ñèãíàëîâ Ïîòîê I ìèíèìàëüíàÿ åäèíèöà ïëàíèðîâàíèÿ I ðàçäåëÿåò ñ äðóãèìè ïîòîêàìè äàííûå è êîä I ðåàëèçàöèè ìîãóò ðàçëè÷àòüñÿ I I I I ïîòîê âûïîëíåíèÿ ñ÷åò÷èê êîìàíä ðåãèñòðû ñ ïåðåìåííûìè ñòåê òåêóùåå ñîñòîÿíèåå 7 / 29 Ïîòîêè è ïðîöåññû Ïîíÿòèå ïîòîêà Ìíîãîïîòî÷íûå ïðîãðàììû I I Ïîòîêè ìîãóò âûïîëíÿòüñÿ îäíîâðåìåííî. Îòäåëüíîå àäðåñíîå ïðîñòðàíñòâî =⇒ çàùèòà äðóãèõ ïðîöåññîâ è ñèñòåìû. 8 / 29 Ïîòîêè è ïðîöåññû Ïîíÿòèå ïîòîêà Äîáðî èëè çëî? Ïðåèìóùåñòâà: 1. Îäèí ïîòîê çàáëîêèðîâàí, äðóãîé ðàáîòàåò (âåðíî è äëÿ ïðîöåññîâ) 2. Ðàçäåëÿþò ðåñóðñû I I I ïðîùå îãðàíèçîâàòü âçàèìîäåéñòâèå äåøåâëå ñîçäàâàòü è óíè÷òîæàòü äåøåâëå ïåðåêëþ÷àòüñÿ ìåæäó ïîòîêàìè (ïî÷åìó?) 3. Ðàáîòà íà ìíîãîïðîöåññîðíûõ ìàøèíàõ Íåäîñòàòêè: 1. Îñòóòñòâèå çàùèòû ïîòîêîâ äðóã îò äðóãà 2. Òðóäíîñòè ïðè ðåàëèçàöèè I I I Êàêîé ïîòîê ïðèíèìàåò ñèãíàëû? Êàê ðàçìåñòèòü ñòåê? Íå ñîâñåì ãëîáàëüíûå äàííûå (errno) 3. Íåîáõîäèìîñòü ñèíõðîíèçàöèè 9 / 29 Ïîòîêè è ïðîöåññû Ïðèìåðû ïðèëîæåíèé Ïðèìåð: òåêñòîâûé ðåäàêòîð I I I Îäèí ïîòîê âçàèìîäåéñòâóåò ñ ïîëüçîâàòåëåì Âòîðîé â ôîíîâîì ðåæèìå ôîðìàòèðóåò äîêóìåíò Òðåòèé ïåðèîäè÷åñêè ñîõðàíÿåò äàííûå íà äèñê 10 / 29 Ïîòîêè è ïðîöåññû Ïðèìåðû ïðèëîæåíèé Ïðèìåð: âåá-ñåðâåð Ïîòîê äèñïåò÷åð ïðèíèìàåò çàïðîñû è âûñòðàèâàåò èõ â î÷åðåäü. I Åñëè åñòü ñâîáîäíûé ðàáî÷èé ïîòîê ñâÿçàòü åãî ñ çàïðîñîì. I Ðàáî÷èé ïîòîê: ïîèñêàòü ñòðàíèöó â êýøå, åñëè åñòü, îòäàòü èç êýøà, åñëè íåò, ñêà÷àòü è ïîëîæèòü â êýø. Ðàáî÷èé ïîòîê: Äèñïåò÷åð: while(1) { I while(1) { get_next_request(); start_worker(); } } wait_for_work(); look_for_page_in_cache(); if (not_found()) wget_and_store(); return_page(); Íóæíà ñèíõðîíèçàöèÿ ïîòîêîâ ïðè ðàáîòå ñ êýøåì. Àëüòåðíàòèâà àñèíõðîííûé ââîä-âûâîä è ìîäåëü êîíå÷íîãî àâòîìàòà. 11 / 29 Óïðàâëåíèå ïîòîêàìè Óïðàâëåíèå ïîòîêàìè 12 / 29 Óïðàâëåíèå ïîòîêàìè Ðåñóðñû ïîòîêà Ðåñóðñû ïîòîêà Îáùèå äëÿ âñåõ ïîòîêîâ: I Äàííûå (ãëîáàëüíûå ïåðåìåííûå, êó÷à) I Ââîä/âûâîä (ôàéëîâàÿ ñèñòåìà, ñåòåâûå ñîåäèíåíèÿ) Ó êàæäîãî ïîòîêà ñâîè: I Áëîê óïðàâëåíèÿ ïîòîêîì (thread control block, TCB): ñïåöèàëüíûå (PC, SP) è îáùèå ðåãèñòðû ïðîöåññîðà, ñîñòîÿíèå ïðîöåññà, ïðèîðèòåò, èíôîðìàöèÿ ïëàíèðîâùèêà. I Ñòåê 13 / 29 Óïðàâëåíèå ïîòîêàìè Ðåñóðñû ïîòîêà Ïðèìåð èñïîëüçîâàíèÿ ñòåêà I I  ñòåêå õðàíÿòñÿ ëîêàëüíûå ïåðåìåííûå (íåëüçÿ âîçâðàùàòü àäðåñ!). Ñîõðàíåíèå â ñòåêå àäðåñà âîçâðàòà äàåò âîçìîæíîñòü èñïîëüçîâàòü ðåêóðñèþ. 14 / 29 Óïðàâëåíèå ïîòîêàìè Ðåñóðñû ïîòîêà Ñòåê ïîòîêà Ïðîãðàììà ñ äâóìÿ ïîòîêàìè: main() { create_thread(get_primes("primes.txt")); create_thread(hello("hello.txt")); } I I I I Êàê ðàñïîëîæåíû ñòåêè ïîòîêîâ? Êàêîãî ðàçìåðà äîëæåí áûòü ñòåê? Ìîæåò ëè îäèí ïîòîê èñïîðòèòü ñòåê èëè TCB äðóãîãî? Ìîæíî ëè çàùèòèòüñÿ îò ïåðåïîëíåíèÿ ñòåêà? 15 / 29 Óïðàâëåíèå ïîòîêàìè Ïåðåêëþ÷åíèå ìåæäó ïîòîêàìè Êîãäà ïåðåêëþ÷àòüñÿ? 1. Ïîòîê ñàì îòäàåò ïðîöåññîð, ïåðåõîäÿ â ñîñòîÿíèå ñíà èëè âûçûâàÿ yield íå íóæíî áåñïîêîèòüñÿ î ñèíõðîíèçàöèè åñòü ðèñê íèêîãäà íå ïîëó÷èòü óïðàâëåíèå get_primes() { while(1) { get_next_prime(); yield(); } } I I 2. Ïðåðûâàíèå (íàïðèìåð, ïî òàéìåðó) I I I I âåêòîð ïðåðûâàíèé (àäðåñà ïðîöåäóð-îáðàáîò÷èêîâ) àïïàðàòíî: ñîõðàíåíèå PC è ñîñòîÿíèÿ â ñòåêå, ïåðåõîä ïî àäðåñó èç âåêòîðà ïðåðûâàíèé îáðàáîò÷èê: çàâåðøåíèå ñîõðàíåíèÿ, ïåðåóñòàíîâêà SP íà ñâîé ñòåê, îáðàáîòêà ïðåðûâàíèÿ âîññòàíîâëåíèå ñîñòîÿíèÿ ïîòîêà èëè ïåðåõîä ê ñëåäóþùåìó 16 / 29 Óïðàâëåíèå ïîòîêàìè Ïåðåêëþ÷åíèå ìåæäó ïîòîêàìè Êàê ïðîèñõîäèò ïåðåêëþ÷åíèå? A() { B(); } B() { while(1) { yield(); } } Çàïóñêàåì 2 ïîòîêà: S è Ò. Êàæäûé íà÷èíàåò âûïîëíÿòü ïðîöåäóðó A(). Ïðîöåäóðà switch ñîõðàíÿåò ðåãèñòðû ñòàðîãî òðåäà è çàãðóæàåò ðåãèñòðû íîâîãî =⇒ ñ èçìåíåíèåì SP è âûçîâîì return îêàçûâàåòñÿ â íîâîì ïîòîêå! Çà÷åì ïåðåõîäèòü èç ðåæèìà çàäà÷è â ðåæèì ÿäðà? 17 / 29 Óïðàâëåíèå ïîòîêàìè Ðàáîðà ñ ïîòîêàìè Ñîçäàíèå I I I I create_thread(fn_ptr, args_ptr, stack_size); Ñèãíàòóðà ôóíêöèè çàâèñèò îò èñïîëüçóåìîé áèáëèîòåêè. Ïðîâåðêà àðãóìåíòîâ â ðåæèìå ÿäðà. Âûäåëåíèå TCB, ñòåêà è äîáàâëåíèå â î÷åðåäü ïëàíèðîâùèêà, àäðåñ âîçâðàòà ïðîöåäóðà tread_root(); thread_root() { do_startup(); //ñòàòèñòèêà user_mode_switch(); call fn_ptr(args_ptr); thread_nish(); } 18 / 29 Óïðàâëåíèå ïîòîêàìè Ðàáîðà ñ ïîòîêàìè Çàâåðøåíèå I I I I thread_nish() âûïîëíÿåòñÿ â ðåæèìå ÿäðà thread_join(Thread t) îæèäàíèå çàâåðøåíèÿ ïîòîêà t (ïî÷òè êàê wait) Ïðè çàâåðøåíèè ðàçáóäèòü âñåõ, êòî ñäåëàë join òåêóùåìó ïîòîêó Íå ìîæåò îñâîáîäèòü ñòåê, â êîòîðîì ðàáîòàåò. Íî ñëåäóþùèé ïîòîê ìîæåò. 19 / 29 Ðåàëèçàöèè ïîòîêîâ Ðåàëèçàöèè ïîòîêîâ 20 / 29 Ðåàëèçàöèè ïîòîêîâ Ïîòîêè â ïðîñòàíñòâå ÿäðà Ïîòîêè ÿäðà I I I I I Íå ñâÿçàíû ñ ïðèêëàäíûì ïðîöåññîì. Ñîçäàþòñÿ, ðàáîòàþò è óíè÷òîæàþòñÿ âíóòðè ÿäðà. Èñïîëüçóþò òîëüêî ñòåê ÿäðà. Áûñòðîå ïåðåêëþ÷åíèå íåò íåîáõîäèìîñòè ïåðåõîäèòü â ðåæèì çàäà÷è èëè ïåðåêëþ÷àòü àäðåñíîå ïðîñòðàíñòâî. Èñïîëüçóþòñÿ äëÿ ðàáîòû ñèñòåìíûõ ïðîöåññîâ-äåìîíîâ. 21 / 29 Ðåàëèçàöèè ïîòîêîâ Ïîòîêè â ïðîñòàíñòâå ÿäðà Ëåãêîâåñíûå ïðîöåññû (LWP) I I I Ðåàëèçîâàíû ïîâåðõ ïîòîêîâ ÿäðà Ïëàíèðóþòñÿ ÿäðîì =⇒ ìîãóò ïàðàëåëëèòüñÿ íà ïðîöåññîðû. Ñîçäàíèå, ïåðåêëþ÷åíèå è ñèíõðîíèçàöèÿ ÷åðåç ñèñòåìíûå âûçîâû. 22 / 29 Ðåàëèçàöèè ïîòîêîâ Ïîòîêè â ïðîñòðàíñòâå ïîëüçîâàòåëÿ Ïîòîêè â ïðîñòðàíñòâå ïîëüçîâàòåëÿ I I I I I Áèáëèîòåêà ïîòîêîâ ñàìà ðàçìåùàåò èõ â ðàìêàõ îäíîãî ïðîöåññà. Îíà æå çàíèìàåòñÿ ïëàíèðîâàíèåì. Äëÿ ÎÑ ýòî îäèí ïðîöåññ. Áûñòðî ñîçäàþòñÿ, ëåãêî ïåðåêëþ÷àþòñÿ. Ìîãóò èñïîëüçîâàòü íåâûòåñíÿþùåå ïëàíèðîâàíèå (yield), ÷òî ñíèæàåò ðàñõîäû íà ñèíõíîíèçàöèþ. 23 / 29 Ðåàëèçàöèè ïîòîêîâ Ðàçëè÷íûå ìîäåëè ïîòîêîâ Ìîäåëè 1:1, N:1, M:N 1. 1:1, ïîòîêè â ïðîñòðàíñòâå ÿäðà. Íà êàæäûé ïîòîê âûäåëÿåòñÿ ïîòîê ÿäðà. Ñàìàÿ ïðîñòàÿ ðåàëèçàöèÿ. Íåîáõîäèìà ïîääåðæêà ñî ñòîðîíû ÿäðà ÎÑ. (Win32, Solaris, NetBSD, FreeBSD, DragonFly BSD, Linux). 2. N:1, ïîòîêè â ïðîñòðàíñòâå ïîëüçîâàòåëÿ. Íà íåñêîëüêî ïîòîêîâ ïîëüçîâàòåëÿ îäèí ïîòîê ÿäðà. Íå ìîãóò èñïîëüçîâàòü ìíîãîïðîöåññîðíîñòü, ìîãóò áëîêèðîâàòüñÿ, åñëè íå èñïîëüçîâàòü àñèíõðîííûå îïåðàöèè. (Ïîòîêè â Plan9, GNU Portable threads) 3. M:N, êîìáèíèðîâàííûé ïîäõîä. Ïîëüçîâàòåëüñêèå ïîòîêè ìóëüòèïëåñêèðóþòñÿ íà íåñêîëüêî ïîòîêîâ ÿäðà. Ñëîæíàÿ ðåàëèçàöèÿ, âîçìîæíû ïðîáëåìû ñ ïëàíèðîâàíèåì (èíâåðñèÿ ïðèîðèòåòîâ) (FreeBSD 5.0, NetBSD ñ 2 ïî 4, SunOS 5.2-5.8). 24 / 29 Ðåàëèçàöèè ïîòîêîâ Ðàçëè÷íûå ìîäåëè ïîòîêîâ Àêòèâàöèè ïëàíèðîâùèêà I I I I 1991 ãîä, Àíäðåñîí è äð., èñïîëüçîâàíèå ïðåèìóùåñòâ ïîäõîäîâ N:1 è 1:1. ßäðî îòâå÷àåò çà âûäåëåíèå ïðîöåññîðîâ Ïðèêëàäíàÿ áèáëèîòêà îòâå÷àåò çà ïëàíèðîâàíèå Ïðè èçìåíåíèè êîíôèãóðàöèè (äîáàâëåíèå ïðîöåññîðà, áëîêèðóþùèé âûçîâ îäíîãî èç ïîòîêîâ è ò. ï.) ÿäðî äåëàåò îáðàòíûé âûçîâ (upcall) â ïðèêëàäíóþ áèáëèîòåêó è ïåðåäàåò òóäà íîâóþ àêòèâàöèþ ïëàíèðîâùèêà ñôîðìèðîâàííûé êîíòåêñò, â êîòîðîì ìîæåò áûòü çàïóùåí ïîëüçîâàòåëüñêèé ïîòîê. 25 / 29 Ðåàëèçàöèè ïîòîêîâ Ïðèìåðû ðåàëèçàöèé Ïðèìåð ðåàëèçàöèè: Linux I I I I Äî ÿäðà âåðñèè 2.6 èñïîëüçîâàëàñü LinuxTreads, êîòîðàÿ íå î÷åíü ñîîòâåòñòâîâàëà ñòàíäàðòó POSIX, ïîñëå Native POSIX Thread Library (ntpl). Íåò îòäåëüíîé êîíöåïöèè ¾ëåãêîâåñíûõ ïðîöåññîâ¿ (â Solaris åñòü). Ïðîöåññû è ïîòîêè ñîçäàþòñÿ îäíèì è òåì æå ñèñòåìíûì âûçîâîì clone ñ ðàçíûìè ïàðàìåòðàìè, ÿäðîì óïðàâëÿþòñÿ îäèíàêîâî.  ïàðàìåòðàõ ìîæåò áûòü óêàçàíî, êàêèå ðåñóðñû íóæíî ðàçäåëÿòü. 26 / 29 Ðåàëèçàöèè ïîòîêîâ Ïðèìåðû ðåàëèçàöèé Èíòåðôåéñ pthreads I I I I Íè÷åãî íå ãîâîðèò î òîì, êàê äîëæíû áûòü ðåàëèçîâàíû ïîòîêè (â ÿäðå, â ïðîñòàíñòâå ïîëüçîâàòåëÿ, êîìáèíèðîâàíî) Ýòî õîðîøî: ìîæíî ïèñàòü ïåðåíîñèìûé êîä. È ïëîõî: íåò ãàðàíòèè, ÷òî êîä áóäåò âûïîëíÿòüñÿ îïðåäåëåííûì îáðàçîì, ïðèõîäèòñÿ ðàññ÷èòûâàòü íà õóäøåå. Ïðåäîñòàâëÿåò âûçîâû pthread_create, pthread_join, pthread_exit, à òàêæå ìåõàíèçìû ñèíõðîíèçàöèè ïîòîêîâ. 27 / 29 Çàêëþ÷åíèå Çàêëþ÷åíèå 28 / 29 Çàêëþ÷åíèå Èòîãè ëåêöèè I I I I I I Ñóùåñòâóþò çàäà÷è, ãäå íåîáõîäèìî ìåæïðîöåññíîå âçàèìîäåéñòâèå. Ïðîöåññ ìîæíî ðàçäåëèòü íà àäðåñíîå ïðîñòðàíñòâî è ïîòîêè âûïîëíåíèÿ. Ïîòîêè îáëàäàþò ñîáñòâåííûìè ðåãèñòðàìè è ñòåêîì è ðàçäåëÿþò âñå îñòàëüíîå. Ïåðåêëþ÷åíèå ìîæåò áûòü âûòåñíÿþùèì (ïî òàéìåðó) è íåâûòåñíÿþùèì (yield). Ïîòîêè ìîãóò áûòü ðåàëèçîâàíû â ïðîñòðàíñòâå ÿäðà è â ïðîñòðàíñòâå ïîëüçîâàòåëÿ, îáà ïîäõîäà èìåþò ïðèåìóùåñòâà è íåäîñòàòêè. Ïðè âûòåñíÿþùåì ïëàíèðîâàíèè íåîáõîäèìà ñèíõðîíèçàöèÿ! 29 / 29