Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

Λειτουργικά Συστήματα

Παρόμοιες παρουσιάσεις


Παρουσίαση με θέμα: "Λειτουργικά Συστήματα"— Μεταγράφημα παρουσίασης:

1 Λειτουργικά Συστήματα
Ντίρλης Νικόλαος- ΕΤΥ 2ο Φροντιστήριο Παρασκευή, 18/10/2013 Β4 Λειτουργικά Συστήματα- Φροντιστήριο 2

2 Διεργασίες και Εργαλεία
Λειτουργικό Σύστημα -> Multitasking Κάθε διεργασία μπορεί να ειδωθεί σαν μία δέσμη στοιχείων που διατηρούνται από τον πυρήνα για να ελέγχει και να διαχειρίζεται όλα αυτά τα tasks Processes: Διαχείριση Επικοινωνία Συγχρονισμός Λειτουργικά Συστήματα- Φροντιστήριο 2

3 Διαχείριση Εργασιών Εργαλεία: fork() :create a child process
exit(): causes normal process termination exec(): replaces the current process image Λειτουργικά Συστήματα- Φροντιστήριο 2

4 Επικοινωνία Διεργασιών
Εργαλεία: signals: asynchronous notification sockets και client/server shared memory Λειτουργικά Συστήματα- Φροντιστήριο 2

5 Συγχρονισμός Διεργασιών
Εργαλεία: Semaphors: control access to a common resource Λειτουργικά Συστήματα- Φροντιστήριο 2

6 Η fork Ο μοναδικός τρόπος να δημιουργηθεί µια νέα διεργασία στο UNIX είναι µε την κλήση του fork Η διεργασία που καλεί την fork ονομάζεται γονέας (parent) Η νέα διεργασία ονοµάζεται παιδί (child) Σύνταξη της κλήσης- συστήµατος fork pid = fork(); Όταν επιστρέψει η κλήση της fork Η δύο διεργασίες έχουν ολόιδια αντίγραφα του χώρου μνήµης (σε επίπεδο χρήστη) Εκτός από την τιµή της µεταβλητής pid Για την διεργασία-γονέας η pid είναι η ταυτότητα (ID) της διεργασίας-παιδί Για την διεργασία-παιδί η pid = 0 Πώς ξεχωρίζουμε στον κώδικα ποια διεργασία είναι παιδί και ποια πατέρας? Λειτουργικά Συστήματα- Φροντιστήριο 2

7 Παράδειγμα #1 #include <string.h> #include <stdio.h>
main() { int pid = 0; printf("hello world\n"); pid = fork(); if (pid == 0) // Child process executes here printf("this is the child\n"); } else // parent process executes here printf("this is the parent\n"); printf("bye\n"); return 0; Λειτουργικά Συστήματα- Φροντιστήριο 2

8 Παράδειγμα #2 #include <string.h> main() { int pid = 0;
printf("hello world\n"); pid = fork(); if (pid == 0) { // Child process executes here printf("this is the child\n"); exit(0); } // only the parent process executes this printf("this is the parent\n"); Λειτουργικά Συστήματα- Φροντιστήριο 2

9 Παράδειγμα #3 #include <string.h> main() { int i = 0;
if (fork() == 0) { // Child process executes here i = 1; } printf("My value:%d\n", i); exit(0); Λειτουργικά Συστήματα- Φροντιστήριο 2

10 Signals Το ΛΣ στέλνει ένα signal στη διεργασία για να την ενημερώσει για κάποιο γεγονός. 1) Εκτέλεση Διεργασίας 2) Γεγονός 3) Signal 4) Διακοπή Εκτέλεσης Διεργασίας 5) Signal Handler 6) Συνέχιση Εκτέλεσης Διεργασίας Λειτουργικά Συστήματα- Φροντιστήριο 2

11 Kill (1/2) Kill –l: list signal names
Tα πιο βασικά signals μπορούμε να τα στείλουμε με το πληκτρολόγιο CTRL-C -> SIGINT =Terminate CTRL-Z -> SIGTSTP = Suspend execution CTRL-\ -> SIGABRT = Abort Επίσης έχουμε: SIGCHLD:  sent to the parent of a child process when it exits, is interrupted, or resumes after being interrupted. By default the signal is simply ignored.  One common usage of the signal is to instruct the operating system to clean up the resources used by a child process after its termination without an explicit call to the wait system call (βλ handler για zombie processes). SIGCONT (πχ με “fg” από το terminal): signal instructs the operating system to continue (restart) a process previously paused by the SIGSTOP or SIGTSTP signal SIGSEGV: sent to a process when it makes an invalid virtual memory reference. Λειτουργικά Συστήματα- Φροντιστήριο 2

