2016-11-29 3 views
2

Je suis très nouveau en langage C et Linux et l'anglais n'est pas ma langue maternelle. Désolé pour ceux d'avance.Implémentation du planificateur de threads round robin et thread cancel

Je travaille sur un projet d'école qui consiste à implémenter un planificateur round robin sur linux et j'ai quelques problèmes sur l'implémentation de scheduler et thread_self.

Le programmateur vérifie si la file d'attente prête est vide en premier, si oui, définissez la tranche de temps et l'alarme (timeslice). Sinon, recherchez un nouveau thread à partir de la liste ready, répartissez TCB du nouveau thread, définissez le timeslice, basculez vers un nouveau thread et définissez l'alarme (timeslice). Mais je continue à avoir des erreurs à un moment donné et je ne pouvais pas trouver où réparer.

Une autre chose à propos de thread_cancel. La fonction int thread_cancel (thread_t tid) supprime la cible tcb et je dois trouver la tcb en utilisant tid. J'ai essayé comme

Thread* temp = getpid(); 
kill(pid, SIGKILL); 

mais je ne pouvais pas comprendre comment retirer tcb de la file d'attente. S'il vous plaît donnez-moi une meilleure idée!

Thread.h

typedef struct _Thread{ 
    ThreadStatus status; 
    pid_t pid; 
    Thread* pPrev; 
    Thread* pNext; 
}Thread; 
Thread* ReadyQHead; 
Thread* ReadyQTail; 

-Queue

typedef struct _queue{ 
    Thread* head; 
    Thread* tail; 
    unsigned int num; 
} queue; 

queue* runList; 
queue* readyList; 
queue* waitList; 

-Queue.c

void enqueue(queue * q, Thread* tcb) 
{ 
    if(q->num == 0) { 
     q->head = tcb; 
     q->tail = tcb; 
    } else { 
     q->tail->pNext = tcb; 
     q->tail = tcb; 
    } 
    q->num ++; 
} 

Thread * dequeue(queue * q) 
{ 
    Thread * tmp; 
    if(q->num == 0) return NULL; 
    else if(q->num == 1) { 
     tmp = q->head; 
     q->head = NULL; 
     q->tail = NULL; 
    } else { 
     tmp = q->head; 
     q->head = q->head->pNext; 
    } 
    q->num --; 
    return tmp; 
} 

-scheduler

void alarmHandler(int signal) 
{ 
    printf("Scheduler awake!!"); 
    /*Do schedule*/ 
} 

int RunScheduler(void) 
{ 
    //check if ready queue is empty 
    if(is_empty(readyList) != 0) 
    { 
     printf("this is weird"); 
     signal(SIGALRM, alarmHandler); 
    } 
    else { 
     /*Look up a new thread from ready list*/ 
     Thread* tmp = ReadyQHead; 

     /*send sigcont*/ 
     kill(tmp->pid, SIGCONT); 

     //dispatch TCB of new thread 
     if(is_empty(runList) != 0 && runList->head->status == 0) 
      enqueue(readyList, tmp); 

     //pick thread at head of ready list as first thread to dispatch 
     tmp->status = 0; // tmp == runningTcb 
     printf("alive tcb : %d\n", tmp->pid); 

     ReadyQHead = dequeue(readyList); 
     //set timeslice 
     signal(SIGALRM, alarmHandler); 
     //context switch to new thread 
     _ContextSwitch(tmp->pid, ReadyQHead->pid); 

    } 

    while(1){ 
     alarm(TIMESLICE); 
    } 

    return 0; 
} 


void _ContextSwitch(int curpid, int tpid) 
{ 
    kill(curpid, SIGSTOP); 
    kill(tpid, SIGCONT); 
} 
+0

Pouvez-vous poster un programme complet, parce que j'ai besoin de vérifier la définition de enqueue et dequeue. –

+0

@SumitGemini J'ai édité! – user19283043

+0

Veuillez noter que l'appel 'printf' dans un gestionnaire de signal est maléfique car' printf' n'est pas sûr pour le signal asynchrone. – MirkoBanchi

Répondre

0

ici est un exemple simple de round robin

while(1) 
{ 
    process1(); 
    process2(); 
    process3(); 
    process4(); 
    .... 
    processN(); 
} 

quelque chose de plus complexe, comme le changement de contexte alors qu'un processus est « sommeil » ou le changement de contexte en attendant d'E/S ou le changement de contexte, car un processus doit être exécuté sur une base temporisée ou due à un événement d'interruption ajoute une complexité énorme.

Alors, quel est exactement votre but/objectif?