Потоки

advertisement
Ïîòîêè
Îïåðàöèîííûå ñèñòåìû 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
Download