Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
personal Operating Systems project/exercises
C Shell

This branch is 38 commits ahead, 1 commit behind papagryllos-produnctions:master

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
.gitignore
Changelog
Makefile
README.md
client.c
pizza.h
pizza_server.c
run_tests.sh

README.md

Λειτουργικά Συστήματα Ι - 2012
Άσκηση 2

Παρασκευή 04/01/2013


Γεώργιος Παπανικολάου - Α.Μ.: 5044
Προκόπης Γρύλλος - Α.Μ.: 4975


Build for GNU/Linux (x86_64-pc-linux-gnu) with:
* gcc 4.7.2
* GNU make 3.82
* GNU bash 4.2.39
* git 1.8.0
* vim 7.3.754 (patched for Arch Linux)

Project hosted on http://github.com/Nacho-Libre/projectOS/tree/threads
(threads branch) There is ABSOLUTELY NO WARRANTY


Project files
* pizza_server.c
* client.c
* pizza.h (Header file)
* Makefile
* run_tests.sh (Bash script)


Στην παρούσα άσκηση καλούμαστε να υλοποιήσουμε ένα απλό σύστημα εξυπηρέτησης παραγγελειών με τη δημιουργία και την διαχείρηση νημάτων.

Για τη δημιουργία και τον τερματισμο των νημάτων (threads) χρησιμοποίουμε τις συναρτήσεις προτύπου POSIX pthread_create() και pthread_exit() αντίστοιχα κάθως και τις συναρτήσεις pthread_join() και pthread_detach() για την συνένωση και αποκόλληση τους. Στην υλοποίηση αυτή δεν κρίναμε απαραίτητη την χρησή σημάτων (signals) για την επικοινωνία των νημάτων δεδομένου ότι έχουμε thread-based υλοποίηση και μπορούμε να εκμεταλλευτούμε το γεγονός οτί ολα τα thread μίας διεργασίας βλέπουν". Αυτό από την άλλη δημιουργεί το κλασσικό πρόβλημα συγχρονισμού των διαφόρων νημάτων που έχουν πρόσβαση και προσπαθούν να ελέγξουν ή να τροποποιήσουν κοίνες μεταβλητές, το πρόβλημα αυτό αντιμετωπίστηκε με την χρήση σημαφόρων (mutexes). Η επικοινωνία μεταξύ client και server γίνεται με τη χρηση UNIX sockets (/tmp/file) . Χρησιμοποιήσαμε ακόμα condition variables για να διασφαλίσουμε το γεγονός οτί δεν θα χρησιμοποιούνται ποτέ πάνω απο 10 ψήστες ταυτόχρονα.

Στο αρχείο pizza_server.c περιέχεται όλος ο κώδικας για την υλοποίηση του server. Με την εκκίνηση του server γίνονται όλες οι απαραίτητες αρχικοποιήσεις και δημιουργείται μια διεργασία η οποία τρέχει στο παρασκήνιο (deamon mode) και είναι υπεύθυνη για την διαχείρηση των εισερχόμενων παραγγελειών. Kάθε φορά που λαμβάνεται αίτηση για καινούρια παραγγελεία δημιουγείται ενα καινούριο νήμα το οποίο εκτελεί την συνάρτηση order_handling() και ειναι υπεύθυνο για την διεκπαιρέωση της. Mέσα στο σώμα της συνάρτησης order_hadling() και ανάλογα με τον αριθμό των πιτσών στη παραγελεία, η οποία περνιέται ολόκληρη σαν όρισμα, δημιουργείται ένα καινούριο νήμα για κάθε μία το οποίο εκτελεί τη συνάρτηση cook(), αφού πρώτα ελεγχθεί αν υπάρχει διαθέσιμος ψήστης. Στην περίπτωση που δεν υπάρχει, η διαχείρηση της παραγγελείας μπλοκάρεται με την συνάρτηση pthread_cond_wait() μέχρις ώτου καποία συνάρτηση cook() να τελειώσει και αν ελευθερώσει ενα ψήστη, τότε με την συνάρτηση pthread_cond_signal διαλέγεται και αφυπνίζεται κάποιο από τα μπλοκαρισμένα νήματα. Όταν τα νήματα για το ψήσιμο των πιτσών τερματίστουν εννώνονται με το κυρίως νήμα διαχείρησης της παραγγελείας το οποίο περιμένει για την επιστροφή τους με την συνάρτηση pthread_join() και στη συνέχεια άρχιζει η διαδικασία παράδοσης της πίτσας. Και σε αυτή τη περίπτωση χρησιμοποιούμε condition variables για να διασφαλίσουμε οτί παραδιδόνται το πολυ μέχρι 10 παραγγελείες ταυτόχρονα. Με το τερματισμό της παραγγελείας το νήμα διαχείρισης τερματίζει και όλα τα δεδομένα του χάνονται.

