2011-06-29 11 views
7

czytam ten Wikipedia text kawałek:Jak działa wielozadaniowość kooperacyjna?

Ponieważ wspólnie multitasked system opiera się na każdym procesie regularnie rezygnując czas do innych procesów w systemie, jeden źle zaprojektowany program może zużywać cały czas procesora dla siebie lub spowodować zawieszenie całego systemu.

Z ciekawości, jak zrezygnować z tego czasu? Czy to jest jakieś wywołanie systemu operacyjnego? Pomyślmy o przypadkach nieprzyjmujących, takich jak włókna lub zdarzenia IO, które prowadzą do wielozadaniowości kooperacyjnej. Jak oni rezygnują z tego czasu?

Take this NodeJS przykład:

var fs = require('fs'); 
fs.readFile('/path/to/file', function(err, data) {}); 

Jest dla mnie oczywiste, że proces ten nie robi nic, podczas gdy jest to oczekiwanie na dane, ale jak V8 w tym przypadku zrezygnować czas dla innych procesów?

Załóżmy, że Linux/Windows jest naszym systemem operacyjnym.

Edytuj: Dowiedziałem się, jak Google robi to z V8.

Na Windows oni spać w zasadzie zerowy czas:

void Thread::YieldCPU() { 
    Sleep(0); 
} 

I na Linux one wykonanie połączenia OS:

void Thread::YieldCPU() { 
    sched_yield(); 
} 

z sched.h.

+0

Czy jądro nie decyduje, który proces powinien "poświęcić czas"? – Hannesh

+2

@Hannesh: To wielozadaniowość zapobiegawcza. – sharptooth

Odpowiedz

4

Tak, każdy program bierze udział w decyzjach dotyczących planowania systemu operacyjnego, więc musisz wywołać konkretną syscall, która mówi jądru, aby się z powrotem zabrał. Często było to nazywane wydajnością (). Jeśli sobie wyobrazisz, jak trudno jest zagwarantować, że linia kodu jest wywoływana w regularnych, krótkich odstępach czasu lub nawet w ogóle, masz pojęcie, dlaczego wielozadaniowość kooperatywna jest rozwiązaniem nieoptymalnym.

W tym przykładzie silnik javascript jest przerywany przez program planujący systemu operacyjnego, jeśli jest to system operacyjny. Jeśli jest kooperatywny, to nie, silnik nie wykonuje żadnej pracy, ani nie wykonuje żadnego innego procesu. W rezultacie takie systemy zwykle nie są odpowiednie do obciążeń w czasie rzeczywistym (lub nawet poważnych).

+0

+1, można spojrzeć na funkcję "Śpij()" - Win32, podczas gdy Win32 używa wielozadaniowości zapobiegawczej 'Śpij()' robi dokładnie to. – sharptooth

0

Zgodnie z ogólną zasadą, wielozadaniowość kooperacyjna obejmuje funkcje sygnalizujące, że obecnie czekają, zamiast wchodzić w pętle spinowe (gdzie przetwarzają podczas oczekiwania), które same się zawieszają.

W takim przypadku przetwarzanie za plikiem ReadFile będzie obsługiwać oczekiwanie na dane i odpowiednią sygnalizację, że można je zawiesić. W ramach własnego kodu, niezależnie od tego, co jest napisane, należy zawiesić przetwarzanie, jeśli czekasz na długotrwały proces, a nie wirowanie. Jednak w wielu przypadkach procesy zawieszenia są automatycznie obsługiwane, ponieważ zawieszenie jest wbudowane. Niebezpieczeństwo jest w tym przypadku, jeśli celowo wymuszasz długoterminowe obroty, wtedy zawiesisz system.

Alternatywą (z tej wiki) jest zapobiegawcze wielozadaniowość, w której proces zostaje wymuszony po określonym czasie, niezależnie od tego, co robi. Oznacza to, że cokolwiek robisz, nie może działać wiecznie, ponieważ proces systemowy wymusi to.Może być jednak mniej efektywny, ponieważ punkty przerwania nie są zdefiniowane.

2

Przykładem takiego systemu operacyjnego jest NetWare. W tym systemie konieczne było wywołanie określonej funkcji (myślę, że nazywa się to ThreadSwitch lub może ThreadSwitchWithDelay). I zawsze było odgadnięcie, jak często było to potrzebne. W każdej pętli wymagającej dużego obciążenia procesora w produkcie konieczne było okresowe wywoływanie jednej z tych funkcji.

Ale w tym systemie inne połączenia spowodowałyby uruchomienie innych wątków. W szczególności (i istotne dla pytania) jest to, że wywołania we/wy spowodowały umożliwienie OS uruchomienia innych wątków. Zasadniczo każde wywołanie systemowe, które dało kontrolę systemowi operacyjnemu, było wystarczające, aby umożliwić uruchamianie innych wątków (ważne są wywołania mutex/semafor).