
 Υπάρχουν μερικά έργα εκεί έξω που χρησιμοποιούν το MappedByteBuffers που επέστρεψε το Java's FileChannel.map () ως τρόπο κοινής χρήσης μνήμης IPC μεταξύ JVMs στον ίδιο κεντρικό υπολογιστή (βλ. Chronicle Queue, Aeron IPC κ.λπ.). Από όσο μπορώ να πω, αυτό το api βρίσκεται ακριβώς πάνω από την κλήση mmap. Ωστόσο, η εφαρμογή Java δεν επιτρέπει ανώνυμες αντιστοιχίσεις (χωρίς υποστήριξη αρχείων). 

 Η ερώτησή μου είναι, σε Java (1.8) και Linux (3.10), τα MappedByteBuffers είναι πραγματικά απαραίτητα για την εφαρμογή κοινόχρηστης μνήμης IPC ή μήπως οποιαδήποτε πρόσβαση σε ένα κοινό αρχείο θα παρέχει την ίδια λειτουργικότητα; (Αυτή η ερώτηση δεν ασχολείται με τις επιπτώσεις απόδοσης της χρήσης ενός MappedByteBuffer ή όχι.) 

 Εδώ είναι η κατανόησή μου: 

1. Όταν το Linux φορτώνει ένα αρχείο από το δίσκο, αντιγράφει το περιεχόμενο αυτού του αρχείου σε σελίδες στη μνήμη. Αυτή η περιοχή μνήμης ονομάζεται προσωρινή μνήμη σελίδας. Από όσο μπορώ να πω, το κάνει αυτό ανεξάρτητα από τη μέθοδο Java (FileInputStream.read (), RandomAccessFile.read (), FileChannel.read (), FileChannel.map ()) ή την εγγενή μέθοδο που χρησιμοποιείται για την ανάγνωση του αρχείου ( παραλήφθηκε με "δωρεάν" και παρακολουθώντας την τιμή "cache").
2. Εάν μια άλλη διαδικασία προσπαθεί να φορτώσει το ίδιο αρχείο (ενώ εξακολουθεί να βρίσκεται στην προσωρινή μνήμη), ο πυρήνας το εντοπίζει και δεν χρειάζεται να φορτώσει ξανά το αρχείο. Εάν η προσωρινή μνήμη της σελίδας γεμίσει, οι σελίδες θα εκδιωχθούν - οι βρώμικες εγγράφονται πίσω στον δίσκο. (Οι σελίδες γράφονται και πάλι εάν υπάρχει ρητή έξαψη στο δίσκο και περιοδικά με ένα νήμα πυρήνα).
3. Το να υπάρχει ήδη ένα (μεγάλο) αρχείο στην κρυφή μνήμη είναι μια σημαντική αύξηση της απόδοσης, πολύ περισσότερο από τις διαφορές βάσει των μεθόδων Java που χρησιμοποιούμε για το άνοιγμα / ανάγνωση αυτού του αρχείου.
4. Το πρόγραμμα AC που καλεί την κλήση συστήματος mmap μπορεί να κάνει μια ΑΝΩΝΥΜΗ αντιστοίχιση, η οποία εκχωρεί ουσιαστικά σελίδες στην προσωρινή μνήμη που δεν υποστηρίζονται από ένα πραγματικό αρχείο (οπότε δεν χρειάζεται να εκδίδονται πραγματικές εγγραφές στο δίσκο), αλλά η Java δεν φαίνεται για να το προσφέρω (θα χαρτογραφήσει ένα αρχείο σε *tmpfs* το ίδιο πράγμα;)
5. Εάν ένα αρχείο φορτώνεται χρησιμοποιώντας την κλήση συστήματος mmap (C) ή μέσω FileChannel.map () (Java), ουσιαστικά οι σελίδες του αρχείου (στην κρυφή μνήμη) φορτώνονται απευθείας στον χώρο διευθύνσεων της διαδικασίας. Χρησιμοποιώντας άλλες μεθόδους για να ανοίξετε ένα αρχείο, το αρχείο φορτώνεται σε σελίδες που δεν βρίσκονται στο χώρο διευθύνσεων της διαδικασίας και, στη συνέχεια, οι διάφορες μέθοδοι για την ανάγνωση / εγγραφή αυτού του αρχείου αντιγράφουν μερικά bytes από / προς αυτές τις σελίδες σε ένα buffer στον χώρο διευθύνσεων της διαδικασίας . Υπάρχει ένα προφανές όφελος απόδοσης αποφεύγοντας αυτό το αντίγραφο, αλλά η ερώτησή μου δεν αφορά την απόδοση.

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

 Λοιπόν, παρακαλώ επιτρέψτε μου να ξέρω πού είναι η κατανόηση μου. 

 Ευχαριστώ. 

 
