2012-02-04 7 views
16

Zostałem za zadanie w klasie, aby utworzyć bibliotekę wątków na poziomie użytkownika w C. Zastanawiałem się, czy ktoś mógłby dać mi listę rzeczy do przeczytania, aby to osiągnąć. Mam dobry pomysł, od czego zacząć, ale wszelkie zasoby na temat wątków na poziomie użytkownika i niektóre stosowne aspekty języka C, które mogłyby pomóc, byłyby niezwykle cenne.Wdrażanie pakietu wątków na poziomie użytkownika

Jestem bardzo niejasna, w jaki sposób mogę wdrożyć harmonogram dla takich. Załóżmy, że dobrze rozumiem język C i niektóre z jego bardziej przydatnych funkcji bibliotecznych.

+4

Przypisanie jest nieco trudne do spełnienia, ponieważ nie można tego zrobić "w C". Potrzebujesz co najmniej minimalnej ilości zespołów lub odpowiedników rozszerzeń kompilatora, aby ułatwić tworzenie nowych kontekstów wykonania i przełączać się między nimi. Albo możesz napisać własną wirtualną maszynę i implementację C, aby uruchomić na maszynie wirtualnej, ale nie sądzę, że to jest to, co twój instruktor miał na myśli ... –

+1

Dla wielozadaniowości współpracy/wątkowania możesz znaleźć getcontext/makecontext/przydatne funkcje setcontext. – MetallicPriest

+0

Nie widzę, jak można to zrobić bez asemblera do implementacji zapisywania/przywracania kontekstu rejestru i wskaźnika stosu. To bez nawet rozważania I/O i jak na to czekać. –

Odpowiedz

8

Zrobiłem to dla zadania domowego bez pisania jakiegokolwiek asemblera. Mechanizm przełączania wątków był setjmp/longjmp. Wiązało się to z przydzieleniem pamięci dla każdego stosu wątku, a następnie bardzo ostrożnym masowaniem wartości w jmp_buff, więc wykonanie przechodzi do stosu następnego wątku.

Zobacz także całkiem niezauważalny Russ Cox libtask.

Edytuj w odpowiedzi na komentarz PO: Przy podejmowaniu decyzji o zmianie wątków istnieją dwa główne kierunki: prewencyjny & spółdzielczy. W modelu wyprzedzającym, będziesz miał coś w rodzaju sygnału timera, który powoduje, że przepływ wykonania przeskoczy do głównego wątku programu rozsyłającego, który wybiera następny wątek do uruchomienia. W modelu współpracy wątki "ustępują" sobie nawzajem, albo jawnie (, np., przez wywołanie funkcji yield(), którą podasz) lub niejawnie (, np., żądając blokady utrzymywanej przez inny wątek).

Zobacz przykładowe API libtask na przykładzie modelu kooperacyjnego, w szczególności opis funkcji taskyield(). To wyraźny plon, o którym wspomniałem. Istnieją również nieblokujące funkcje wejścia/wyjścia, które zawierają ukrytą wydajność - bieżące "zadanie" zostaje wstrzymane do czasu zakończenia operacji wejścia/wyjścia, ale pozostałe zadania mają szansę na uruchomienie.

+0

Tak wyobrażałem sobie, że będę przełączać wątki. Przypuszczam, że moim największym brakiem wiedzy jest ustalenie, kiedy wątek powinien zrezygnować z kontroli, aby inny mógł działać. tj. w jaki sposób wątki decydują o tym, że mają wystarczająco dużo czasu. – SirensOfTitan

+0

@SirensOfTitan, zaktualizowałem swoją odpowiedź, aby uwzględnić to, o co prosiłeś. –

4

Prosty spółdzielnia scheduler można zrobić w C z użyciem swapcontext, spojrzeć na przykład na stronie swapcontext człowieka here, to jego produkcja:

$ ./a.out 
main: swapcontext(&uctx_main, &uctx_func2) 
func2: started 
func2: swapcontext(&uctx_func2, &uctx_func1) 
func1: started 
func1: swapcontext(&uctx_func1, &uctx_func2) 
func2: returning 
func1: returning 
main: exiting 

Więc jak widać jest to całkiem wykonalne.

Uwaga: jeśli zamienisz kontekst wewnątrz programu obsługi sygnałów czasomierza, otrzymasz plan działania zapobiegawczego, ale nie jestem pewien, czy jest to bezpieczne, czy możliwe.

Edit: Znalazłem to w stronę man sigaction co sugeruje, że jest to możliwe, aby przełączyć kontekst wewnątrz obsługi sygnału:

Jeśli SA_SIGINFO jest określona w sa_flags, następnie sa_sigaction (zamiast sa_handler) określa funkcję obsługi sygnału dla signum. Ta funkcja odbiera numer sygnału jako pierwszy argument, wskaźnik do siginfo_t jako drugi argument , a wskaźnik do ucontext_t (rzutowany na void *) jako trzeci argument.

+1

Biorąc pod uwagę, że jest to problem z pracą domową (i tak go retagowałem), PO powinien sprawdzić, czy byłoby to do przyjęcia. Bardziej prawdopodobne jest, że instruktor szuka raczej implementacji funkcji 'swapcontext()' niż po prostu go używa. –

1

Możesz zajrzeć do implementacji open source firmy Apple. Zauważ, że największa część kodu jest w rzeczywistości zbiorem, ponieważ wymaga pewnych specjalistycznych rzeczy, których nie możesz wykonać w C, takich jak pobieranie adresu powrotu ramki stosu lub przeskakiwanie do dowolnego adresu.

Wątki użytkownika (zwane również powszechnie "włóknami") zazwyczaj wykorzystują model kooperatywny; to znaczy wątki są wykonywane, dopóki nie zdecydują, że mają wystarczająco dużo czasu, a następnie poddają się innemu wątkowi. Za pomocą kolejki priorytetowej można zaimplementować program planujący, który wykonuje zadanie, które zostało uruchomione przez najkrótszy czas. (Program planujący śledzi bieżące zadania, a uruchomione zadanie zwraca się, gdy uzna, że ​​jest wystarczająco dużo, a program planujący aktualizuje czas wykonania zadania, a następnie generuje czas, który miał najmniejszy czas wykonania).

Powiązane problemy