linachris / time-scheduling-simulator

A priority based time scheduling simulator using the Priority Inversion protocol & a simulation of Semaphores, written in C

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Priority Based Time Scheduling Simulator

Σταυρούλα Χριστοπούλου

Εντολή μεταγλώττισης: make

(Έχει υλοποιηθεί αρχείο Makefile)

Εντολή εκτέλεσης: ./simulator lambda_arrival lambda_lifetime lambda_cs_time total_processes k S

όπου:

Παράμετροι:

  • lambda_arrival: Η παράμετρος λάμδα(της εκθετικής κατανομής) του μέσου χρόνου μεταξύ διαδοχικών αφίξεων διεργασιών
  • lambda_lifetime: Η παράμετρος λάμδα(της εκθετικής κατανομής) της μέσης διάρκειας ζωής διεργασίας
  • lambda_cs_time: Η παράμετρος λάμδα(της εκθετικής κατανομής) της μέσης διάρκειας εκτέλεσης κρίσιμης περιοχής
  • k: Πιθανότητα εισόδου στην κρίσιμη περιοχή
  • S: Αριθμός σημαφόρων συστήματος
  • total_processes: Αριθμός δοσοληψιών παιδιών

Δομή project και Διαχωρισμός αρχείων:

Για λόγους απλούστευσης του κώδικα, έχει υλοποιηθεί ένα interface, με τα παρακάτω directories και αρχεία:

  • src:

    • ADTPriorityQueue.c: Υλοποιήση συναρτήσεων ουράς προτεραιότητας με την χρήση min heap για την ταξινόμηση της ουράς σύμφωνα με την μικρότερη προτεραιότητα σε αριθμό(μεγαλύτερη για την υλοποίηση μας), την εύρεση και την διαγραφή της μεγαλύτερης σε προτεραιότητα διεργασίας.
    • ADTVector.c: Υλοποίηση συναρτήσεων min heap για την ουρά προτεραιότητας.
    • semaphore.c: Υλοποίηση δομής σημαφόρων συστήματος, για την δημιουργία τους, την δέσμευση και την αποδέσμευση των πόρων του συστήματος κατά τις εισόδους στην κρίσιμη περιοχή, και την καταστροφή τους.
    • simulator.c: Υλοποίηση προσωμοιωτή συστήματος χρονοδρομολόγησης βάσει προτεραιοτήτων, καθώς και υλοποίηση δομής των διεργασιών του συστήματος, για την δημιουργία τους, την επεξεργασία τους, και την καταστροφή τους.
  • include: header files για τα παραπάνω αρχεία των σημαφόρων, της ουράς προτεραιότητας, του vector, αλλά και το common_types για ορισμένα κοινά στοιχεία μεταξύ τους.

  • Αρχείο Makefile: Για την μεταγλώττιση και τη σύνδεση όλων των αρχείων.

simulator.c:

Κατά την μεταγλώττιση, από το αρχείο αυτό παράγεται και το εκτελέσιμο. Έχει σχεδιαστεί κατάλληλα ένας προσομοιωτής συστήματος χρονοδρομολόγησης βάσει προτεραιοτήτων με εξαρτήσεις μεταξύ των διεργασιών, όπου σύμφωνα με τις αφίξεις και τις προτεραιότητες των διεργασιών, και πριν τελειώσει η διάρκεια ζωής τους, εκτελούνται ανά χρονοθυρίδες, μέσα στις οποίες επιχειρούν με μία πιθανότητα την ακολουθία down()/up() σε σημαφόρους.

Η λειτουργία του:

  1. Λαμβάνονται από τον χρήστη μέσω του command line οι παράμετροι της προσομοίωσης που αναφέρονται και παραπάνω.
  2. Αρχικοποιούνται οι πίνακες με τα running, blocked, waiting, cs_time χρονοθυρίδες ανά προτεραιότητα καθώς και το αρχείο που θα περιέχει το running state ανά χρονοθυρίδα.
  3. Αρχικοποιούνται οι σημαφόροι, που θα χρησιμοποιηθούν, σε έναν πίνακα sem_set. Παράγονται όλες οι διεργασίες που θα υπάρξουν κατά την εκτέλεση με τυχαίες αφίξεις, διάρκεια ζωής, και προτεραιότητες και εισάγονται σε μία ουρά προτεραιότητας ταξινομημένη ανά χρόνο άφιξης. Αρχικοποιούνται και 2 ουρές προτεραιότητας, αρχικά κενές, από τις; οποίες η μία κατά την διάρκεια της εκτέλεσης θα περιέχει τις διεργασίες που έχουν ήδη φτάσει, και η άλλη αυτές που έχουν ήδη τελειώσει.
  4. Αρχίζει η εκτέλεση ανά χρονοθυρίδα διακριτού χρόνου, η οποία θεωρούμε πως είναι το while loop που ελέγχει αν έχει γεμίσει η finished_pq, και είναι 1sec το οποίο προσμετράται με την μεταβλήτη curr_time.
  5. Ανά χρονοθυρίδα, με ένα while loop, ελέγχοντας το pqueue_max στοιχείο κάθε φορά, της ουράς που υπάρχουν όλες οι διεργασίες(process_pool), αν έχει ήδη φτάσει το αφαιρούμε από την αρχική ουρά και το προσθέτουμε στην ουρά των "έτοιμων" διεργασιών προς εκτέλεση(ready_pqueue).
  6. Ελέγχουμε την διεργασία που τρέχει τώρα, καθώς δεν είναι μέσα στο ready_pqueue, μήπως δεν είναι alive, δηλαδή έχει περάσει ο χρόνος ζωής της, και αν έχει περάσει την προσθέτουμε στο finished_pqueue.
  7. Ύστερα, ελέγχουμε όλο το ready_pqueue, για άλλες τυχόν διεργασίες που δεν είναι alive, και αν υπάρχουν τις αφαιρούμε από εκεί και τις προσθέτουμε στο finished_pqueue.
  8. Τώρα, που όλες οι διεργασίες που είναι στο ready_pqueue, είναι alive, άρα πρέπει να αποφασιστεί το ποιά διεργασία θα εκτελεστεί.