Χρησιμοποιώντας αρχεία για κοινή μνήμη IPC, απαιτείται η χαρτογράφηση μνήμης;
=============================================================================



 Αξίζει να αναφέρουμε τρία σημεία: απόδοση, και ταυτόχρονες αλλαγές και χρήση μνήμης. 

 Έχετε δίκιο στην εκτίμηση ότι το MMAP-based συνήθως προσφέρει πλεονέκτημα απόδοσης σε σχέση με το IO που βασίζεται σε αρχεία. Συγκεκριμένα, το πλεονέκτημα απόδοσης είναι σημαντικό εάν ο κώδικας εκτελεί πολλά μικρά IO στο αυθαίρετο σημείο του αρχείου. 

 εξετάστε το ενδεχόμενο αλλαγής του N-th byte: με mmap `buffer[N] = buffer[N] + 1` και με πρόσβαση βάσει αρχείων χρειάζεστε (τουλάχιστον) 4 ελέγχους σφαλμάτων κλήσεων συστήματος: 


```
   seek() + error check
   read() + error check
   update value
   seek() + error check
   write + error check

```
 Είναι αλήθεια ότι ο αριθμός των πραγματικών IO (στο δίσκο) πιθανότατα είναι ο ίδιος. 

 Το δεύτερο σημείο αξίζει να σημειωθεί η ταυτόχρονη πρόσβαση. Με IO που βασίζεται σε αρχεία, πρέπει να ανησυχείτε για πιθανή ταυτόχρονη πρόσβαση. Θα χρειαστεί να εκδώσετε ρητό κλείδωμα (πριν από την ανάγνωση) και να ξεκλειδώσετε (μετά την εγγραφή), για να αποτρέψετε δύο διαδικασίες για εσφαλμένη πρόσβαση στην τιμή ταυτόχρονα. Με κοινή μνήμη, οι ατομικές λειτουργίες μπορούν να εξαλείψουν την ανάγκη για πρόσθετο κλείδωμα. 

 Το τρίτο σημείο είναι η πραγματική χρήση μνήμης. Για περιπτώσεις όπου το μέγεθος των κοινόχρηστων αντικειμένων είναι σημαντικό, η χρήση κοινόχρηστης μνήμης μπορεί να επιτρέψει σε μεγάλο αριθμό διαδικασιών να αποκτήσουν πρόσβαση στα δεδομένα χωρίς να εκχωρηθεί επιπλέον μνήμη. Εάν τα συστήματα περιορίζονται από τη μνήμη ή από σύστημα που πρέπει να παρέχει απόδοση σε πραγματικό χρόνο, αυτός θα μπορούσε να είναι ο μόνος τρόπος πρόσβασης στα δεδομένα. 

 


