Moduł p-linux - przykładowa implementacja

Każdy moduł Linuksa musi zawierać funkcje inicjującą i usuwającą moduł:

int init_module( void ) {
   if ( ts_installed ) // jakiś moduł już jest zainstalowany
      return -1;       // sygnalizowany jest błąd
   ts_installed = 1;
   ts_select = linux_select;
   ts_wakeup = linux_wakeup;
   return 0;
}

void cleanup_module(void) {
   ts_select = NULL;
   ts_wakeup = NULL;
   ts_on = 0; // Moduł nie implementuje funkcji ts_sched_off,
              // więc wystarczy wyzerować flagę.
   ts_installed = 0;
}
Zaimplementowana musi być funkcja dla zdarzenia SELECT:
Process linux_select(Process current, int cpu) {
      // Numer procesora (cpu) nie jest wykorzystywany,
      // gdyż SMP nie jest obsługiwane.
   int pri, best_pri = -1000;
   Process p, found = NULL;

   for_each_ready_process(p) {
      pri = p->counter;
      if (p==current && pri>0)
           pri = pri + 1;
      if (pri>best_pri)
         best_pri = pri, found = p;
   }
   
   if (best_pri==0) {     // Postarzanie
      for_each_process(p) {
         p->counter = (p->counter / 2) + p->priority;         
   }
   return next;
}
Proces budzony może wywłaszczyć proces bieżący, zatem potrzebna jest funkcja obsługujące zdarzenie WAKEUP:
int linux_wakeup(Process task) {
   if (task->counter > current->counter+3)
      need_resched = 1;		
   return 0;
}

Jak widać treść modułu to kilkadziesiąt wierszy, z czego właściwy algorytm zajmuje około 30, a funkcje administracyjne są niewielkie. Algorytm wygląda praktycznie identycznie z pseudokodem opisanym w punkcie 2.2. Różnica dotyczy nazwy pola priorytetu statycznego upri (w Linuksie -- priority) oraz sposobu odwołania się do elementów struktur (-> w miejsce .).

Zaletą zaproponowanego tu rozwiązania jest jego elastyczność, nakład pracy proporcjonalny do stopnia skomplikowania algorytmu planisty oraz osadzenie w jednym pliku funkcji realizujących jeden algorytm (modularyzacja).

Pełną treść modułu można obejrzeć w pliku ts_linux.c.



Tomek Blaszczyk
1999-05-21