1 / 17

ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ Ι

ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ Ι. Ντίρλης Νίκος- ΕΤΥ 4 ο ΦΡΟΝΤΙΣΤΗΡΙΟ Παρασκευή 4-11- 2013 Β4. Κοινή Μνήμη και Συγχρονισμός. Κοινή Μνήμ η μεταξύ διεργασιών -> Γρηγορότερη μορφή IPC Τα δεδομένα δεν αντιγράφονται πάνω από μία φορά

nike
Download Presentation

ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ Ι

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ Ι Ντίρλης Νίκος- ΕΤΥ 4ο ΦΡΟΝΤΙΣΤΗΡΙΟ Παρασκευή 4-11-2013 Β4

  2. Κοινή Μνήμη και Συγχρονισμός Κοινή Μνήμη μεταξύ διεργασιών -> Γρηγορότερη μορφή IPC Τα δεδομένα δεν αντιγράφονται πάνω από μία φορά Server/Client model. Όταν ο Server γράφει, ο client πρέπει να διαβάσει όταν ο server έχει τελειώσει. Χρειάζεται συγχρονισμός Χρήση semaphors

  3. Δημιουργία και χρήση κοινής μνήμης System V IPC Shared Memory • Δημιουργία κοινής μνήμης από διεργασία • shmget() • Προσκόλληση διεργασίας στης κοινή μνήμη • shmat() • Αποκόλληση διεργασία; από κοινή μνήμη • shmdt() • Έλεγχος κοινής μνήμης (περιλαμβάνει διαγραφή) • shmctl() • man (shmget) man(shmat) man(shmdt) man(shmctl)

  4. shmget() Με την shmget() παίρνουμε ένα shared memory identifier #include<sys/types.h> #include<sys/ipc.h> #include<sys/shm.h> intshmget(key_t key, int size, int flag); Η shmget() επιστρέφει ένα shared memory ID if OK και-1 αν error Το «key» είναι συνήθως η σταθερά “IPC_PRIVATE”, που ζητά από τονkernel έναν non-negative integer identifier που η τιμή του αυξάνει μέχρι μια μέγιστη τιμή πριν μηδενιστεί. Το «size» είναι το μέγεθοςτων shared memory segment σε bytes Το «flag» μπορεί να είναι “SHM_R”, “SHM_W” ή“SHM_R | SHM_W”

  5. shmat() Όταν ένα shared memory segment έχει δημιουργηθεί, το process το κάνει attach στο address space του καλώντας τηνshmat(): void *shmat(intshmid, void* addr, int flag); Η shmat() επιστρέφει ένανpointer σε έναshared memory segment αν OK και-1 αν error Η συνήθης προτεινόμενη προγραμματιστική τεχνική είναι να θέτονται το addrκαιflag στο μηδέν, πχ: char* buf = (char*)shmat(shmid,0,0); ΣτοUNIX οι εντολές “ipcs” και“ipcrm” χρησιμοποιούνται για να κάνουν list και removeshared memory segments στο current machine. Τοdefault action για ένα shared memory segment είναι να παραμένει στο σύστημα ακόμα και μετά το θάνατο μιας διεργασίας. Αν θέλουμε να το αποφύγουμε αυτό (και συνήθως το θέλουμε!) χρησιμοποιούμε την shmctl().

  6. shmctl() Η shmctl() κάνει αρκετά πραγματάκια: intshmctl (intshmid, intcmd, structshmid_ds *buf); Το «cmd»μπορεί να είναι ένα από τα IPC_STAT, IPC_SET, ή IPC_RMID. Μπορούμε εύκολα να δούμε τι κάνει το καθένα από αυτά. Με ένα googlάρισμα βρίσκουμε: – IPC_STAT fills the buf data structure – IPC_SET can change the uid, gid, and mode of the shmid – IPC_RMID sets up the shared memory segment to be removedfrom the system once the last process using the segmentterminates or detaches from it – a process detaches from ashared memory segment using shmdt(void* addr), which issimilar to free() Η shmctl() επιστρέφει 0 αν OK και-1 ανerror

  7. Παραδείγματα shm_id = shmget(SHM_KEY, SHM_SIZE, 0600); if (shm_id < 0) { printf("Could not create shared memory!\n"); exit(1); } data = shmat(shm_id, NULL, 0); //δείκτης προς την αρχή της sm if (data == (char *)-1) { printf(“Could not attach to shared memory!\n”); exit(1); }

  8. και άλλο ένα… char* ShareMalloc(int size) { intshmId; char* returnPtr; if ((shmId=shmget(IPC_PRIVATE, size, (SHM_R | SHM_W)) < 0) Abort(“Failure on shmget\n”); if (returnPtr=(char*)shmat(shmId,0,0)) == (void*) -1) Abort(“Failure on shmat\n”); shmctl(shmId, IPC_RMID, (structshmid_ds *) NULL); return (returnPtr); }

  9. Race Conditions (1/2 ) Τι θα συμβεί αν τρέξουμε το παρακάτω κομμάτι κώδικα; intmain(void) { pid_tpid; if ((pid = fork()) < 0) Abort(“Fork Error”); else if (pid == 0) charatatime(“output from child\n”); else charatatime(“output from parent\n”); exit(0); } Έχουμε το φαινόμενο του «compile timenon-determinism»! Διαδοχικά run του παραπάνω κώδικα δίνουν και διαφορετικά αποτελέσματα!

  10. Race Conditions(2/2 ) Αν θέλουμε να επέμβουμε στη σειρά εκτέλεσης (γιατί για παράδειγμα η διεργασία-γονιός χρειάζεται κάποια δεδομένα από τη διεργασία παιδί) μπορούμε να κάνουμε wait. Σε αυτή την περίπτωση χρησιμοποιούμε signals. Διαφορετικά κάνουμε busy waiting κοιτώντας ένα flag, κάτι όμως που φυσικά θέλουμε να το αποφεύγουμε! Όμως για θυμηθείτε το παράδειγμα των Φιλοσόφων! Χρειαζόμαστε και έναν «διαιτητή» (ή έναν «σερβιτόρο» στην περίπτωση των φιλοσόφων). Αυτός είναι ο ρόλος του semaphor

  11. Τhe «Critical Section Problem» Code that modifies shared data usuallyhas the following parts: – Entry section: The code that requestspermission to modify the shared data. – Critical Section: The code that modifies theshared variable. – Exit Section: The code that releases access tothe shared data. – Remainder: The remaining code The critical section problem refers to the problem of executingcritical sections in a fair, symmetric manner. Solutions to the criticalsection problem must satisfy each of the following: – Mutual Exclusion: At most one process is in its critical section atany time – Progress: If no process is executing its critical section, a processthat wishes to enter can get in – Bounded Waiting: No process is postponed indefinitely An atomic operation is an operation that, once started, completes ina logical indivisible (=αδιαίρετος) way. Most solutions to the critical sectionproblem rely on the existence of certain atomic operations

  12. Semaphors (1/2) Ένας semaphore είναι μια ακέραια μεταβλητή με δύο atomic operations: wait and signal. Άλλες ονομασίες που θα βρείτε για αυτές είναι down, P και lock για το wait και up, V, unlock και post για το signal. Μία process που κάνει wait σε έναν semaphoreS δεν μπορεί να συνεχίσει μέχρι η τιμή του S είναι θετική. Μετά μειώνει κατά ένα την τιμή του isS. Όταν γίνει «signal» η τιμή του S μεγαλώνει κατά ένα. Τι δεν θέλουμε να κάνει ένας semaphor; void wait(int *s) { while (*s <= 0); /* END WHILE*/ (*s)--; } void signal(int *s) { (*s)++; }

  13. Semaphors (1/2) Το πρόβλημα με τον κώδικα αυτό είναι αρχικά το busy waiting και επίσης το γεγονός ότι οι πράξεις «- -» και «+ +» δεν είναι atomic! Αυτό που θέλουμε να κάνουμε είναι το ακόλουθο: wait(&s); /* critical section */ signal(&s); /* remainder section */ και αυτό γίνεται με τη χρήση των system callssemget() και semop()

  14. Semaphors (2/2) • Δημιουργία - Άνοιγμα σημαφόρου • sem_open() • Κλείδωμα σημαφόρου • sem_wait() • Απελευθέρωση σημαφόρου • sem_post() • Κλείσιμο σημαφόρου • sem_close() • Διαγραφή σημαφόρου • sem_unlink()

  15. semget() #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> intsemget(key_t key, intnsems, intsemflg); Δημιουργεί έναν semaphore και αρχικοποιεί κάθε στοιχείο του στο μηδέν. int semID = semget(IPC_PRIVATE, 1, S_IRUSR |S_IWUSR); Όπως στο shared memory, έτσι και εδώ το ipcsκαιipcrmμπορούν να κάνουν list και remove semaphores

  16. semop() intsemop(intsemid, structsembuf *sops, unsigned nsops); Increment, decrement, or test semaphore elements for a zero value Από το <sys/sem.h>: sops->sem_num, sops->sem_op, sops->sem_flg Αν το sem_opείναι θετικόή semop() προσθέτει ένα στην τιμή και ξυπάνει τη διαδικασία που περιμένει. Αν το sem_opείναι αρνητικό , η semop() προσθέτει ένα στην τιμή και αν <0 ή semop() sets to 0 and blocks until it increases Αν το sem_opείναι μηδέν και το semaphore element value όχι μηδέν, η semop() blocks the calling process until the value becomes zero Αν η semop() is interrupted by a signal, it returns –1 with errno = EINTR

  17. Παράδειγμα structsembufsemWait[1] = {0,-1,0}; semSignal[1] = {0,1,0}; intsemID; semop(semID,semSignal,1); /* init to 1 */ while((semop(semID,semWait,1) == -1) && (errno == EINTR)); { /* Critical Section */ } while((semop(semID,semSignal,1) == -1) && (errno == EINTR));

More Related