Διεργασίες Λειτουργικά Συστήματα
Λειτουργικά Συστήματα/ Slide 2 Η Έννοια της Διεργασίας * Διεργασία (Process) – ο μηχανισμός εκτέλεσης ενός προγράμματος * Η διαδικασία ενεργή οντότητα (περιέχει ένα σύνολο από συσχετισμένους με αυτή πόρους προκειμένου να εκτελεστεί), το πρόγραμμα παθητική * Ένα πρόγραμμα από μόνο του δεν αποτελεί διεργασία * Κάθε διεργασία εκτελεί ένα μοναδικό πρόγραμμα. Το ίδιο πρόγραμμα μπορεί να εκτελείται από πολλές διεργασίες (με διαφορετικές ταχύτητες και ακολουθίες εκτέλεσης των εντολών) * Η εκτέλεση μιας διεργασίας γίνεται σειριακά. Το λειτουργικό μπορεί όμως να εκτελεί πολλές διεργασίες «παράλληλα» μεταξύ τους
Λειτουργικά Συστήματα/ Slide 3 Καταστάσεις Διεργασίας * new: η διεργασία δημιουργείται * running: η διεργασία εκτελείται σε κάποιον επεξεργαστή * waiting: η διεργασία αναμένει (απενεργοποιημένη) κάποιο συμβάν * ready: η διεργασία αναμένει να τις δοθεί (από το ΛΣ) σε κάποιον επεξεργαστή για την συνέχιση της εκτέλεσης της * terminated: η διεργασία έχει ολοκληρώσει την εκτέλεσή της
Λειτουργικά Συστήματα/ Slide 4 Αλλαγές Κατάστασης Διεργασίας * running -> waiting -> ready: Μια διεργασία αλλάζει την κατάσταση της από running σε waiting συνήθως όταν περιμένει να τις δοθεί κάποιος πόρος ή επιθυμεί να χρησιμοποιήσει κάποιον πόρο που δεν είναι διαθέσιμος και πρέπει να ελευθερωθεί. Εν συνεχεία, η διεργασία αλλάζει σε κατάσταση ready όταν τις δοθεί ο πόρος που ζητήθηκε * running -> ready: Μια διεργασία αλλάζει την κατάσταση της από running σε ready συνήθως όταν η εκτέλεση της διακόπτεται από διακοπή υλικού (hardware interrupt) ή κλήση συστήματος (software trap) * ready -> running: Μια διεργασία αλλάζει την κατάσταση της από ready σε running όταν τις δοθεί επεξεργαστής για να συνεχίσει την εκτέλεση της
Λειτουργικά Συστήματα/ Slide 5 Διάγραμμα των καταστάσεων μιας διεργασίας
Λειτουργικά Συστήματα/ Slide 6 Αναπαράσταση Εκτέλεσης Διεργασιών (ΥΣ με μια ΚΜΕ) running P1 ready waiting running P2ready waiting running P3ready waiting
Λειτουργικά Συστήματα/ Slide 7 Λογικά Τμήματα Μνήμης Διεργασιών * Τμήμα κώδικα (code section): περιέχει τις εντολές του προγράμματος που εκτελείται * Τμήμα καθολικών δεδομένων (static / global data section): περιέχει τα μόνιμα δεδομένα του προγράμματος που εκτελείται * Τμήμα δυναμικών δεδομένων (dynamic data section): περιέχει τα δυναμικά δεδομένα της εκτέλεσης * Στοίβα (stack): περιέχει τις προσωρινές τοπικές μεταβλητές της εκτέλεσης που δημιουργούνται λόγω κλήσεων συναρτήσεων
Λειτουργικά Συστήματα/ Slide 8 Αναπαράσταση Τμημάτων Μνήμης Διεργασιών στην Μνήμη του ΥΣ P1 code static data dynamic data stack Μνήμη ΥΣ
Λειτουργικά Συστήματα/ Slide 9 Πίνακας Ελέγχου Διεργασίας – Process Control Block (PCB) Βασικές πληροφορίες που συσχετίζονται με την κάθε διεργασία: * Κατάσταση διεργασίας (process state) * Μετρητής εντολών προγράμματος (program counter) * Καταχωρητές της ΚΜΕ (CPU registers) * Πληροφορίες για το χρονοπρογραμματισμό της ΚΜΕ (CPU scheduling information) * Πληροφορίες διαχείρισης μνήμης (memory- management information) * Συλλογή στοιχείων διαχείρισης (accounting information) * Πληροφορίες κατάστασης εισόδου/εξόδου (Ι/Ο status information)
Λειτουργικά Συστήματα/ Slide 10 Πίνακας Ελέγχου Διεργασίας (συνέχεια)
Λειτουργικά Συστήματα/ Slide 11 Η Λειτουργία της Στοίβας * Η στοίβα χρησιμοποιείται για την προσωρινή αποθήκευση τοπικών μεταβλητών κατά την κλήση υποπρογραμμάτων (συναρτήσεων) καθώς και για την μετάδοση παραμέτρων και αποτελεσμάτων ανάμεσα στα υποπρογράμματα * Κάθε νέα κλήση δεσμεύει χώρο στην στοίβα για την αποθήκευση των αντίστοιχων τοπικών μεταβλητών του υποπρογράμματος. Αυτός ο χώρος αποδεσμεύεται όταν επιστρέψει το υποπρόγραμμα * Αλυσιδωτές κλήσεις υποπρογραμμάτων, η μια μέσα από την άλλη, έχουν σαν αποτέλεσμα την επέκταση της στοίβας * Αν γίνουν πάρα πολλές αλυσιδωτές κλήσεις, η στοίβα μπορεί να γεμίσει (stack overflow) με αποτέλεσμα να τερματιστεί η διεργασία. Κλασικό παράδειγμα είναι η ατέρμονη αναδρομή
Λειτουργικά Συστήματα/ Slide 12 Εναλλαγή Περιβάλλοντος Λειτουργίας * Όταν η ΚΜΕ ανατίθεται σε μια νέα διεργασία για να συνεχίσει την εκτέλεση της, το ΛΣ πρέπει να σώσει την κατάσταση της τρέχουσας διεργασίας (που εκτελείται εκείνη την στιγμή) και να φορτώσει την κατάσταση της νέας διεργασίας προς εκτέλεση * Αυτή η διαδικασία ονομάζεται εναλλαγή περιβάλλοντος λειτουργίας (context switch). O χρόνος που απαιτείται για την εκτέλεση της λειτουργίας αυτής είναι φόρτος (overhead) για το σύστημα (το οποίο όσο ασχολείται με την εναλλαγή δεν κάνει χρήσιμη δουλειά για τις διεργασίες των χρηστών) * Ο χρόνος της εναλλαγής εξαρτάται (α) από την πολυπλοκότητα του ΛΣ και (β) την υποστήριξη από το υλικό του ΥΣ (κυρίως από τον επεξεργαστή και την μονάδα διαχείρισης μνήμης)
Λειτουργικά Συστήματα/ Slide 13 Εναλλαγή Περιβάλλοντος Λειτουργίας (συνέχεια) ανενεργή Διεργασία 0Λειτουργικό ΣύστημαΔιεργασία 1 Αποθήκευση κατάστασης στο PCB0 εκτέλεση Ανάκτηση κατάστασης από PCB1 εκτέλεση Αποθήκευση κατάστασης στο PCB1 Ανάκτηση κατάστασης από PCB εκτέλεση ανενεργ ή Διακοπή ή κλήση συστήματος Χρόνος Εκτέλεσης ΛΣ (context switch)
Λειτουργικά Συστήματα/ Slide 14 Κλασική Υλοποίηση Εναλλαγής Περιβάλλοντος Λειτουργίας * Η εναλλαγή περιβάλλοντος λειτουργίας γίνεται συνήθως μέσω ειδικής κλήσης συστήματος, η οποία μπορεί να ενεργοποιηθεί είτε μέσα από κώδικα χειρισμού διακοπών (interrupt handler) είτε μέσα από άλλες συναρτήσεις βιβλιοθήκης ή κλήσεις συστήματος * Η κλήση εναλλαγής περιβάλλοντος λειτουργίας, σώζει την κατάσταση της τρέχουσας διεργασίας στον πίνακα ελέγχου της και επαναφέρει την κατάσταση της διεργασίας προς εκτέλεσης χρησιμοποιώντας τις τιμές που έχουν αποθηκευτεί στο αντίστοιχο πίνακα ελέγχου * Κατά την διάρκεια της εναλλαγής γίνεται και αλλαγή από την στοίβα συστήματος της τρέχουσας διεργασίας στην στοίβα συστήματος της νέας διεργασίας, με αποτέλεσμα όταν επιστρέφει η κλήση συστήματος να συνεχίσει η εκτέλεση του κώδικα της νέας διεργασίας
Λειτουργικά Συστήματα/ Slide 15 Αναπαράσταση Κλήσης Εναλλαγής Περιβάλλοντος Λειτουργίας foo1 u stack foo 1 foo2 foo3 foo2 foo3 foo1 ctxt P1 running P2 ready P2 running P1 ready u stack foo 2 s stack ctxt u stack foo 1 s stack ctxt u stack foo 2 s stack foo 3 ctxt foo 3
Λειτουργικά Συστήματα/ Slide 16 Επιλογή Διεργασίας προς Εκτέλεση * Το ΛΣ διατηρεί πολλές ουρές αναμονής (π.χ. για κάθε συσκευή και πόρο τους συστήματος) όπου τοποθετούνται οι πίνακες ελέγχου των διεργασιών που αναμένουν την ολοκλήρωση των αιτήσεων τους * Όταν η αίτηση μιας διεργασίας εξυπηρετηθεί, το ΛΣ επαναφέρει την διεργασία σε κατάσταση ready και την τοποθετεί στην ουρά αναμονής (ready queue) των διεργασιών έτοιμων προς εκτέλεση * Ο γρήγορος έλεγχος της ουράς έτοιμων διεργασιών είναι αποφασιστικής σημασίας για την απόδοση του συστήματος * Η διαδικασία επιλογής της επόμενης διεργασίας ονομάζεται χρονοπρογραμματισμός της ΚΜΕ (CPU scheduling)
Λειτουργικά Συστήματα/ Slide 17 Ουρές Αναμονής του ΛΣ
Βασικές Λειτουργίες με Διεργασίες
Λειτουργικά Συστήματα/ Slide 19 Δημιουργία Νέας Διεργασίας * Οι πατρικές διεργασίες (Parent process) δημιουργούν διεργασίες παιδιά (children processes), οι οποίες με τη σειρά τους, δημιουργούν άλλες διεργασίες, δημιουργώντας έτσι ένα δένδρο διεργασιών * Διαμοιρασμός πόρων n Οι «γονείς και τα παιδιά» μοιράζονται όλους τους πόρους n Τα παιδιά παίρνουν υποσύνολο των πόρων * Εκτέλεση n Οι πατρικές και οι θυγατρικές διεργασίες εκτελούνται ταυτόχρονα n Οι πατρικές διεργασίες περιμένουν τον τερματισμό των παιδιών
Λειτουργικά Συστήματα/ Slide 20 Δημιουργία Διεργασίας (συνέχεια) * Χώρος Διευθύνσεων: n Το παιδί αντίγραφο του πατέρα n Το παιδί φορτώνει και εκτελεί κάποιο πρόγραμμα * Παραδείγματα στο UNIX: n Με την κλήση συστήματος fork() δημιουργούνται νέες διεργασίες n Με την κλήση συστήματος exec(), η οποία χρησιμοποιείται μετά την fork() για την αντικατάσταση του χώρου μνήμης της διεργασίας με ένα νέο πρόγραμμα n Με την κλήση συστήματος clone() δημιουργούνται νέα νήματα εκτέλεσης (threads of control)
Λειτουργικά Συστήματα/ Slide 21 Δένδρο Διεργασιών σε ένα Σύστημα Unix
Λειτουργικά Συστήματα/ Slide 22 Τερματισμός Διεργασίας * Η διεργασία εκτελεί την τελευταία εντολή και καλεί το ΛΣ (exit). n Μεταφορά δεδομένων προς τον πατέρα (μέσω wait). n Οι πόροι της διεργασίας επανέρχονται στη διάθεση του ΛΣ * Η πατρική διεργασία μπορεί να διακόψει τη θυγατρική (abort). n Η θυγατρική έχει υπερβεί τους πόρους που της είχαν ανατεθεί n Η εργασία που ανατέθηκε στο παιδί δεν χρειάζεται * Η διεργασία πατέρας τερματίζει την εκτέλεση της n To ΛΣ δεν επιτρέπει στο παιδί να συνεχίσει εφόσον ο πατέρας τερματίσει n Διαδοχικοί Τερματισμοί
Λειτουργικά Συστήματα/ Slide 23 Παράδειγμα 1 #include #include int main() { fork(); printf("\nHello, I am the process with ID = %d\n", getpid()); return 0; }
Λειτουργικά Συστήματα/ Slide 24 Παράδειγμα 2 #include #include int main() { pid_t pid; pid=fork(); printf("\nHello, I am the process with ID = %d\n", getpid()); if (pid==0) execlp(“/bin/ls”, “ls”, NULL); else wait(); return 0; }
Λειτουργικά Συστήματα/ Slide 25 exec execl int execl(const char *path, const char *arg,...) Παίρνει το path για το εκτελέσιμο και μία σειρά από arguments τερματιζόμενη με NULL. execlp int execlp(const char *file, const char *arg,...) Παίρνει το όνομα του εκτελέσιμου και μία σειρά από arguments τερματιζόμενη με NULL. execle int execle(const char *path, const char *arg,..., char *const envp[]) Παίρνει το path για το εκτελέσιμο μία σειρά από arguments τερματιζόμενη με NULL και έναν πίνακα με πληροφορίες περιβάλλοντος.
Λειτουργικά Συστήματα/ Slide 26 exec execv int execv(const char *path, char *const argv[]) Παίρνει το path για το εκτελέσιμο και έναν πίνακα με τα arguments execvp int execvp(const char *file, char *const argv[]) Παίρνει το όνομα του εκτελέσιμου και έναν πίνακα με τα arguments execve int execve(const char *path, char *const argv[], char *const envp[]) Παίρνει το path για το εκτελέσιμο, έναν πίνακα με τα arguments και έναν πίνακα με πληροφορίες περιβάλλοντος
Λειτουργικά Συστήματα/ Slide 27 Παράδειγμα 3 (WIN) #include int main(VOID){ STARTUPINFO si; PROCESS_INFORMATION pi; //allocate memory ZeroMemory(&si, sizeof(si)); si.cb=sizeof(si); ZeroMemory(&pi, sizeof(pi));
Λειτουργικά Συστήματα/ Slide 28 Παράδειγμα 3 (WIN) //create child process if (!CreateProcess(NULL, //use command line "C:\\WINDOWS\\system32\\mspaint.exe", //command line NULL, //don't inherit process handle NULL, //don't inherit thread handle FALSE, //disable handle inheritance 0, //no creation flags NULL, //use parent's environment block NULL, //use parent's existing directory &si, &pi)) { fprintf(stderr, "Create process failed"); return -1; }
Λειτουργικά Συστήματα/ Slide 29 Παράδειγμα 3 (WIN) //parent will wait for the child to complete WaitForSingleObject(pi.hProcess, INFINITE); printf("Child Complete"); //close handles CloseHandle(pi.hProcess); CloseHandle(pi.hThread); }
Λειτουργικά Συστήματα/ Slide 30 Παράδειγμα 4 int main(void) { pid_t pid; int status; command_t *cmd; char *newdir; int chdirresult; while (TRUE) { cmd = (command_t *)malloc(sizeof(command_t)); /* create a new command_t structure */ cmd->argv = (char **)calloc(20, sizeof(char *)); /* allocate the argument array for the new command */ cmd->cmdLine = (char *)calloc(200, sizeof(char)); /* allocate space for the full command line to be loaded */ printPrompt();
Λειτουργικά Συστήματα/ Slide 31 Παράδειγμα 4 gets(cmd->cmdLine); /* get the command line from the user */ parse(cmd->cmdLine, cmd); /* parse the command (store the arguments in the argv array in the cmd struct */ pid = fork(); if (pid == 0) { execvp(cmd->name, cmd->argv); } else { wait(&status); //wait for the successful completion of the newly executed application. } } return 0; }
Λειτουργικά Συστήματα/ Slide 32 Σήματα στο Unix (Unix Signals) * Ένα σήμα αντιπροσωπεύει μια ειδοποίηση προς μια συγκεκριμένη διεργασία για κάποιο γεγονός που συνέβη * Τα σήματα ονομάζονται και software interrupts * Τα σήματα είναι ασύγχρονα (η δημιουργία και αποστολή τους γίνεται χωρίς να υπάρχει προηγούμενη συνεννόηση με την διεργασία για την οποία προορίζονται) * Τα σήματα στέλνονται: n Από μια διεργασία στην άλλη n Από τον πυρήνα στη διεργασία * Stevens, W.R., “Unix Network Programming”, Prentice-Hall
Λειτουργικά Συστήματα/ Slide 33 Δημιουργία Σήματος (Signal Generation) * Από τον χρήστη (μέσω εντολών): n Η εντολή kill του shell χρησιμοποιείται για να στέλνει σήματα n Ειδικοί χαρακτήρες από το πληκτρολόγιο δημιουργούν σήματα (π.χ. Ctrl-C, ή Delete, που δημιουργούν το σήμα SIGINT) * Από διεργασίες/κώδικα: n Κλήση συστήματος kill() n Καταστάσεις του υλικού δημιουργούν σήματα, που στέλνονται από τον πυρήνα στη διεργασία (π.χ. αναφορά σε διεύθυνση εκτός του χώρου διευθύνσεων της διεργασίας δημιουργεί το σήμα SIGSEGV) n Καταστάσεις λογισμικού δημιουργούν σήματα (π.χ. άφιξη δεδομένων εκτός ζώνης (out-of-band data) σε ένα στόμιο)
Λειτουργικά Συστήματα/ Slide 34 Χειρισμός Σημάτων (Signal Handling) * Τι μπορεί να κάνει μια διεργασία με ένα σήμα; n Μπορεί να παρέχει μια συνάρτηση που καλείται οποτεδήποτε στέλνεται ένας συγκεκριμένος τύπος σήματος στην διεργασία n Μπορεί να αγνοήσει το σήμα (κάποιοι τύποι σημάτων «πιάνονται» αυτόματα και σε κάθε περίπτωση από το ΛΣ) n Μπορεί να επιτρέψει να συμβεί η προκαθορισμένη λειτουργία για κάθε σήμα * Στις πρώτες εκδόσεις του Unix τα σήματα μπορούσαν να χαθούν (unreliable), οι νεώτερες εκδόσεις του Unix όμως, υποστηρίζουν αξιόπιστο (reliable) μηχανισμό σημάτων
Λειτουργικά Συστήματα/ Slide 35 Συνεργαζόμενες Διεργασίες * Οι ανεξάρτητες (Independent) διεργασίες δεν επηρεάζουν άλλες διεργασίες ούτε και επηρεάζονται από την εκτέλεση άλλων διεργασιών * Οι συνεργαζόμενες (Cooperating) διεργασίες μπορούν να επηρεάσουν ή να επηρεαστούν από την εκτέλεση άλλων διεργασιών * Κύριοι λόγοι για την δημιουργία συνεργαζόμενων διεργασιών: n Διαχείριση κοινής πληροφορίας n Επιτάχυνση υπολογισμών n Διαχωρισμός κώδικα σε ξεχωριστά τμήματα
Λειτουργικά Συστήματα/ Slide 36 Επικοινωνία μεταξύ Διεργασιών * Οι διεργασίες επικοινωνούν μεταξύ τους για να επιτευχθεί: n ανταλλαγή δεδομένων n συγχρονισμός επεξεργασίας * Υπάρχουν δύο βασικές προσεγγίσεις επικοινωνίας: n χρήση κοινής μνήμης n ανταλλαγή μηνυμάτων * Κοινή μνήμη (shared memory): οι διεργασίες χρησιμοποιούν κοινές μεταβλητές των οποίων τις τιμές αλλάζουν κατάλληλα * Ανταλλαγή μηνυμάτων (message passing): οι διεργασίες επικοινωνούν στέλνοντας και λαμβάνοντας μηνύματα
Λειτουργικά Συστήματα/ Slide 37 Μηνύματα - Κανάλια Επικοινωνίας * Δημιουργείται ένα (λογικό) κανάλι (channel) επικοινωνίας μεταξύ των διεργασιών, μέσω του οποίου ανταλλάσσονται τα μηνύματα * Το ΛΣ παρέχει τις εξής βασικές πράξεις: n open(channel) – δημιουργία/άνοιγμα καναλιού n send(channel, message) – αποστολή μηνύματος n receive(channel, message) – παραλαβή μηνύματος n close(channel) – κλείσιμο καναλιού * Συνήθως κάθε κανάλι έχει ένα άκρο (παραλήπτη) * Ένα κανάλι μπορεί να είναι μονής ή διπλής κατεύθυνσης
Λειτουργικά Συστήματα/ Slide 38 Μηνύματα - Άμεση Επικοινωνία * Ο παραλήπτης και αποστολέας προσδιορίζεται σαφώς κατά την αποστολή/παραλαβή του μηνύματος * Το ΛΣ παρέχει τις εξής βασικές πράξεις: n send (P, message) – στείλε μήνυμα στη διεργασία P n receive(Q, message) – λάβε ένα μήνυμα από τη διεργασία Q * Τα μηνύματα μπορεί (αλλά δεν πρέπει) να παραδίδονται στον παραλήπτη με την σειρά που στέλνονται από τον αποστολέα
Λειτουργικά Συστήματα/ Slide 39 Μηνύματα - Έμμεση Επικοινωνία * Τα μηνύματα στέλνονται σε και παραλαμβάνονται από (γραμματο)θυρίδες (mailboxes ή ports) * Το ΛΣ παρέχει τις εξής βασικές πράξεις: n open(mailbox) – δημιουργία/άνοιγμα θυρίδας n send(mailbox, message) – αποστολή μηνύματος n receive(mailbox, message) – παραλαβή μηνύματος n close(mailbox) – κλείσιμο θυρίδας * Μια θυρίδα μπορεί να είναι προσβάσιμη από πολλές διεργασίες * Συνήθως το μήνυμα που βρίσκεται σε μια θυρίδα το λαμβάνει η διεργασία που «πρώτη» επιχειρεί να παραλάβει ένα μήνυμα. Ουσιαστικά επιτρέπεται στο σύστημα να διαλέξει αυθαίρετα τον παραλήπτη. Ο αποστολέας ειδοποιείται για τον παραλήπτη
Λειτουργικά Συστήματα/ Slide 40 Επικοινωνία μέσω δικτύου * Επικοινωνία ανάμεσα σε διαφορετικούς υπολογιστές γίνεται συνήθως με τα πρωτόκολλα διαδικτύου (Internet protocols, IP) * Κάθε άκρο μιας σύνδεσης προσδιορίζεται μέσω της διεύθυνσης του υπολογιστή (Internet address), και της θύρας (port) που έχει ανοίξει μια διεργασία * Για παράδειγμα το άκρο :1625 αναφέρεται στη θύρα 1625 στον κόμβο με την διεύθυνση * Το πιο διαδεδομένο πρωτόκολλο επικοινωνίας του διαδικτύου, το TCP/IP, υποστηρίζει την δημιουργία συνδέσεων μεταφοράς δεδομένων μεταξύ δύο άκρων
Λειτουργικά Συστήματα/ Slide 41 Επικοινωνία μέσω TCP/IP
Λειτουργικά Συστήματα/ Slide 42 Υλοποίηση Μηχανισμών Επικοινωνίας πάνω από Δίκτυο με TCP/IP * Το TCP/IP είναι η βάση πάνω στην οποία μπορεί να χτιστούν πολλοί διαφορετικοί μηχανισμοί επικοινωνίας διεργασιών * Με βάση το TCP/IP μπορούν να υλοποιηθούν και όλοι οι προηγούμενοι μηχανισμοί ανταλλαγής μηνυμάτων * Οι αντίστοιχες διασυνδέσεις μεταξύ των διεργασιών υλοποιούνται με συνδέσεις TCP/IP αντί να χρησιμοποιείται μνήμη του τοπικού ΛΣ * Η ταχύτητα ανταλλαγής μηνυμάτων μεταξύ των διεργασιών εξαρτάται πλέον από την ταχύτητα μετάδοσης δεδομένων πάνω από το δίκτυο (και την αποδοτικότητα του πρωτοκόλλου TCP/IP) και όχι τόσο από την ταχύτητα αντιγραφής δεδομένων στην μνήμη του ΛΣ
Λειτουργικά Συστήματα/ Slide 43 Τυπικά Ερωτήματα Υλοποίησης * Υπάρχει «μόνιμη» σύνδεση επικοινωνίας μεταξύ αποστολέα και παραλήπτη; * Με ποια λογική δημιουργούνται και καταστρέφονται συνδέσεις επικοινωνίας (σε χαμηλό επίπεδο, όπως π.χ. μέσω μνήμης του συστήματος ή δικτυακών συνδέσεων) μεταξύ διεργασιών που ανταλλάσσουν μηνύματα; * Είναι το μήκος των μηνυμάτων σταθερό και γνωστό εκ των προτέρων, ή μπορεί να είναι μεταβλητό (πως ανακαλύπτεται το μέγεθος μεταβλητών μηνυμάτων την ώρα της εκτέλεσης); * Τί γίνεται με λάθη, όταν δηλαδή μια από τις δύο διεργασίες τερματιστεί; Πως το αντιλαμβάνεται αυτό η άλλη μεριά;
Λειτουργικά Συστήματα/ Slide 44 Συγχρονισμός * Σύγχρονη επικοινωνία: ο αποστολέας περιμένει μέχρι να λάβει το μήνυμα ο παραλήπτης (blocking send), ο παραλήπτης περιμένει μέχρι να υπάρχει διαθέσιμο μήνυμα προς παραλαβή (blocking receive) * Ασύγχρονη επικοινωνία: ο αποστολέας συνεχίζει την εκτέλεση ανεξάρτητα από την παραλαβή του μηνύματος (non-blocking send), ο παραλήπτης δεν περιμένει μέχρι να φτάσει κάποιο μήνυμα (non- blocking receive) * συνδυασμοί σύγχρονης/ασύγχρονης αποστολής/παραλαβής
Λειτουργικά Συστήματα/ Slide 45 Ενδιάμεση Αποθήκευση (buffering) * Πόσα μηνύματα μπορούν να αποθηκευτούν προσωρινά, μέχρι να τα ζητήσει ο παραλήπτης; * Η ουρά των μηνυμάτων μιας σύνδεσης μπορεί να υλοποιηθεί με έναν από τους ακόλουθους τρόπους: n Μηδενική χωρητικότητα – 0 μηνύματα Ο αποστολέας πρέπει να περιμένει τον παραλήπτη (rendezvous) n Περιορισμένη χωρητικότητα – N μηνύματα Ο αποστολέας περιμένει αν ο σύνδεσμος είναι γεμάτος n Απεριόριστη χωρητικότητα – απεριόριστο μήκος Ο αποστολέας δεν περιμένει ποτέ
Λειτουργικά Συστήματα/ Slide 46 Παράδειγμα - Producer/Consumer * Έστω μια διεργασία (παραγωγός) που επιθυμεί να στέλνει «πακέτα εργασίας» σε μια δεύτερη διεργασία (καταναλωτής) * Έστω πως η επικοινωνία των διεργασιών πρέπει να υλοποιηθεί με: n (α) άμεση ανταλλαγή μηνυμάτων n (β) ασύγχρονο send n (γ) σύγχρονο receive
Λειτουργικά Συστήματα/ Slide 47 Παράδειγμα - Υλοποίηση Consumer typedef struct msg {…} msg; void consumerCode() { msg m; while (1) { receive(producerID,&m); processItem(&m); }
Λειτουργικά Συστήματα/ Slide 48 Παράδειγμα - Υλοποίηση Producer typedef struct msg {…} msg; void producerCode() { msg m; while (1) { produceItem(&m); send(consumerID,&m); }
Λειτουργικά Συστήματα/ Slide 49 Παράδειγμα (συνέχεια) * Έστω πως επιθυμούμε να περιορίσουμε τον αριθμό (έστω Ν) των «πακέτων εργασίας» που βρίσκονται σε αναμονή (έχουν σταλεί από τον παραγωγό χωρίς να τα έχει παραλάβει ο καταναλωτής), αλλά δεν μπορούμε να προσδιορίσουμε την χωρητικότητα του καναλιού επικοινωνίας μεταξύ των δύο διεργασιών * Ο συγχρονισμός μπορεί να γίνει βάζοντας τον καταναλωτή να στέλνει αίτηση στον παραγωγό για κάθε «πακέτο εργασίας» που επιτρέπεται να αποθηκευτεί ενδιάμεσα (στο κανάλι επικοινωνίας) * Στην αρχή πρέπει να σταλούν Ν αιτήσεις, ενώ κάθε φορά που ο καταναλωτής λαμβάνει ένα «πακέτο εργασίας» πρέπει να στέλνει και νέα αίτηση
Λειτουργικά Συστήματα/ Slide 50 Παράδειγμα - Υλοποίηση Consumer #define N 100 typedef struct msg {…} msg; typedef int req; void consumerCode() { msg m; req ok; int i; for (i=0; i<N; i++) {send(producerID,&req);} while (1) { receive(producerID,&m); send(producerID,&req); processItem(&m); }
Λειτουργικά Συστήματα/ Slide 51 Παράδειγμα - Υλοποίηση Producer typedef struct msg {…} msg; typedef int req; void producerCode() { msg m; req ok; while (1) { produceItem(&m); receive(consumerID,&req); send(consumerID,&m); }
Λειτουργικά Συστήματα/ Slide 52 Απομακρυσμένη επικοινωνία * Υποδοχές (sockets) * Remote Procedure Call (RPC) * Remote Method Invocation (RMI) για Java
Λειτουργικά Συστήματα/ Slide 53 Υποδοχές (Sockets) * Ένα ζευγάρι διεργασιών που επικοινωνούν πάνω από δίκτυο χρησιμοποιούν ένα ζευγάρι υποδοχών. * Υποδοχή: IP διεύθυνση + αριθμός θύρας (port) * Τα sockets χρησιμοποιούνται κυρίως στο μοντέλο client-server. * O server ακούει ένα port και όταν έρθει αίτηση δέχεται τη σύνδεση από το socket του πελάτη. * Servers συγκεκριμένων υπηρεσιών ακούν σε καθορισμένα ports πχ. http 80, ftp 21, telnet 23 κλπ * Γενικά όλες οι θύρες κάτω από 1024 θεωρούνται ευρέως γνωστές.
Λειτουργικά Συστήματα/ Slide 54 Υποδοχές (Sockets) * Κάθε σύνδεση είναι μοναδική * Όταν ο client εκκινεί μια σύνδεση του ανατίθεται port από το ΛΣ Στη Java υπάρχουν 3 κύριοι τύποι υποδοχών: - Connection oriented (TCP) Socket - Connectionless (UDP) DatagramSocket - Πολλαπλών παραληπτών MulticastSocket (υποκλάση της DatagramSocket)
Λειτουργικά Συστήματα/ Slide 55 Client-Server παράδειγμα import java.net.* import java.io.* public class DateServer { public static void main (String[] args){ try{ ServerSocket sock=new ServerSocket(6013); while(true){ Socket client=sock.accept(); PrintWriter pout=new PrintWriter(client.getOutputStream(), true); pout.println(new java.util.Date().toString()); client.close(); } catch(IOException ioe){ System.err.println(ioe); }
Λειτουργικά Συστήματα/ Slide 56 Client-Server παράδειγμα import java.net.* import java.io.* public class DateClient { public static void main (String[] args){ try{ Socket sock=new Socket(“ ”, 6013); InputStream in=sock.getInputStream(); BufferedReader bin=new BufferedReader(new InputSreamReader(in)); String line; while ((line=bin.readLine())!=null) System.out.println(line); sock.close(); } catch(IOException ioe){ System.err.println(ioe); }
Λειτουργικά Συστήματα/ Slide 57 Sockets-C Δημιουργία int socket (int protocolFamily, int type, int protocol) protocolFamily:AF_INET, AF_UNIX, κλπ. type: SOCK_STREAM, SOCK_DGRAM protocol: IPPROTO_TCP, IPPROTO_UDP Κλείσιμο int close (int socket)
Λειτουργικά Συστήματα/ Slide 58 Sockets-C Διεύθυνση struct sockaddr{ unsigned short sa_family; //Address family, e.g, AF_INET char sa_data[14]; //Family specific address info }; Για TCP-IP struct in_addr{ unsigned long s_addr; //Internet address 32 bits }; struct sockaddr_in { unsigned short sin_family; //Internet protocol e.g., AF_INET or PF_INET unsigned short sin_port; //Address port 16 bits struct in_addr sin_addr; //Internet address 32 bits char sin_zero[8]; //not used };
Λειτουργικά Συστήματα/ Slide 59 Sockets-C Πχ. Finger server struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(79); addr.sin_addr.s_addr = inet_addr(" ");
Λειτουργικά Συστήματα/ Slide 60 TCP Client Βήματα 1. Δημιουργία TCP socket με χρήση της socket() 2. Δημιουργία σύνδεσης με το server με χρήση της connect() 3. Επικοινωνία (send/receive) 4. Κλείσιμο (close)
Λειτουργικά Συστήματα/ Slide 61 TCP Client int connect (int socket, struct sockaddr *foreignAddress, unsigned int addressLength) int send(int socket, const void *msg, unsigned int msgLength, int flags) int recv(int socket, void *rcvBuffer, unsigned int bufferLength, int flags) Blocking send/receive
Λειτουργικά Συστήματα/ Slide 62 Παράδειγμα EchoClient Δες EchoClient.c Σημείωση: - H inet_addr() μετατρέπει τo string της IP διεύθυνσης σε 32 bit - Tο TCP είναι byte stream protocol. Αυτό σημαίνει ότι τα bytes που στέλνει ο server δεν είναι απαραίτητο ότι μπορεί να ληφθούν με ένα μόνο recv. - Δε στέλνουμε το ‘\0’. Γιατί? Παράδειγμα εκτέλεσης % TCPEchoClient "Echo this!" Received Echo this!
Λειτουργικά Συστήματα/ Slide 63 TCP Server Βήματα 1. Δημιουργία TCP socket με χρήση της socket() 2. Ανάθεση port στο socket με χρήση της bind() 3. Αποδοχή συνδέσεων στο port με χρήση της listen() 4. while(1) Δημιουργία νέου socket για κάθε client με τη χρήση της accept() Επικοινωνία με τον client μέσω send/recv Κλείσιμο της σύνδεσης με close()
Λειτουργικά Συστήματα/ Slide 64 TCP Server int bind(int socket, struct sockaddr *localAddress, unsigned int addressLength) int listen(int socket, int queueLimit) int accept(int socket, struct sockaddr *clientAddress, unsigned int addressLength) Σημείωση: To socket που κάνουμε bind δε χρησιμοποιείται για send/recv. Μόνος του ρόλος είναι να δέχεται τις αιτήσεις για connections. Με το που έχουμε accept γίνεται dequeue ένα connection request και δημιουργείται ένα νέο socket με το client address.
Λειτουργικά Συστήματα/ Slide 65 Παράδειγμα EchoServer Δες EchoServer.c Σημείωση: - Χρησιμοποιούμε την INADDR_ANY για να μπορεί ο server μας να τρέξει ανξαρτήτως της IP διεύθυνσης του μηχανήματος - Η inet_ntoa() είναι η αντίστροφη της inet_addr Παράδειγμα εκτέλεσης % TCPEchoServer 5000 Handling client % TCPEchoClient "Echo this!" Received Echo this!
Λειτουργικά Συστήματα/ Slide 66 Sockets-Java IP Διευθύνσεις: κλάση InetAddress Μέθοδοι για εξαγωγή διεύθυνσης και χειρισμό. Δες InetAddressEaxample.java Παράδειγμα εκτέλεσης με παράμετρο localhost: Local Host: luke-PC localhost: localhost :0:0:0:0:0:0:1
Λειτουργικά Συστήματα/ Slide 67 Sockets-Java TCP sockets: Κλάσεις Socket, ServerSocket TCP Client Βήματα: 1) Δημιουργία αντικειμένου Socket. O constructor δημιουργεί μια TCP σύνδεση με τον απομακρυσμένο host. 2) Επικοινωνία μέσω InputStream και OutputStream. Τα streams αυτά περιέχονται στο Socket αντικείμενο και ο χειρισμός τους γίνεται όπως με οποιαδήποτε Java streams. 3) Κλείσιμο με close(). Δες TCPEchoClient.java
Λειτουργικά Συστήματα/ Slide 68 Παράδειγμα EchoClient Δες TCPEchoClient.java Σημειώσεις: - Τα ΤCP sockets στέλνουν και λαμβάνουν bytes. H getBytes() μέθοδος της String μετατρέπει το String σε byte array. - H parseInt() μετατρέπει το string του argument σε ακέραιο. - Πάλι χρησιμοποιούνται πολλαπλά receives
Λειτουργικά Συστήματα/ Slide 69 Sockets-Java TCP Server Βήματα: * Κατασκευή ServerSocket αντικειμένου σε κάποιο port. To αντικείμενο αυτό ακούει το port αυτόματα (δε χρειάζεται listen()) * while(1) Κάλεσε accept() για να αποδεχτείς την επόμενη σύνδεση. Η accept() επιστρέφει Socket αντικείμενο με τη νέα σύνδεση. Επικοινωνία μέσω InputStream/OutputStream κλείσιμο
Λειτουργικά Συστήματα/ Slide 70 Παράδειγμα EchoClient Δες TCPEchoClient.java Σημειώσεις - Οι getInetAddress(), getPort() μέθοδοι στο socket επιστρέφουν διεύθυνση και port του client - H δεύτερη παράμετρος στην write(), είναι ένα offset για το που βρίσκεται το πρώτο byte στον πίνακα που πρόκειται να σταλεί.
Λειτουργικά Συστήματα/ Slide 71 UDP Sockets-Java - Τα UDP sockets δε χρειάζεται να είναι connected πριν χρησιμοποιηθούν - Αναλογία: TCP/τηλέφωνο, UDP/γραμματοκιβώτιο - Τα μηνύματα στο UDP (datagrams) εμπεριέχουν τη διεύθυνση του αποστολέα. - Ένα UDP socket διατηρεί το μέγεθος του μηνύματος. - Μηνύματα μπορεί να χαθούν ή να φτάσουν με λάθος σειρά - Χρήσιμο όταν το πλήθος των μηνυμάτων που ανταλλάσσονται είναι μικρό. - Κλάσεις DatagramSocket, DatagramPacket. Ίδια τόσο για clients όσο και για servers
Λειτουργικά Συστήματα/ Slide 72 Παραδείγματα - Δες UDPEchoClientTimeout.java και τον αντίστοιχο server.