>  Η ερώτησή μου είναι, σε Java (1.8) και Linux (3.10), τα MappedByteBuffers είναι πραγματικά απαραίτητα για την εφαρμογή κοινόχρηστης μνήμης IPC ή μήπως οποιαδήποτε πρόσβαση σε ένα κοινό αρχείο θα παρέχει την ίδια λειτουργικότητα; 
> 
> 

 Εξαρτάται από το *γιατί* θέλετε να εφαρμόσετε κοινόχρηστη μνήμη IPC. 

 Μπορείτε να εφαρμόσετε σαφώς το IPC χωρίς κοινόχρηστη μνήμη. π.χ. πάνω από πρίζες. Επομένως, εάν δεν το κάνετε για λόγους απόδοσης, δεν είναι απαραίτητο να κάνετε κοινή χρήση IPC μνήμης! 

 Επομένως, η απόδοση πρέπει να βρίσκεται στη ρίζα κάθε συζήτησης. 

 Η πρόσβαση με χρήση αρχείων μέσω του Java κλασικού io ή nio API δεν παρέχει λειτουργικότητα ή απόδοση κοινόχρηστης μνήμης. 

 Η κύρια διαφορά μεταξύ κανονικού αρχείου I / O ή Socket I / O έναντι κοινόχρηστης μνήμης IPC είναι ότι η πρώτη απαιτεί από τις εφαρμογές να κάνουν ρητά `read` και `write` syscalls για αποστολή και λήψη μηνυμάτων. Αυτό συνεπάγεται επιπλέον syscalls και συνεπάγεται δεδομένα αντιγραφής του πυρήνα. Επιπλέον, εάν υπάρχουν πολλά νήματα, είτε χρειάζεστε ένα ξεχωριστό "κανάλι" μεταξύ κάθε ζεύγους νήματος ή κάτι για την πολυπλεξία πολλαπλών "συνομιλιών" μέσω ενός κοινόχρηστου καναλιού. Το τελευταίο μπορεί να οδηγήσει στο κοινόχρηστο κανάλι να γίνει ταυτόχρονη συμφόρηση. 

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

 Αντίθετα, με την εφαρμογή IPC που χρησιμοποιούν κοινόχρηστη μνήμη, δεν υπάρχουν `read` και `write` syscalls και χωρίς επιπλέον βήμα αντιγραφής. Κάθε "κανάλι" μπορεί απλά να χρησιμοποιήσει μια ξεχωριστή περιοχή του αντιστοιχισμένου buffer. Ένα νήμα σε μία διαδικασία γράφει δεδομένα στην κοινόχρηστη μνήμη και είναι σχεδόν άμεσα ορατό στη δεύτερη διαδικασία. 

 Η προειδοποίηση είναι ότι οι διαδικασίες πρέπει να 1) συγχρονιστούν και 2) να εφαρμόσουν εμπόδια μνήμης για να διασφαλίσουν ότι ο αναγνώστης δεν βλέπει τα παλιά δεδομένα. Αλλά αυτά και τα δύο μπορούν να εφαρμοστούν χωρίς syscalls. 

 Στο πλύσιμο, η κοινή μνήμη IPC που χρησιμοποιεί αρχεία που αντιστοιχίζονται στη μνήμη >> είναι << ταχύτερη από τη χρήση συμβατικών αρχείων ή υποδοχών και γι 'αυτό το κάνουν οι άνθρωποι. 



---

 Ρωτήσατε επίσης σιωπηρά αν η κοινή χρήση μνήμης IPC μπορεί να εφαρμοστεί χωρίς αρχεία που έχουν αντιστοιχιστεί στη μνήμη. 

* Ένας πρακτικός τρόπος θα ήταν να δημιουργήσετε ένα αρχείο που έχει αντιστοιχιστεί στη μνήμη για ένα αρχείο που ζει σε ένα σύστημα αρχείων μόνο για μνήμη. π.χ. ένα "tmpfs" στο Linux. 

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


	+ Στη γονική διαδικασία, χρησιμοποιήστε mmap για να δημιουργήσετε ένα τμήμα με `MAP_ANONYMOUS | MAP_SHARED` .
	+ Διαδικασίες παιδικού πιρουνιού. Αυτά θα καταλήξουν σε κάθε κοινή χρήση του τμήματος μεταξύ τους και της γονικής διαδικασίας. Ωστόσο, η εφαρμογή αυτού για μια διαδικασία Java θα ήταν ... πρόκληση. AFAIK, η Java δεν το υποστηρίζει.

 Αναφορά: 

* [Ποιος είναι ο σκοπός της MAP\_ANONYMOUS flag στην κλήση συστήματος mmap;](https://stackoverflow.com/questions/34042915/what-is-the-purpose-of-map-anonymous-flag-in-mmap-system-call)

 