Μια εις βάθος εξερεύνηση στο SDCardFS, την αντικατάσταση της Google για το FUSE, και πώς η υλοποίησή του θα μειώσει τα έξοδα εισόδου/εξόδου.
Πριν από αρκετούς μήνες, η Google πρόσθεσε κάτι που ονομάζεται "SDCardFS” στα επίσημα υποκαταστήματα AOSP για τον πυρήνα του Linux. Τότε, η κίνηση έγινε αντιληπτή μόνο από ορισμένοι προγραμματιστές πυρήνα, αλλά κατά τα άλλα πέταξε κάτω από το ραντάρ των περισσότερων χρηστών. Δεν υπάρχει έκπληξη, δεδομένου του γεγονότος ότι οι περισσότεροι χρήστες, συμπεριλαμβανομένου του εαυτού μου, δεν γνωρίζουν πραγματικά τι συμβαίνει κάτω από την κουκούλα του λειτουργικού συστήματος Android και του πυρήνα του.
Ωστόσο, το πιο πρόσφατο επεισόδιο του Android Developers Backstage Το podcast ανανέωσε το ενδιαφέρον για αυτό το θέμα. Το podcast, που φιλοξενήθηκε από τον Chet Haase (ανώτερο μηχανικό λογισμικού στην Google), διερεύνησε πρόσφατες και επερχόμενες αλλαγές που έγιναν στον πυρήνα. Στην εκπομπή ήταν ένας προγραμματιστής πυρήνα Linux που εργαζόταν στην ομάδα Android - ο Rom Lemarchand. Το δίδυμο συζήτησε κυρίως ποιες αλλαγές έγιναν για την προσαρμογή των ενημερώσεων A/B, αλλά στα τελευταία 5 λεπτά του επεισοδίου ο κ. Lemarchand μίλησε για «το επόμενο μεγάλο πράγμα» στο οποίο εργαζόταν η ομάδα του -
Πρέπει να ομολογήσω ότι έμαθα για την ύπαρξη του SDCardFS αφού άκουσα αυτό το podcast. Φυσικά, δεν ήμουν ο μόνος που ενδιαφέρθηκε για αυτό το θέμα, καθώς α πρόσφατο νήμα του Reddit έχει δείξει. Ωστόσο, δεν έμεινα ικανοποιημένος με τη βασική εξήγηση που προσφέρθηκε στο podcast και σε μια προσπάθεια να διαλύσω μερικά από τα παραπληροφόρηση που διαδίδεται, έκανα κάποια δική μου έρευνα και μίλησα με μερικούς ειδικούς με σχετική γνώση για το ύλη.
Ευχαριστώ πολύ τον προγραμματιστή λογισμικού Michal Kowalczyk για τη συνεισφορά του στις γνώσεις του σε αυτό το άρθρο και για τον χρόνο που αφιέρωσε για να απαντήσει στις ερωτήσεις μου.
Το "εξωτερικό" είναι πραγματικά εσωτερικό
Αμέσως μετά, σίγουρα θα υπάρχουν κάποιες παρανοήσεις που πρέπει να ξεκαθαρίσουμε - διαφορετικά το υπόλοιπο άρθρο θα είναι πολύ μπερδεμένο. Είναι χρήσιμο να συζητήσετε το ιστορικό των καρτών SD και των τηλεφώνων Android.
Στις πρώτες μέρες των τηλεφώνων Android, σχεδόν κάθε συσκευή βασιζόταν στη χρήση των καρτών microSD για αποθήκευση. Αυτό οφειλόταν στο γεγονός ότι τα τηλέφωνα εκείνη την εποχή αποστέλλονταν με ελάχιστες χωρητικότητες εσωτερικής αποθήκευσης. Ωστόσο, οι κάρτες SD που χρησιμοποιούνται για την αποθήκευση εφαρμογών συχνά δεν παρέχουν μια εκπληκτική εμπειρία χρήστη, τουλάχιστον σε σύγκριση με την ταχύτητα με την οποία η εσωτερική μνήμη flash μπορεί να διαβάσει/εγγράψει δεδομένα. Ως εκ τούτου, η αυξανόμενη χρήση καρτών SD για εξωτερική αποθήκευση δεδομένων γινόταν ανησυχία για την εμπειρία χρήστη για την Google.
Λόγω του πρώιμου πολλαπλασιασμού των καρτών SD ως εξωτερικών συσκευών αποθήκευσης, οι συμβάσεις ονομασίας αποθήκευσης του Android βασίστηκαν στο γεγονός ότι κάθε συσκευή είχε μια πραγματική, φυσική υποδοχή κάρτας microSD. Αλλά ακόμα και σε συσκευές που δεν περιείχαν υποδοχή κάρτας SD, η ετικέτα /sdcard εξακολουθούσε να χρησιμοποιείται για να δείχνει το πραγματικό τσιπ εσωτερικής αποθήκευσης. Πιο μπερδεμένο είναι το γεγονός ότι οι συσκευές που χρησιμοποιούσαν τόσο μια φυσική κάρτα SD όσο και ένα τσιπ αποθήκευσης υψηλής χωρητικότητας για αποθήκευση συχνά ονομάζουν τα διαμερίσματα τους με βάση την κάρτα SD. Για παράδειγμα, σε αυτές τις συσκευές το σημείο προσάρτησης /sdcard θα αναφέρεται στο πραγματικό τσιπ εσωτερικής αποθήκευσης, ενώ κάτι σαν το /storage/sdcard1 θα αναφέρεται στη φυσική εξωτερική κάρτα.
Έτσι, παρόλο που η κάρτα microSD πρακτικά θεωρείται ότι είναι εξωτερική αποθήκευση, η σύμβαση ονομασίας είχε ως αποτέλεσμα η "SDCard" να παραμένει εδώ και πολύ καιρό μετά από οποιαδήποτε πραγματική χρήση μιας φυσικής κάρτας. Αυτή η σύγχυση με την αποθήκευση προκάλεσε επίσης κάποιο πονοκέφαλο στους προγραμματιστές εφαρμογών λόγω του γεγονότος ότι τα δεδομένα της εφαρμογής και τα μέσα της ήταν διαχωρισμένα μεταξύ των δύο κατατμήσεων.
Ο χαμηλός χώρος αποθήκευσης των πρώιμων τσιπ εσωτερικής αποθήκευσης είχε ως αποτέλεσμα οι χρήστες να ανακαλύπτουν με απογοήτευση ότι δεν μπορούσαν πλέον να εγκαταστήσουν εφαρμογές (λόγω του πληρώματος του διαμερίσματος /data). Εν τω μεταξύ, οι κάρτες microSD μεγαλύτερης χωρητικότητας υποβιβάστηκαν στην αποθήκευση μόνο μέσων (όπως φωτογραφίες, μουσική και ταινίες). Οι χρήστες που περιηγήθηκαν στα φόρουμ μας παλιά μπορεί να θυμούνται αυτά τα ονόματα: Link2SD και Apps2SD. Αυτές ήταν λύσεις (root) που επέτρεπαν στους χρήστες να εγκαταστήσουν τις εφαρμογές τους και τα δεδομένα τους όλα στη φυσική κάρτα SD. Αλλά αυτές δεν ήταν τέλειες λύσεις, οπότε η Google έπρεπε να παρέμβει.
Ως γνωστόν, η Google τράβηξε την πρίζα από τις κάρτες SD πολύ νωρίς. Το Nexus One παραμένει η μοναδική συσκευή Nexus με υποδοχή κάρτας microSD (και θα είναι για πάντα αφού η επωνυμία Nexus είναι ουσιαστικά νεκρή). Με το Nexus S, υπήρχε πλέον μόνο ένα, ενοποιημένο διαμέρισμα για την αποθήκευση όλων των δεδομένων εφαρμογών και των μέσων - το διαμέρισμα /data. Αυτό που κάποτε ήταν γνωστό ως σημείο προσάρτησης /sdcard τώρα αναφερόταν απλώς σε ένα εικονικό σύστημα αρχείων (που υλοποιείται στο ΑΣΦΑΛΕΙΑ ΗΛΕΚΤΡΙΚΗ πρωτόκολλο όπως συζητείται παρακάτω) που βρίσκεται στο διαμέρισμα δεδομένων - /data/media/0.
Προκειμένου να διατηρήσει τη συμβατότητα και να μειώσει τη σύγχυση, η Google εξακολουθούσε να χρησιμοποιεί αυτό το πλέον εικονικό διαμέρισμα "sdcard" για τη διατήρηση πολυμέσων. Αλλά τώρα που αυτό το εικονικό διαμέρισμα "sdcard" βρισκόταν στην πραγματικότητα μέσα στο /data, οτιδήποτε είναι αποθηκευμένο σε αυτό θα μετρούσε στον αποθηκευτικό χώρο του εσωτερικού τσιπ αποθήκευσης. Έτσι, εναπόκειτο στους OEM να εξετάσουν πόσο χώρο θα διαθέσουν στις εφαρμογές (/data) έναντι των μέσων (/data/media).
Η Google ήλπιζε οι κατασκευαστές να ακολουθήσουν το παράδειγμά τους και να απαλλαγούν από τις κάρτες SD. Ευτυχώς, με την πάροδο του χρόνου οι κατασκευαστές τηλεφώνων μπόρεσαν να προμηθεύονται αυτά τα εξαρτήματα σε υψηλότερες χωρητικότητες, ενώ παρέμεναν οικονομικά αποδοτικές, έτσι η ανάγκη για κάρτες SD άρχισε να εξαντλείται. Ωστόσο, οι συμβάσεις ονομασίας εξακολουθούν να μειώνουν την προσπάθεια που θα έπρεπε να καταβάλουν οι προγραμματιστές και οι ΚΑΕ για να προσαρμοστούν. Επί του παρόντος, όταν αναφερόμαστε σε "εξωτερική αποθήκευση" αναφερόμαστε είτε ένα από τα δύο πράγματα: η πραγματική αφαιρούμενη κάρτα microSD ή το εικονικό διαμέρισμα "SDCard" που βρίσκεται στο /data/media. Το τελευταίο από αυτά, πρακτικά, είναι στην πραγματικότητα εσωτερική αποθήκευση, αλλά η σύμβαση ονομασίας της Google τη διαφοροποιεί λόγω του γεγονότος ότι αυτά τα δεδομένα είναι προσβάσιμα στον χρήστη (όπως όταν είναι συνδεδεμένα στον υπολογιστή).
Επί του παρόντος, όταν αναφερόμαστε σε "εξωτερική αποθήκευση" αναφερόμαστε είτε ένα από τα δύο πράγματα: η πραγματική αφαιρούμενη κάρτα microSD ή το εικονικό διαμέρισμα "SDCard" που βρίσκεται στο /data/media.
Η ιστορία των εικονικών συστημάτων αρχείων του Android
Τώρα που η "sdcard" αντιμετωπίζεται ως εικονικό σύστημα αρχείων, σήμαινε ότι θα μπορούσε να μορφοποιηθεί όπως οποιοδήποτε σύστημα αρχείων ήθελε η Google. Ξεκινώντας με το Nexus S και το Android 2.3, η Google επέλεξε να μορφοποιήσει την "sdcard" ως VFAT (εικονικό FAT). Αυτή η κίνηση είχε νόημα εκείνη την εποχή, καθώς η τοποθέτηση VFAT θα επέτρεπε σε σχεδόν οποιονδήποτε υπολογιστή να έχει πρόσβαση στα δεδομένα που είναι αποθηκευμένα στο τηλέφωνό σας. Ωστόσο, υπήρχαν δύο σημαντικά ζητήματα με αυτήν την αρχική εφαρμογή.
Το πρώτο αφορά πρωτίστως τον τελικό χρήστη (εσείς). Για να συνδέσετε τη συσκευή σας στον υπολογιστή σας, θα χρησιμοποιούσατε τη λειτουργία μαζικής αποθήκευσης USB για τη μεταφορά δεδομένων. Αυτό, ωστόσο, απαιτούσε από τη συσκευή Android να αποσυνδέσει το εικονικό διαμέρισμα πριν ο υπολογιστής μπορέσει να αποκτήσει πρόσβαση στα δεδομένα. Εάν ένας χρήστης ήθελε να χρησιμοποιήσει τη συσκευή του ενώ είναι συνδεδεμένος, πολλά πράγματα θα εμφανίζονταν ως μη διαθέσιμα.
ο εισαγωγή του πρωτοκόλλου μεταφοράς πολυμέσων (MTP) έλυσε αυτό το πρώτο ζήτημα. Όταν είναι συνδεδεμένος, ο υπολογιστής σας βλέπει τη συσκευή σας ως συσκευή αποθήκευσης πολυμέσων. Ζητάει μια λίστα αρχείων από το τηλέφωνό σας και το MTP επιστρέφει μια λίστα αρχείων που μπορεί να κατεβάσει ο υπολογιστής από τη συσκευή. Όταν ζητείται η διαγραφή ενός αρχείου, το MTP στέλνει μια εντολή για να αφαιρέσει το ζητούμενο αρχείο από την αποθήκευση. Σε αντίθεση με τη λειτουργία μαζικής αποθήκευσης USB που στην πραγματικότητα τοποθετεί την «κάρτα sd», το MTP επιτρέπει στον χρήστη να συνεχίσει να χρησιμοποιεί τη συσκευή του ενώ είναι συνδεδεμένος. Επιπλέον, το σύστημα αρχείων που υπάρχει στο τηλέφωνο Android δεν έχει πλέον σημασία για τον υπολογιστή να αναγνωρίσει τα αρχεία στη συσκευή.
Δεύτερον, υπήρχε το γεγονός ότι το VFAT δεν παρείχε το είδος της ισχυρής διαχείρισης αδειών που χρειαζόταν η Google. Από νωρίς, πολλοί προγραμματιστές εφαρμογών θα αντιμετώπιζαν την "sdcard" ως χωματερή για τα δεδομένα της εφαρμογής τους, χωρίς ενιαία αίσθηση του πού να αποθηκεύουν τα αρχεία τους. Πολλές εφαρμογές θα δημιουργήσουν απλώς έναν φάκελο με το όνομα της εφαρμογής τους και θα αποθηκεύουν εκεί τα αρχεία τους.
Σχεδόν κάθε εφαρμογή εκεί έξω εκείνη τη στιγμή απαιτούσε το WRITE_EXTERNAL_STORAGE άδεια εγγραφής των αρχείων εφαρμογής τους στην εξωτερική αποθήκευση. Ωστόσο, αυτό που ήταν πιο ανησυχητικό ήταν το γεγονός ότι σχεδόν κάθε εφαρμογή απαιτούσε επίσης το READ_EXTERNAL_STORAGE άδεια - απλώς για να διαβάσουν τα δικά τους αρχεία δεδομένων! Αυτό σήμαινε ότι οι εφαρμογές θα μπορούσαν εύκολα να έχουν πρόσβαση σε δεδομένα που είναι αποθηκευμένα οπουδήποτε στον εξωτερικό χώρο αποθήκευσης, και μια τέτοια άδεια χορηγούνταν συχνά από τον χρήστη, επειδή απαιτούνταν για πολλές εφαρμογές να εξισορροπήσουν λειτουργία.
Η Google το θεώρησε ξεκάθαρα ως προβληματικό. Η όλη ιδέα πίσω από τη διαχείριση αδειών είναι να διαχωρίσουμε σε ποιες εφαρμογές μπορούν και σε τι δεν μπορούν να έχουν πρόσβαση. Εάν σχεδόν σε κάθε εφαρμογή παραχωρείται πρόσβαση ανάγνωσης σε δυνητικά ευαίσθητα δεδομένα χρήστη, τότε η άδεια δεν έχει νόημα. Έτσι, η Google αποφάσισε ότι χρειαζόταν μια νέα προσέγγιση. Εκεί μπαίνει το FUSE.
Σύστημα αρχείων στον χώρο χρήστη (FUSE)
Ξεκινώντας με το Android 4.4, η Google αποφάσισε να μην προσαρτήσει πλέον το εικονικό διαμέρισμα "sdcard" ως VFAT. Αντίθετα, η Google άρχισε να χρησιμοποιεί το FUSE για να μιμηθεί το FAT32 στο εικονικό διαμέρισμα "sdcard". Με το πρόγραμμα sdcard που καλεί FUSE για εξομοίωση αδειών καταλόγου τύπου FAT-on-sdcard, οι εφαρμογές θα μπορούσαν να αρχίσουν να έχουν πρόσβαση στα δεδομένα της που είναι αποθηκευμένα σε εξωτερικό χώρο αποθήκευσης χωρίς να απαιτούνται άδειες. Πράγματι, ξεκινώντας από το επίπεδο API 19, το READ_EXTERNAL_STORAGE δεν χρειαζόταν πλέον για πρόσβαση σε αρχεία που βρίσκονται σε εξωτερικό χώρο αποθήκευσης - με την προϋπόθεση ότι ο φάκελος δεδομένων που δημιουργήθηκε από τον δαίμονα FUSE ταιριάζει με το όνομα του πακέτου της εφαρμογής. FUSE θα χειριζόταν σύνθεση του κατόχου, της ομάδας και των τρόπων λειτουργίας αρχείων σε εξωτερικό χώρο αποθήκευσης όταν εγκαθίσταται μια εφαρμογή.
Το FUSE διαφέρει από τις μονάδες εντός πυρήνα, καθώς επιτρέπει σε μη προνομιούχους χρήστες να γράφουν εικονικά συστήματα αρχείων. Ο λόγος που η Google εφάρμοσε το FUSE είναι μάλλον απλός - έκανε αυτό που ήθελαν και ήταν ήδη καλά κατανοητό και τεκμηριωμένο στον κόσμο του Linux. Για να παραθέσω α προγραμματιστής της Google σχετικά με το θέμα:
"Επειδή το FUSE είναι ένα ωραίο σταθερό API, ουσιαστικά δεν απαιτείται εργασία συντήρησης όταν μετακινείστε μεταξύ των εκδόσεων του πυρήνα. Εάν πραγματοποιούσαμε μετεγκατάσταση σε μια λύση εντός πυρήνα, θα εγγραφήκαμε για τη διατήρηση ενός συνόλου ενημερώσεων κώδικα για κάθε σταθερή έκδοση πυρήνα." -Jeff Sharkey, Μηχανικός Λογισμικού στην Google
Ωστόσο, γινόταν πολύ σαφές ότι τα γενικά έξοδα του FUSE εισήγαγαν μια επιτυχία στην απόδοση μεταξύ άλλων ζητημάτων. Ο προγραμματιστής με τον οποίο μίλησα σχετικά με αυτό το θέμα, Michal Kowalczyk, έγραψε μια εξαιρετική ανάρτηση στο blog πριν από περισσότερο από ένα χρόνο περιγράφοντας λεπτομερώς τα τρέχοντα προβλήματα με το FUSE. Περισσότερες τεχνικές λεπτομέρειες μπορείτε να διαβάσετε στο blog του, αλλά θα περιγράψω τα ευρήματά του (με την άδειά του) με πιο απλούς όρους.
Το πρόβλημα με την ασφάλεια
Στο Android, ο δαίμονας του userpace "sdcard" χρησιμοποιεί το FUSE για να προσαρτήσει το /dev/fuse στον εξομοιούμενο κατάλογο εξωτερικού χώρου αποθήκευσης κατά την εκκίνηση. Μετά από αυτό, ο δαίμονας sdcard ψηφίζει τη συσκευή FUSE για τυχόν εκκρεμή μηνύματα από τον πυρήνα. Αν ακούσατε το podcast, ίσως έχετε ακούσει τον κ. Lemarchand να αναφέρεται στο FUSE που εισάγει το overhead κατά τις λειτουργίες I/O - εδώ είναι ουσιαστικά τι συμβαίνει.
Στον πραγματικό κόσμο, αυτό το χτύπημα απόδοσης επηρεάζει όποιος αρχείο που είναι αποθηκευμένο σε εξωτερικό χώρο αποθήκευσης.
Πρόβλημα #1 - Γενικά I/O
Ας πούμε ότι δημιουργούμε ένα απλό αρχείο κειμένου, που ονομάζεται "test.txt", και το αποθηκεύουμε στο /sdcard/test.txt (το οποίο, ας σας υπενθυμίζω, είναι στην πραγματικότητα /data/media/0/test.txt υποθέτοντας ότι ο τρέχων χρήστης είναι ο κύριος χρήστης στο συσκευή). Αν θέλαμε να διαβάσουμε (command cat) αυτό το αρχείο, θα περιμέναμε το σύστημα να εκδώσει 3 εντολές: άνοιγμα, ανάγνωση και μετά κλείσιμο. Πράγματι, όπως αποδεικνύει ο κ. Kowalczyk χρησιμοποιώντας στρας, αυτό συμβαίνει:
Επειδή όμως το αρχείο βρίσκεται στον εξωτερικό χώρο αποθήκευσης που διαχειρίζεται ο δαίμονας sdcard, υπάρχουν πολλές πρόσθετες λειτουργίες που πρέπει να εκτελεστούν. Σύμφωνα με τον κ. Kowalczyk, χρειάζονται ουσιαστικά 8 επιπλέον βήματα για καθεμία από αυτές τις 3 μεμονωμένες εντολές:
- Κλήση συστήματος ζητημάτων εφαρμογής χώρου χρήστη που θα χειρίζεται το πρόγραμμα οδήγησης FUSE στον πυρήνα (το βλέπουμε στην έξοδο πρώτης γραμμής)
- Το πρόγραμμα οδήγησης FUSE στον πυρήνα ειδοποιεί τον δαίμονα χώρου χρήστη (sdcard) για νέο αίτημα
- Ο δαίμονας του χώρου χρήστη διαβάζει /dev/fuse
- Ο δαίμονας του χώρου χρήστη αναλύει την εντολή και αναγνωρίζει τη λειτουργία αρχείου (π.χ. Άνοιξε)
- Ο δαίμονας του χώρου χρήστη ζητά κλήση συστήματος στο πραγματικό σύστημα αρχείων (EXT4)
- Ο πυρήνας διαχειρίζεται την πρόσβαση σε φυσικά δεδομένα και στέλνει δεδομένα πίσω στον χώρο χρηστών
- Ο χώρος χρήστη τροποποιεί (ή όχι) δεδομένα και τα περνάει ξανά από το /dev/fuse στον πυρήνα
- Ο πυρήνας ολοκληρώνει την αρχική κλήση συστήματος και μετακινεί δεδομένα στην πραγματική εφαρμογή χώρου χρηστών (στο παράδειγμά μας cat)
Αυτό φαίνεται σαν πολύ των γενικών εξόδων σε μία μόνο εντολή I/O που θα εκτελεστεί. Και θα είχες δίκιο. Για να το αποδείξει αυτό, ο κ. Kowalczyk επιχείρησε δύο διαφορετικές δοκιμές εισόδου/εξόδου: η μία περιελάμβανε αντιγραφή μεγάλου αρχείου και η άλλη αντιγραφή πολλών μικρών αρχείων. Συνέκρινε την ταχύτητα του FUSE (στο εικονικό διαμέρισμα που είναι τοποθετημένο ως FAT32) που χειρίζεται αυτές τις λειτουργίες με το πυρήνα (στο διαμέρισμα δεδομένων που έχει μορφοποιηθεί ως EXT4) και διαπίστωσε ότι το FUSE συνέβαλε πράγματι σημαντικά πάνω από το κεφάλι.
Στην πρώτη δοκιμή, αντέγραψε ένα αρχείο 725 MB και στις δύο συνθήκες δοκιμής. Βρήκε ότι η εφαρμογή FUSE μετέφερε μεγάλα αρχεία 17% πιο αργά.
Στη δεύτερη δοκιμή, αντέγραψε 10.000 αρχεία - το καθένα από αυτά μεγέθους 5KB. Σε αυτό το σενάριο, η εφαρμογή FUSE είχε τελειώσει 40 δευτερόλεπτα πιο αργά για να αντιγράψετε βασικά δεδομένα αξίας 50 MB.
Στον πραγματικό κόσμο, αυτό το χτύπημα απόδοσης επηρεάζει όποιος αρχείο που είναι αποθηκευμένο σε εξωτερικό χώρο αποθήκευσης. Αυτό σημαίνει εφαρμογές όπως Χάρτες που αποθηκεύουν μεγάλα αρχεία σε /sdcard, Μουσικές εφαρμογές που αποθηκεύουν τόνους αρχείων μουσικής, εφαρμογές κάμερας και φωτογραφίες κ.λπ. Οποιαδήποτε λειτουργία I/O που εκτελείται και περιλαμβάνει την εξωτερική αποθήκευση επηρεάζεται από τα γενικά έξοδα του FUSE. Αλλά η επιβάρυνση I/O δεν είναι το μόνο πρόβλημα με το FUSE.
Πρόβλημα #2 - Διπλή προσωρινή αποθήκευση
Η προσωρινή αποθήκευση δεδομένων είναι σημαντική για τη βελτίωση της απόδοσης πρόσβασης στα δεδομένα. Αποθηκεύοντας βασικά κομμάτια δεδομένων στη μνήμη, ο πυρήνας του Linux είναι σε θέση να ανακαλεί γρήγορα αυτά τα δεδομένα όταν χρειάζεται. Όμως, λόγω του τρόπου με τον οποίο υλοποιείται το FUSE, το Android αποθηκεύει διπλάσια ποσότητα μνήμης cache που απαιτείται.
Όπως αποδεικνύει ο κ. Kowalczyk, ένα αρχείο 10 MB αναμένεται να αποθηκευτεί στην κρυφή μνήμη ακριβώς 10 MB, αλλά αντ' αυτού θα αυξηθεί στο μέγεθος της κρυφής μνήμης κατά περίπου 20 MB. Αυτό είναι προβληματικό σε συσκευές με λιγότερη μνήμη RAM, καθώς ο πυρήνας Linux αποθηκεύει την προσωρινή μνήμη σελίδων για την αποθήκευση δεδομένων σε μνήμη. Ο κ. Kowalczyk δοκίμασε αυτό το ζήτημα διπλής προσωρινής αποθήκευσης χρησιμοποιώντας αυτήν την προσέγγιση:
- Δημιουργήστε ένα αρχείο με γνωστό μέγεθος (για δοκιμή, 10MB)
- Αντιγράψτε το στο /sdcard
- Ρίξτε την προσωρινή μνήμη της σελίδας
- Πάρτε ένα στιγμιότυπο της χρήσης της προσωρινής μνήμης σελίδας
- Διαβάστε το αρχείο δοκιμής
- Τραβήξτε ένα άλλο στιγμιότυπο της χρήσης της προσωρινής μνήμης σελίδας
Αυτό που βρήκε ήταν ότι πριν από τη δοκιμή του, 241 MB χρησιμοποιήθηκαν από τον πυρήνα για την προσωρινή μνήμη σελίδων. Μόλις διάβασε το δοκιμαστικό του αρχείο, περίμενε να δει 251 MB να χρησιμοποιούνται για την προσωρινή μνήμη σελίδων. Αντ 'αυτού, διαπίστωσε ότι αυτός ο πυρήνας χρησιμοποιούσε 263 MB για προσωρινή μνήμη σελίδας - περίπου διπλάσιο από το αναμενόμενο. Ο λόγος που συμβαίνει αυτό είναι επειδή τα δεδομένα αποθηκεύονται πρώτα στην προσωρινή μνήμη από την εφαρμογή χρήστη που εξέδωσε αρχικά την κλήση I/O (FUSE) και, δεύτερον, από τον δαίμονα της κάρτας sdcard (EXT4 FS).
Πρόβλημα #3 - Ημιτελής υλοποίηση του FAT32
Υπάρχουν δύο ακόμη ζητήματα που προκύπτουν από τη χρήση του FAT32 που προσομοιώνει FUSE, τα οποία είναι λιγότερο ευρέως γνωστά στην κοινότητα Android.
Το πρώτο περιλαμβάνει λανθασμένες χρονικές σημάνσεις. Εάν έχετε ποτέ μεταφέρει ένα αρχείο (όπως μια φωτογραφία) και παρατηρήσετε ότι η χρονική σήμανση είναι λανθασμένη, αυτό οφείλεται στην εφαρμογή του FUSE από το Android. Αυτό το θέμα έχει υπήρχε για χρόνια. Για να γίνουμε πιο συγκεκριμένοι, το θέμα αφορά το utime() κλήση συστήματος που σας επιτρέπει να αλλάξετε τον χρόνο πρόσβασης και τροποποίησης ενός αρχείου. Δυστυχώς, οι κλήσεις που γίνονται στον δαίμονα της κάρτας sdcard ως τυπικός χρήστης δεν έχουν την κατάλληλη άδεια για την εκτέλεση αυτής της κλήσης συστήματος. Υπάρχουν λύσεις για αυτό, αλλά το απαιτούν έχουν πρόσβαση root.
Εάν έχετε ποτέ μεταφέρει ένα αρχείο (όπως μια φωτογραφία) και παρατηρήσετε ότι η χρονική σήμανση είναι λανθασμένη, αυτό οφείλεται στην εφαρμογή του FUSE από το Android.
Το επόμενο πρόβλημα είναι περισσότερο ανησυχητικό για τις επιχειρήσεις που χρησιμοποιούν κάτι σαν α κάρτα smartSD. Πριν από το FUSE, οι κατασκευαστές εφαρμογών μπορούσαν να παρακολουθούν το Σημαία O_DIRECT προκειμένου να επικοινωνήσει με έναν ενσωματωμένο μικροελεγκτή στην κάρτα. Με το FUSE, οι προγραμματιστές μπορούν να έχουν πρόσβαση μόνο στην προσωρινά αποθηκευμένη έκδοση ενός αρχείου και δεν μπορούν να δουν τις εντολές που αποστέλλονται από έναν μικροελεγκτή. Αυτό είναι προβληματικό για ορισμένες εφαρμογές επιχειρήσεων/κρατικών/τραπεζών που επικοινωνούν με κάρτες microSD προστιθέμενης αξίας.
Ασφάλεια απόρριψης για SDCardFS
Ορισμένοι OEMS αναγνώρισαν αυτά τα προβλήματα από νωρίς και άρχισαν να αναζητούν μια λύση στον πυρήνα για να αντικαταστήσουν το FUSE. Η Samsung, για παράδειγμα, αναπτύχθηκε SDCardFS που βασίζεται στο WrapFS. Αυτή η λύση εντός πυρήνα προσομοιώνει το FAT32 όπως ακριβώς και το FUSE, αλλά παραιτείται από την επιβάρυνση I/O, τη διπλή προσωρινή αποθήκευση και άλλα ζητήματα που ανέφερα παραπάνω. (Ναι, επιτρέψτε μου να επαναλάβω αυτό το σημείο, αυτή η λύση που εφαρμόζει τώρα η Google βασίζεται στο έργο της Samsung).
Η ίδια η Google αναγνώρισε επιτέλους τα μειονεκτήματα που σχετίζονται με το FUSE, γι' αυτό και άρχισαν να κινούνται προς το επίπεδο εξομοίωσης FAT32 του πυρήνα που αναπτύχθηκε από τη Samsung. Η εταιρεία, όπως αναφέρεται στην Android Developers Backstage podcast, εργάζεται για να κάνει το SDCardFS διαθέσιμο για όλες τις συσκευές σε μια επερχόμενη έκδοση του πυρήνα. Αυτήν τη στιγμή μπορείτε να δείτε την πρόοδό τους εργάζονται στην AOSP.
Σαν Ο προγραμματιστής της Google εξήγησε νωρίτερα, η μεγαλύτερη πρόκληση με την εφαρμογή μιας λύσης εντός πυρήνα είναι πώς να αντιστοιχίσετε το όνομα του πακέτου Το αναγνωριστικό εφαρμογής είναι απαραίτητο για ένα πακέτο να έχει πρόσβαση στα δικά του δεδομένα σε εξωτερικό χώρο αποθήκευσης χωρίς να απαιτείται καμία άδειες. Αλλά αυτή η δήλωση έγινε πριν από ένα χρόνο και φτάσαμε στο σημείο όπου η ομάδα αποκαλεί το SDCardFS «το επόμενο μεγάλο πράγμα». Έχουν ήδη επιβεβαιώσει ότι το τρομακτικό σφάλμα χρονικής σφραγίδας έχει επιδιορθωθεί, χάρη στην απομάκρυνση από το FUSE, έτσι μπορούμε να ανυπομονούμε να δούμε όλες τις αλλαγές που επιφέρονται με την εγκατάλειψη του FUSE.
Παρανοήσεις για τον έλεγχο γεγονότων
Εάν έχετε φτάσει τόσο μακριά στο άρθρο, τότε συγχαρητήρια που συμβαδίζετε με τα πάντα μέχρι τώρα! Ήθελα να διευκρινίσω μερικές ερωτήσεις που είχα όταν έγραφα αυτό το άρθρο:
- Το SDCardFS διαθέτει καμία σχέση με τις πραγματικές κάρτες SD. Απλώς ονομάζεται έτσι επειδή χειρίζεται την πρόσβαση I/O για /sdcard. Και όπως ίσως θυμάστε, το /sdcard είναι μια ξεπερασμένη ετικέτα που αναφέρεται στον "εξωτερικό" χώρο αποθήκευσης της συσκευής σας (όπου οι εφαρμογές αποθηκεύουν τα πολυμέσα τους).
- Το SDCardFS είναι όχι ένα παραδοσιακό σύστημα αρχείων όπως FAT32, EXT4 ή F2FS. Είναι ένα σύστημα αρχείων περιτυλίγματος με δυνατότητα στοίβαξης που μεταβιβάζει εντολές στα χαμηλότερα, εξομοιούμενα συστήματα αρχείων (σε αυτήν την περίπτωση, θα ήταν FAT32 στο /sdcard).
- Τίποτα δεν θα αλλάξει σε σχέση με το MTP. Θα συνεχίσετε να χρησιμοποιείτε το MTP για να μεταφέρετε αρχεία προς/από τον υπολογιστή σας (μέχρι η Google να καταλήξει σε ένα καλύτερο πρωτόκολλο). Αλλά τουλάχιστον το σφάλμα χρονικής σφραγίδας θα διορθωθεί!
- Όπως αναφέρθηκε προηγουμένως, όταν η Google αναφέρεται στην "Εξωτερική αποθήκευση" είτε μιλάνε για το (για όλες τις προθέσεις και σκοπούς) εσωτερικό /sdcard εικονικό διαμέρισμα FAT32 Ή μιλούν για ένα πραγματικό, φυσικό, αφαιρούμενο microSD κάρτα. Η ορολογία είναι μπερδεμένη, αλλά είναι αυτό που μας εντυπωσιάζει.
συμπέρασμα
Με την απομάκρυνση από το FUSE και την εφαρμογή ενός επιπέδου εξομοίωσης FAT32 εντός πυρήνα (SDCardFS), η Google θα μειώσει σημαντική επιβάρυνση I/O, εξαλείφοντας τη διπλή προσωρινή αποθήκευση και επιλύοντας ορισμένα σκοτεινά ζητήματα που σχετίζονται με την εξομοίωση του FUSE του FAT32.
Δεδομένου ότι αυτές οι αλλαγές θα γίνουν σε έναν πυρήνα, μπορούν να κυκλοφορήσουν χωρίς μια σημαντική νέα έκδοση του Android μαζί του. Ορισμένοι χρήστες αναμένουν να δουν αυτές τις αλλαγές να εφαρμόζονται επίσημα στο Android 8, αλλά είναι δυνατό για οποιαδήποτε μελλοντική OTA σε μια συσκευή Pixel για να φέρει την έκδοση 4.1 του πυρήνα Linux που έχει λειτουργήσει η Google επί.
Για κάποιους από εσάς, το SDCardFS δεν είναι μια νέα ιδέα. Στην πραγματικότητα, οι συσκευές της Samsung το χρησιμοποιούν εδώ και χρόνια (ήταν αυτές που το ανέπτυξαν τελικά). Από τότε που το SDCardFS εισήχθη στο AOSP πέρυσι, ορισμένοι προγραμματιστές προσαρμοσμένης ROM και πυρήνα επέλεξαν να το εφαρμόσουν στην εργασία τους. Το CyanogenMOD σε ένα σημείο σκέφτηκε να το εφαρμόσει, αλλά το επανέφερε όταν οι χρήστες αντιμετώπισαν προβλήματα με τις φωτογραφίες τους. Αλλά ελπίζουμε ότι με την Google να αναλαμβάνει τη βασιλεία αυτού του έργου, οι χρήστες Android σε όλες τις μελλοντικές συσκευές μπορούν να επωφεληθούν από τις βελτιώσεις που εισάγονται με την εγκατάλειψη του FUSE.