Πως αποφασίζεται ποια διεργασία θα εκτελεστεί;

Σημαντική παραδοχή: Αν δεν υπάρχει κάποια διεργασία που τρέχει αυτή τη στιγμή, το curr_proc_running = NULL, και αν υπάρχει διεργασία που τρέχει αυτή την στιγμή, η τιμή της γίνεται stored as curr_proc_running, και δεν θα βρίσκεται σε κάποιο PQ όσο τρέχει.

  1. Αν η ready_pqueue δεν είναι άδεια και δεν τρέχει κάποια διεργασία αυτή την στιγμή, το curr_proc_running θα είναι το μέγιστο στοιχείο της ready_pqueue.
  2. Αν η ready_pqueue δεν είναι άδεια και τρέχει κάποια διεργασία αυτή την στιγμή,
    • Aν η διεργασία αυτή είναι στην κρίσιμη περιοχή της, τότε η μεγαλύτερη σε προτεραιότητα διεργασία από την ready_pqueue μπλοκάρεται.
    • Αν η διεργασία αυτή είναι στην κρίσιμη περιοχή της, τότε βρίσκουμε την διεργασία με την μεγαλύτερη προτεραιότητα μεταξύ τους, την θέτουμε σαν την curr_proc_running, και η άλλη μπλοκάρεται.
  3. Αν η ready_pqueue και η process_pool είναι άδειες και το curr_proc_running != NULL, έχουμε την τελευταία διεργασία να τρέχει.
  4. Εφόσον έχουμε βρεί την μεγαλύτερη σε προτεραιότητα διεργασία που μπορεί να τρέξει, συνεχίζουμε σε έλεγχο του αν έχει εκτελεστεί όλο το CS της.
  5. Αυξάνουμε τα attributes της για το running και το cs_time_executed, και αυξάνουμε το waiting time των διεργασιών που περιμένουν, αλλά παραμένουν ενεργές στο ready_pqueue.
  6. Πηγαίνουμε στην επόμενη χρονοθυρίδα(στο επόμενο βήμα του while loop) με curr_time++. Η προσομοίωση τελειώνει, όταν έχει περάσει το lifetime όλων των διεργασιών που παράχτηκαν στην αρχή, είναι δηλαδή όλες στο finished priority queue, και αποδεσμεύεται η μνήμη μέσω της free_resources.

Σημειώσεις/Παραδοχές

  • Θεωρούμε ότι κάθε χρονοθυρίδα(time_slot) διακριτού χρόνου, είναι το while loop που ελέγχει αν έχει γεμίσει η finished_pq, και είναι 1sec το οποίο μετριέται με την μεταβλήτη curr_time. Μετά το πέρας μίας χρονοθυρίδας ελέγχουμε για άλλες διεργασίες.
  • Όλες οι διεργασίες της προσομοίωσης παράγονται στην αρχή της εκτέλεσης σύμφωνα με τις παραμέτρους του χρήστη, αλλά επειδή έχουν arrival τυχαίες χρονικές στιγμές, φτάνουν πιο μετά κατά την εκτέλεση, και όχι όλες μαζί.
  • Finished είναι οι διεργασίες που πέρασε το lifetime τους, το οποίο και μετράει από την στιγμή που φτάνει η διεργασία(έχει προστεθεί δηλαδή από την αρχή στην τιμή του lifetime το arrival_time)
  • Αν δύο διεργασίες έχουν την ίδια προτεραιότητα, θα εκτελεστεί εκείνη η οποία τρέχει ήδη
  • Αν μία διεργασία προσπαθήσει να μπει στο CS και μπλοκαριστεί, δεν θεωρούμε ότι τρέχει, αλλά ο χρόνος μετράει σαν waiting_time και blocked_time.
  • Στο simulator.c υπάρχουν αρκετές βοηθητικές συναρτήσεις για τις διαδικασίες της main()
    • compare_functions(): Ανάλογα με την ουρά προτεραιότητας επιλέγεται και διαφορετική.
    • processes_generator(): Παράγει όλες τις διεργασίες της προσομοίωσης.
    • incr_proc_waiting_time(): Αυξάνεται ο χρόνος αναμονής των διεργασιών στο ready_pqueue
    • checkIfAnyProcessPassedItsLifetime(): Ελέγχει αν έχει παρέλθει το lifetime για τις διεργασίες της ready_pqueue
    • rand_exponential(): Εκθετική κατανομή
    • rand_uniform(): Ομοιόμορφη κατανομή

About

A priority based time scheduling simulator using the Priority Inversion protocol & a simulation of Semaphores, written in C


Languages

Language:C 98.4%Language:Makefile 1.6%