Το client.c περιέχει τον κώδικα για την υλοποίηση του πελάτη του συστήματος. Χρημιμοποιει ιδιες δομές με τον server και sockets για να στελνει την παραγγελία. Χωρις ορισματα μπαίνει σε interactive mode για είσοδο παραγγελίας απο το χρηστη, με όρισμα rand παράγει μια τυχαία παραγγελία. (Χρηση του run_tests.sh για περισσότερες)

Στο pizza.h δηλώνονται οι σταθερες, bool type με enumeration, και το struct της παραγγελιας που περιεχει αριθμο των διαφορετικων ειδών πίτσας της παραγγελιας, μεταβλητες χρόνου, και μία βοηθητικη μεταβλητη exists για την εύκολη διαγραφή. Έδω υπάρχει η δυνατότητα αλλαγης των default μεγεθών της άσκησης. (π.χ.: το χρόνο ψησίματος της μαργαρίτας)

Θέμα mutexes: Τα mutexes που χρησιμοποιούμε ανήκουν στη δομή pthread_mutex_t και χρησιμοποίουμε ένα για τη μεταβλητή των ψηστών, ένα για των διανομέων και ένα για τη λίστα των παραγγελείων ώστε να διασφαλίσουμε ότι δεν θα προσπαθήσουν δυο διαφορετικά νήματα να τροποποιήσουν ταυτόχρονα την ίδια θέση μνήμης

Θέμα condition variables: Xρησιμοποιήσαμε condition variables της δομής pthread_cond_t. Tα χρησιμοποιούμε σε συνδιασμό με τον έλεγχο των τιμών των μεταβλητών που κρατάνε τον αριθμό των διαθέσιμων ψηστών και διανομέων αντίστοιχα ( οι οποίες αρχικοποιούνται στο 10 ) ώστε να διασφαλίζεται η ορθή χρήση των διαθέσιμων "πόρων" (στην προκειμένη περίπτωση 10 ψήστες και 10 διανομείς )

Θέμα Coca-coles: Με την εκκίνηση του server ένα παραπάνω νήμα δημιουργείται για τον εντοπίσμο καθυστερημένων παραγγελειών και την προσθήκη coca-colas σε αυτές. To νήμα αυτό κάθε T_VERYLONG (βλ. pizza.h για τιμές ) ελέγχει τη λίστα των παραγγελειών και συγκρίνοντας την χρονική στιγμή εκκίνησης της κάθε παραγγελείας με την τρέχουσα χρονική στιγμή υπολογίζει αν η παραγγελεία βρίσκεται εντός η εκτός χρονικών ορίων και αν εντοπίσει καθυστέρηση ενημερώνει (εικονικά) γράφωντας σε ένα αρχείο (coke).

Θέμα sockets: Τα sockets τα κλείνουμε κατευθείαν μόλις έρθει η παραγγελία για ευκολία και ενημερώνουμε τον client (συμβολικά) στο logfile, στο οποίο εκτυπώνονται πολλων ειδων μηνυματα απο τον server. Η αναγνώριση της παραγγελίας γίνεται με το αντίστοιχο pid του process.

Το script run_tests.sh χρησιμοποιείται για την εκίνηση πολλών client μαζί. Χωρις ορίσματα στέλνει 100 clients, εναν καθε 0.01 (για να αλλαζουν τα νούμετα της γεννήτριας ψευδοτυχαίων αριθμών). Δυο πιθανά ορίσματα: Πρωτο ο αριθμός των πόσων clients να στέιλει και δέυτερο πιθανο άλλο όνομα του εκτελέσιμου.


Κάποια πράγματα δεν είναι απαραίτητα για τη σωστή λειτουργεία του προγραμματος αλλα ειτε απαιτούνταν στην εκφωνηση ειτε βοηθούσαν στο debugging, οπότε παρέμειναν. (π.χ.: τα statuses των παραγγελιών και οι μεταβλητες χρόνου στις παραγγελιές)


Γνωστά Προβλήματα:

*Mερικές φορές είναι πιθανή η ανικανότητα του προγράμματος για δημιουργία περισσότερων threads (λόγο του λειτουργικού συστήματος ή του υπολογιστή), σε αυτη τη περίπτωση ο server τερματίζει τη λειτουργία του και μαζί του κλείνουν όλα τα ανοιχτά απο αυτόν threads

*Προτιμήθηκε η χρήση της συνάρτησης sleep() αντι της pthread_timedwait(), μπορείτε να βρείτε την υλοποιήση μας με χρήση της timedwait εδω


Something went wrong with that request. Please try again.