12 Kill (2/2) Μπορούμε να στείλουμε όλα τα signals από τη γραμμή εντολών
kill -<signal> PID π.χ. kill -SIGINT 2115 στέλνει ένα SIGINT signal στη διεργαςία με PID 2115 Προγραμματιστικά μπορούμε να στείλουμε signals με την κληση του συστήματος kill(...) pid_t my_pid = getpid(); kill(my_pid, SIGSTOP); Λειτουργικά Συστήματα- Φροντιστήριο 2

13 Signal Handlers Ολα τα signals μπορούµε να τα χειριστούµε, εκτός από τα SIGKILL signal -- Η διεργασία τερµατίζει SIGSTOP signal -- Η διεργασία σταµατάει Προκαθορισμένοι signal handlers Αν δεν ορίσουµε έναν συγκεκριµένο handler για κάποιο τύπου signal το σύστηµα χρησιµοποιεί τους προκαθορισµένους π.χ. όταν έρθει ένα TERM signal -- ο προκαθορισµένος handler κάνει exit(...) Ορίζουµε handlers µε την κλήση του συστήματος signal(...) Πρώτη παράμετρος – ο τύπος του signal ∆εύτερη παράμετρος – η συνάρτηση του handle Λειτουργικά Συστήματα- Φροντιστήριο 2

14 Δημιουργία Signal Handler (1/2)
void catch_int(int sig_num) { printf("Don’t do that\n"); } ... signal(SIGINT, catch_int); Οταν ο χρήστης πατήσει CTRL-C ϑα κληθεί η catch_int() και ϑα τυπώσει "Don’t do that" Προσοχη: – Αµέσως µετά, το σύστηµα ϑα αφαιρέσει την catch_int() από το signal SIGINT Αν ϑέλουµε η catch_int() να χειρίζεται όλα τα signals τύπου SIGINT πρέπει να το ϑέσουµε ξεκάθαρα Μέσα στην catch_int() ϑα πρέπει να καλέσουµε ξανά την signal(SIGINT, catch_int); Λειτουργικά Συστήματα- Φροντιστήριο 2

15 Δημιουργία Signal Handler (2/2)
Αν ϑέλουµε η catch_int() να χειρίζεται όλα τα signals τύπου SIGINT πρέπει να το θέσουµε ξεκάθαρα: void catch_int(int sig_num) { signal(SIGINT, catch_int); printf("Don’t do that\n"); } Δηλαδή, κάθε φορά που καλείται η συνάρτηση του handler ορίζει ότι την επόμενη φορά θα καλείται ο ίδιος ο handler. Το σύστηµα προσφέρει 2 έτοιµους signal handlers SIG_IGN - Αγνοεί το signal -δηλ. ο handler δεν κάνει τίποτα signal(SIGINT, SIG_IGN); SIG_DFL -- Επαναφέρει τον προκαθορισμένο handler signal(SIGTSTP, SIG_DFL); Λειτουργικά Συστήματα- Φροντιστήριο 2

16 Άλλο ένα παράδειγμα #include <stdio.h> #include <unistd.h> #include <signal.h> void sigint_handler (int signum) { printf("got SIGINT\n"); signal(SIGINT, sigint_handler); //make sure that next time SIGINT will be handled by this handler. } int main(void) signal(SIGINT, sigint_handler); printf("pid is %d\n", getpid()); while (1) sleep(1); } Έστω signal.c το παραπάνω στο getit. Κάντε gcc -Wall -o signal signal.c και μετά ./signal. Τι εμφανίζει; Μετά πατήστε ctrl-c και μετά ctrl-z. Τώρα; Μετά, ανοίξτε ένα άλλο terminal window και πληκτρολογήστε kill -SIGINT <PID> και έπειτα στο άλλο τερματικό fg. Τι συμβαίνει; Τέλος πληκτρολογούμε ctrl-\. Μπορείτε να κατανοήσετε ποια signals «έπαιξαν» στην παραπάνω περίπτωση; Λειτουργικά Συστήματα- Φροντιστήριο 2

17 Αποφυγή Zombie Processes
Υλοποιούµε έναν signal handler Θέτουµε signal( SIGCHLD, sig_chld ); /* Avoid "zombie" child-proccesses */ void sig_chld(int signo){ signal( SIGCHLD, sig_chld ); pid_t pid; int stat; while( (pid=waitpid(-1,&stat,WNOHANG)) > 0){ printf( "Child %d terminated.\n", pid ); } Αυτός ο handler μπορεί να χρησιμοποιηθεί σαν “black box” (κυκλοφορεί στην βιβλιογραφία) Μας κάνει να είμαστε σίγουροι πως ο γονιός δεν θα πεθάνει νωρίτερα από τα παιδιά του έτσι ώστε να τα αφήσει στο σύστημά μας σαν zombies. Λειτουργικά Συστήματα- Φροντιστήριο 2


Κατέβασμα ppt "Λειτουργικά Συστήματα"

Παρόμοιες παρουσιάσεις


Διαφημίσεις Google