Εικονική Μνήμη (Virtual Memory) Προγραμματισμός II 1 lalis@inf.uth.gr
Μνήμη και επικοινωνία διεργασιών Κάθε διεργασία έχει δική της ιδιωτική μνήμη Μια διεργασία δεν μπορεί να γράψει/διαβάσει από/σε θέσεις μνήμης άλλων διεργασιών Η επικοινωνία / μεταφορά δεδομένων μεταξύ των διεργασιών γίνεται μέσα από συγκεκριμένους μηχανισμούς επικοινωνίας Μέσω του λειτουργικού (κλήσεις συστήματος) Προγραμματισμός II 2 lalis@inf.uth.gr
process process user code user code πόροι/μηχανισμοί συστήματος system Προγραμματισμός II 3 lalis@inf.uth.gr
Εικονική μνήμη Οι διευθύνσεις μνήμης που χρησιμοποιεί ο κώδικας που εκτελούν οι διεργασίες είναι εικονικές! Κάθε διεργασία έχει την ψευδαίσθηση ότι έχει στην διάθεση της ολόκληρη την μνήμη του Η/Υ ή ακόμα παραπάνω Το λειτουργικό πραγματοποιεί την αντιστοίχιση μεταξύ εικονικών και πραγματικών διευθύνσεων, εξασφαλίζοντας ξεχωριστή μνήμη για κάθε διεργασία Αυτό γίνεται με διαφανή τρόπο, χωρίς να εμπλέκεται ο προγραμματιστής ούτε ο μεταγλωττιστής Προγραμματισμός II 4 lalis@inf.uth.gr
P1 P2 0Κ-4Κ 4Κ-8Κ 8Κ-12Κ πίνακας αντιστοίχισης 0Κ-4Κ 4Κ-8Κ 8Κ-12Κ πραγματική μνήμη 0Κ-4Κ 4Κ-8Κ 8Κ-12Κ 12Κ-16Κ 16Κ-20Κ 20Κ-24Κ 48Κ-52Κ 52Κ-56Κ 56Κ-60Κ 60Κ-64Κ Προγραμματισμός II 5 lalis@inf.uth.gr
Δημιουργία κοινόχρηστης μνήμης Ρύθμιση της εικονικής μνήμης έτσι ώστε κάποιες εικονικές διευθύνσεις διαφορετικών διεργασιών να αντιστοιχηθούν στις ίδιες φυσικές διευθύνσεις Προκύπτουν «κοινόχρηστα» τμήματα μνήμης Σε αυτή την περίπτωση, οι διεργασίες μπορεί να επικοινωνούν μεταξύ τους γράφοντας/διαβάζοντας απ ευθείας σε/από αυτές τις κοινές θέσεις μνήμης Χωρίς να πραγματοποιούν κλήσεις συστήματος Προγραμματισμός II 6 lalis@inf.uth.gr
P1 P2 0Κ-4Κ 4Κ-8Κ 8Κ-12Κ πίνακας αντιστοίχισης 0Κ-4Κ 4Κ-8Κ 8Κ-12Κ πραγματική μνήμη 0Κ-4Κ 4Κ-8Κ 8Κ-12Κ 12Κ-16Κ 16Κ-20Κ 20Κ-24Κ 48Κ-52Κ 52Κ-56Κ 56Κ-60Κ 60Κ-64Κ Προγραμματισμός II 7 lalis@inf.uth.gr
ιδιωτική μνήμη κοινή μνήμη ιδιωτική μνήμη P1 P2 Λειτουργικό Σύστημα Προγραμματισμός ΙΙ 8 lalis@inf.uth.gr
Κοινόχρηστη Μνήμη (Shared Memory) System V API Προγραμματισμός II 9 lalis@inf.uth.gr
Διαδιεργασιακή επικοινωνία System V 3 είδη «αντικειμένων» (μηχανισμών) επικοινωνίας κοινόχρηστες περιοχές μνήμης (shared memory): shm σηματοφόροι (semaphores): sem ουρές μηνυμάτων (message queues): msg Διατηρούνται στην μνήμη του λειτουργικού χάνονται σε κλείσιμο/επανεκκίνηση του Η/Υ Δεν προσπελάζονται μέσω περιγραφέων αρχείου δεν υποστηρίζουν τις open, read, write, close Υπάρχουν ξεχωριστές εντολές για την εμφάνιση και διαγραφή των αντικειμένων επικοινωνίας ipcs (στο πνεύμα της ls), ipcrm (στο πνεύμα της rm) Προγραμματισμός II 10 lalis@inf.uth.gr
Παραγωγή (μοναδικών) κλειδιών key_t ftok(const char *path, int id); Παράγει και επιστρέφει ένα (μοναδικό) κλειδί Το όνομα path αντιστοιχεί σε ένα ισχύον μονοπάτι στον χώρο ονομάτων του συστήματος αρχείων Το πρόγραμμα πρέπει να έχει πρόσβαση στο αντίστοιχο αρχείο/κατάλογο Χρησιμοποιείται μόνο το least significant byte του id Η μοναδικότητα ενός κλειδιού προκύπτει από τον συνδυασμό ονόματος/μονοπατιού και αριθμού Προγραμματισμός II 11 lalis@inf.uth.gr
Λήψη τμήματος κοινόχρηστης μνήμης int shmget(key_t key, size_t size, int flags); Δεσμεύει/βρίσκει το τμήμα κοινόχρηστης μνήμης με κλειδί key, και επιστρέφει το αναγνωριστικό της Η παράμετρος size λαμβάνεται υπόψη μόνο σε περίπτωση δέσμευσης ενός νέου τμήματος μνήμης Επιλογές flags IPC_CREAT: δημιουργεί/δεσμεύει ένα νέο τμήμα μνήμης IPC_EXCL: αποτυχία αν το τμήμα μνήμης υπάρχει άδειες χρήστης/πρόσβασης, όπως στην open Αν το key είναι IPC_PRIVATE, δημιουργείται ένα ανώνυμο/ιδιωτικό τμήμα κοινόχρηστης μνήμης δεν μπορεί να βρεθεί μέσω shmget Προγραμματισμός II 12 lalis@inf.uth.gr
Έλεγχος τμήματος κοινόχρηστης μνήμης int shmctl(int shmid, int cmd, struct shmid_ds *data); H cmd προσδιορίζει την ζητούμενη λειτουργία IPC_RMID: αποδέσμευση του τμήματος μνήμης IPC_STAT: ανάκτηση πληροφοριών για το τμήμα μνήμης IPC_SET: καθορισμός ιδιοτήτων του τμήματος μνήμης Η αποθήκευση των πληροφοριών και ο καθορισμός των επιθυμητών ιδιοτήτων της κοινής μνήμης γίνεται μέσω της δομής struct shmid_ds για περισσότερες λεπτομέρειες, βλέπε manual H αποδέσμευση γίνεται (πιθανώς ασύγχρονα) αν/όταν δεν υφίσταται (πλέον) κάποια διεργασία που να χρησιμοποιεί τη συγκεκριμένη μνήμη Προγραμματισμός II 13 lalis@inf.uth.gr
Σύνδεση τμήματος κοινόχρηστης μνήμης void *shmat(int shmid, const void *addr, int flags); Συνδέει/προσαρτά το τμήμα κοινόχρηστης μνήμης στην (εικονική) μνήμη της διεργασίας Αν addr είναι NULL, η διεύθυνση προσάρτησης επιλέγεται αυτόματα από το λειτουργικό Διαφορετικά το addr πρέπει να είναι πολλαπλάσιο του PAGE_SIZE ή στα flags να προστεθεί το SHM_RND (για αυτόματη στρογγυλοποίηση) η επιλογή του addr δεν είναι προφανής ούτε portable Επιστρέφεται η διεύθυνση στην οποία τελικά προσαρτήθηκε το τμήμα κοινόχρηστης μνήμης σε περίπτωση αποτυχίας επιστρέφεται -1 (όχι NULL) Προγραμματισμός II 14 lalis@inf.uth.gr
Αποσύνδεση τμήματος κοινόχρηστης μνήμης int shmdt(const void *addr); Αποσυνδέει το τμήμα κοινόχρηστης μνήμης που έχει αντιστοιχηθεί στην (εικονική) διεύθυνση addr της διεργασίας Γίνεται αυτόματα όταν τερματίζεται η διεργασία Προγραμματισμός II 15 lalis@inf.uth.gr
p[0] p[1] p[n+1] p[n+2] p p+1 p+n+1 p+n+2 args flag arg[0] arg[n-1] res flag res Server: Client: 1. clear args flag 2. wait for args flag to be set 3. read args 4. write res 5. set res flag 1. wait for args flag to clear 2. write args 3. clear res flag & set args flag 4. wait for res flag to be set 5. read res Προγραμματισμός ΙΙ 16 lalis@inf.uth.gr
int main (int argc, char * argv []) { int shmid,i,key,*p,*argsflag,*args,*resflag,*res; server key = ftok(".",'a'); shmid=shmget(key,(n+3)*sizeof(int),ipc_creat IPC_EXCL S_IRWXU); p = (int *)shmat(shmid,null,0); argsflag = p; args = p+1; resflag = p+n+1; res = p+n+2; } do { *argsflag = 0; // clear args flag while (*argsflag == 0) {} // wait for args flag to be set *res = 0; for (i=0; i<n; i++) { *res = *res + args[i]; } *resflag = 1; // set res flag } while (*res!= 0); shmdt(p); shmctl(shmid,ipc_rmid,null); return(0); Προγραμματισμός ΙΙΙ 17 lalis@inf.uth.gr
int main (int argc, char * argv []) { int shmid,i,key,*p,*argsflag,*args,*resflag,*res; client key = ftok(".",'a'); shmid=shmget(key,0,0); p = (int *)shmat(shmid,null,0); argsflag = p; args = p+1; resflag = p+n+1; res = p+n+2; while (*argsflag!= 0) {} // wait for argsflag to clear for (i=0; i<n; i++) { scanf("%d",&args[i]); } *resflag = 0; // clear res flag *argsflag = 1; // set args flag while (*resflag == 0) {} // wait for res flag to be set printf("result: %d\n",*res); } shmdt(p); return(0); Προγραμματισμός ΙΙΙ 18 lalis@inf.uth.gr
Κοινόχρηστη μνήμη και δείκτες Δεν έχει νόημα οι διεργασίες να «ανταλλάσσουν» δείκτες (δηλαδή διευθύνσεις εικονικής μνήμης) Εκτός αν μια διεύθυνση (α) δείχνει σε κοινόχρηστη περιοχή μνήμης (β) οι διεργασίες έχουν προσαρτήσει την συγκεκριμένη κοινόχρηστη περιοχή μνήμης στις ίδιες εικονικές διευθύνσεις Αν ισχύει μόνο το (α), ο δείκτης της μιας διεργασίας πρέπει να μετατρέπεται σε αντίστοιχο δείκτη στην άλλη διεργασία, μέσω κατάλληλου offset Προγραμματισμός II 19 lalis@inf.uth.gr
struct node { int val; struct node *nxt; }; 1. parent: create memory node 1 node 2 node 3 node 4 node 5 2. parent: fill values and create linked list 1 2 3 4 5 NULL 3. child: traverse linked list (via pointers pointing in shared memory) Προγραμματισμός ΙΙ 20 lalis@inf.uth.gr
struct node { int val; struct node *nxt; }; int main (int argc, char * argv []) { int shmid,pid; struct node *n,*n2; shmid = shmget(ipc_private,n*sizeof(struct node),s_irwxu); n = (struct node *)shmat(shmid,null,0); shmctl(shmid,ipc_rmid,null); // deferred for later for (n2=n; n2<n+n; n2++) { scanf("%d",&n2->val); n2->nxt = n2+1; } (n+n-1)->nxt = NULL; if (!(pid=fork())) { for (n2=n; n2!= NULL; n2=n2->nxt) { printf("%d\n",n2->val); } shmdt(n); return(0); } } waitpid(pid,null,0); shmdt(n); return(0); Προγραμματισμός ΙΙΙ 21 lalis@inf.uth.gr
struct node { int val; struct node *nxt; }; list creator L = sizeof(long); S = sizeof(struct node); A 1 A+L+1S 2 A+L+2S 3 A+L+3S 4 A+L+4S 5 NULL A A+L list reader A+L+1S A+L+2S A+L+3S A+L+4S A 1 A+L+1S 2 A+L+2S 3 A+L+3S 4 A+L+4S 5 NULL A' A'+L off = A'-A A+L+1S + off A+L+2S + off A+L+3S + off A+L+4S + off Προγραμματισμός ΙΙ 22 lalis@inf.uth.gr
int main (int argc, char * argv []) { int shmid; struct node *n,*n2; long *p; list creator shmid = shmget(ipc_private,sizeof(long)+ N*sizeof(struct node),s_irwxu); printf("shmid: %d\n",shmid); // input for reader p = (long *)shmat(shmid,null,0); *p = (long)p; // store attachment address n = (struct node *)(p+1); for (n2=n; n2<n+n; n2++) { scanf("%d",&n2->val); n2->nxt = n2+1; } (n+n-1)->nxt = NULL; } shmdt(p); return(0); Προγραμματισμός ΙΙΙ 23 lalis@inf.uth.gr
int main (int argc, char * argv []) { int shmid; struct node *n; long *p,off; list reader shmid = atoi(argv[1]); p = (long *)shmat(shmid,null,0); off = (long)p - *p; // calc offset for embedded ptrs n = (struct node *)(p+1); while (n!= NULL) { printf("%d\n",n->val); if (n->nxt == NULL) n = NULL; else n = (struct node *)(off + (long)(n->nxt)); } } shmdt(p); shmctl(shmid,ipc_rmid,null); return(0); Προγραμματισμός ΙΙΙ 24 lalis@inf.uth.gr