Następna Poprzednia Spis

2. Kolejka procesów gotowych

2.1 Opis

W systemie jest jedna kolejka procesów gotowych (ang. runqueue), grupująca procesy, które do tego, by móc się wykonywać, potrzebują co najwyżej procesora.

Wszystkie procesy w runqueue powinny mieć status TASK_RUNNING (co oznacza, że są właśnie działające lub gotowe - oczywiście w systemie jednoprocesorowym może być tylko jeden proces działający). Może się co prawda zdarzyć, że w tej kolejce znajdzie się proces o statusie TASK_INTERRUPTIBLE, ale tylko jeśli jest to proces właśnie działający, który zgłasza chęć oczekiwania na przerwanie. Sytuacja taka będzie trwała bardzo krótko - do czasu zakończenia przeszeregowania procesów. Wtedy proces ten zostanie usunięty z kolejki. Jedynym dla niej uzasadnieniem jest oszczędność operacji - być może proces zostanie obudzony przerwaniem nim zdążymy go usunąć z kolejki.

Ilość procesów w kolejce procesów gotowych przechowywana na zmiennej nr_running.

2.2 Struktura

Struktura kolejki runqueue jest tworzona poprzez pole run_list znajdujące się w strukturze task_struct. Jest ono typu list_head, a więc tyczą się jej te same przepisy, które zostały omówione w rozdziale o kolejkach Linuksowych (list.h).

Początek kolejki procesów gotowych jest przechowywany na zmiennej runqueue_head. Nie jest on związany z żadnym procesem, ani nie jest elementem żadnej struktury. Jest to możliwe dzięki nowej strukturze kolejki (list.h). Porównajmy, ze starą strukturą:

2.3 Operacje na kolejce procesów gotowych

Do operowania na kolejce runqueue służą następujące procedury:

Wszystkie powyższe operacje korzystają z funkcji zdefiniowanych w list.h a także odpowiednio zmieniają wartość nr_running. Żadne (oprócz funkcji usuwającej) nie korzystają bezpośrednio ze wskaźników na element następny ani poprzedni.

2.4 Uwagi

Pomimo że procesy gotowe są podzielone na wiele logicznych kolejek w zależności od sposobu szeregowania (inny np. dla zwykłych procesów i procesów czasu rzeczywistego) i od priorytetu (dla procesów czasu rzeczywistego), to fizycznie są one umieszczone na jednej liście, a rozpoznanie jak należy postąpić przy kolejnym przeszeregowaniu jest dokonywane przez funkcję schedule().

Podczas żadnej z tych operacji nie jest sprawdzana logiczna poprawność działań: operacje są niezależne od statusu procesu i w żaden sposób nie jest chroniona ich niepodzielność. O te sprawy należy zadbać pisząc kod funkcji je wykorzystującej.

Kolejka runqueue jest obsługiwana zarówno przez funkcje jądra jak i przez przerwania, więc operacje na niej muszą być wykonywane z wyłączonymi przerwaniami. Do zapewnienia niepodzielności kolejki runqueue służy runqueue_lock. Z zasady jest on używany do ochrony pojedynczej operacji, a nie ciągu operacji.


Następna Poprzednia Spis