Λειτουργικά Συστήματα: Three Easy Pieces. Μέρος 1: Εισαγωγή (μετάφραση)

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

Γεια σου Χαμπρ! Θα ήθελα να παρουσιάσω στην προσοχή σας μια σειρά άρθρων-μεταφράσεων μιας ενδιαφέρουσας κατά τη γνώμη μου λογοτεχνίας - OSTEP. Αυτό το υλικό εξετάζει αρκετά βαθιά τη δουλειά λειτουργικών συστημάτων που μοιάζουν με unix, δηλαδή την εργασία με διεργασίες, διάφορους προγραμματιστές, τη μνήμη και άλλα παρόμοια στοιχεία που συνθέτουν ένα σύγχρονο λειτουργικό σύστημα. Μπορείτε να δείτε το πρωτότυπο όλων των υλικών εδώ εδώ. Σημειώστε ότι η μετάφραση έγινε αντιεπαγγελματικά (αρκετά ελεύθερα), αλλά ελπίζω να διατήρησα το γενικό νόημα.

Εργαστήριο για αυτό το θέμα μπορείτε να βρείτε εδώ:
- πρωτότυπο: pages.cs.wisc.edu/~remzi/OSTEP/Homework/homework.html
- πρωτότυπο: github.com/remzi-arpacidusseau/ostep-code
- Η προσωπική μου προσαρμογή: github.com/bykvaadm/OS/tree/master/ostep

Μπορείτε επίσης να δείτε το κανάλι μου στο τηλεγράφημα =)

Λειτουργία προγράμματος

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

Υπολογιστικό μοντέλο Von Neumann

Η απλοποιημένη μορφή εργασίας που περιγράφεται από εμάς είναι παρόμοια με το μοντέλο υπολογισμού Von Neumann. Ο Von Neumann είναι ένας από τους πρωτοπόρους των συστημάτων υπολογιστών, είναι επίσης ένας από τους συγγραφείς της θεωρίας παιγνίων. Ενώ το πρόγραμμα εκτελείται, λαμβάνουν χώρα πολλά άλλα συμβάντα, πολλές άλλες διαδικασίες και λειτουργούν λογική τρίτων, ο κύριος σκοπός των οποίων είναι να απλοποιήσει την εκκίνηση, τη λειτουργία και τη συντήρηση του συστήματος.
Υπάρχει ένα σύνολο λογισμικού που είναι υπεύθυνο για την εύκολη εκτέλεση προγραμμάτων (ή ακόμα και για την ταυτόχρονη εκτέλεση πολλών προγραμμάτων), που επιτρέπει στα προγράμματα να μοιράζονται την ίδια μνήμη και να επικοινωνούν με διαφορετικές συσκευές. Ένα τέτοιο σύνολο λογισμικού (λογισμικό) ονομάζεται ουσιαστικά λειτουργικό σύστημα και τα καθήκοντά του περιλαμβάνουν την παρακολούθηση της σωστής και αποτελεσματικής λειτουργίας του συστήματος, καθώς και τη διασφάλιση της ευκολίας διαχείρισης αυτού του συστήματος.

Λειτουργικό σύστημα

Ένα λειτουργικό σύστημα, που συντομεύεται ως λειτουργικό σύστημα, είναι ένα σύνολο αλληλένδετων προγραμμάτων που έχουν σχεδιαστεί για τη διαχείριση των πόρων του υπολογιστή και την οργάνωση της αλληλεπίδρασης του χρήστη με έναν υπολογιστή..
Το ΛΣ επιτυγχάνει την αποτελεσματικότητά του καταρχήν, μέσω της πιο σημαντικής τεχνικής - της τεχνικής εικονικοποίηση. Το λειτουργικό σύστημα αλληλεπιδρά με έναν φυσικό πόρο (επεξεργαστή, μνήμη, δίσκος κ.λπ.) και τον μετατρέπει σε μια πιο γενική, πιο ισχυρή και πιο εύχρηστη μορφή από μόνη της. Επομένως, για μια γενική κατανόηση, μπορείτε να συγκρίνετε πολύ χονδρικά το λειτουργικό σύστημα με μια εικονική μηχανή.
Προκειμένου να επιτραπεί στους χρήστες να δίνουν εντολές στο λειτουργικό σύστημα και να χρησιμοποιούν έτσι τις δυνατότητες της εικονικής μηχανής (όπως η εκτέλεση ενός προγράμματος, η εκχώρηση μνήμης, η πρόσβαση σε ένα αρχείο κ.λπ.), το λειτουργικό σύστημα παρέχει κάποια διεπαφή που ονομάζεται API (διεπαφή προγραμματισμού εφαρμογών) και στην οποία μπορείτε να πραγματοποιήσετε κλήσεις (κλήση). Ένα τυπικό λειτουργικό σύστημα επιτρέπει την πραγματοποίηση εκατοντάδων κλήσεων συστήματος.
Τέλος, δεδομένου ότι η εικονικοποίηση επιτρέπει σε πολλά προγράμματα να εκτελούνται (άρα να μοιράζονται την CPU), και ταυτόχρονα να έχουν πρόσβαση στις οδηγίες και τα δεδομένα τους (άρα να μοιράζονται τη μνήμη) και να έχουν πρόσβαση σε δίσκους (άρα να μοιράζονται συσκευές I/O). ), το λειτουργικό σύστημα ονομάζεται επίσης διαχειριστής πόρων. Κάθε επεξεργαστής, δίσκος και μνήμη είναι ένας πόρος του συστήματος, και έτσι ένας από τους ρόλους του λειτουργικού συστήματος γίνεται η διαχείριση αυτών των πόρων, κάνοντας το αποτελεσματικά, ειλικρινά ή το αντίστροφο, ανάλογα με την εργασία για την οποία αυτό το λειτουργικό σύστημα είναι σχεδιασμένο.

Εικονικοποίηση CPU

Σκεφτείτε το ακόλουθο πρόγραμμα:
(https://www.youtube.com/watch?v=zDwT5fUcki4&feature=youtu.be)

Λειτουργικά Συστήματα: Three Easy Pieces. Μέρος 1: Εισαγωγή (μετάφραση)

Δεν εκτελεί καμία ειδική ενέργεια, στην πραγματικότητα, το μόνο που κάνει είναι να καλεί μια συνάρτηση περιστροφή(), του οποίου η αποστολή είναι να κάνει κύκλο στον έλεγχο χρόνου και να επιστρέψει αφού περάσει ένα δευτερόλεπτο. Έτσι, επαναλαμβάνει επ' αόριστον τη συμβολοσειρά που πέρασε ο χρήστης ως όρισμα.
Ας τρέξουμε αυτό το πρόγραμμα και ας του δώσουμε τον χαρακτήρα "A" ως όρισμα. Το αποτέλεσμα δεν είναι ιδιαίτερα ενδιαφέρον - το σύστημα απλώς εκτελεί ένα πρόγραμμα που εμφανίζει περιοδικά τον χαρακτήρα "A".
Τώρα ας δοκιμάσουμε την επιλογή όταν εκτελούνται πολλές παρουσίες του ίδιου προγράμματος, αλλά εξάγουν διαφορετικά γράμματα για να γίνει πιο σαφές. Σε αυτή την περίπτωση, το αποτέλεσμα θα είναι κάπως διαφορετικό. Παρά το γεγονός ότι έχουμε έναν επεξεργαστή, το πρόγραμμα εκτελείται ταυτόχρονα. Πώς συμβαίνει; Αλλά αποδεικνύεται ότι το λειτουργικό σύστημα, όχι χωρίς τη βοήθεια δυνατοτήτων υλικού, δημιουργεί μια ψευδαίσθηση. Η ψευδαίσθηση ότι το σύστημα έχει πολλαπλούς εικονικούς επεξεργαστές, μετατρέποντας έναν ενιαίο φυσικό επεξεργαστή σε έναν θεωρητικά άπειρο αριθμό και έτσι επιτρέπει σε φαινομενικά προγράμματα να τρέχουν ταυτόχρονα. Αυτή η ψευδαίσθηση ονομάζεται Εικονικοποίηση CPU.
Αυτή η εικόνα εγείρει πολλά ερωτήματα, για παράδειγμα, εάν πολλά προγράμματα θέλουν να εκτελούνται ταυτόχρονα, ποιο θα ξεκινήσει; Οι «πολιτικές» του ΛΣ είναι υπεύθυνες για αυτό το ερώτημα. Οι πολιτικές χρησιμοποιούνται σε πολλά σημεία του λειτουργικού συστήματος και απαντούν σε ερωτήσεις όπως αυτή και είναι οι βασικοί μηχανισμοί που εφαρμόζει το ΛΣ. Εξ ου και ο ρόλος του ΛΣ ως διαχειριστή πόρων.

Εικονικοποίηση μνήμης

Ας δούμε τώρα τη μνήμη. Το φυσικό μοντέλο της μνήμης στα σύγχρονα συστήματα αναπαρίσταται ως μια σειρά από byte.. Για να διαβάσετε από τη μνήμη, πρέπει να καθορίσετε διεύθυνση κελιούγια πρόσβαση σε αυτό. Για να γράψετε ή να ενημερώσετε δεδομένα, πρέπει επίσης να καθορίσετε τα δεδομένα και τη διεύθυνση του κελιού όπου θα τα γράψετε.
Η πρόσβαση στη μνήμη γίνεται συνεχώς κατά την εκτέλεση του προγράμματος. Ένα πρόγραμμα αποθηκεύει ολόκληρη τη δομή δεδομένων του στη μνήμη και έχει πρόσβαση σε αυτό εκτελώντας διάφορες εντολές. Οι οδηγίες, εν τω μεταξύ, αποθηκεύονται επίσης στη μνήμη, επομένως είναι επίσης προσβάσιμη για κάθε αίτημα για την επόμενη εντολή.

κλήση malloc().

Εξετάστε το ακόλουθο πρόγραμμα, το οποίο εκχωρεί μια περιοχή μνήμης χρησιμοποιώντας την κλήση malloc () (https://youtu.be/jnlKRnoT1m0):

Λειτουργικά Συστήματα: Three Easy Pieces. Μέρος 1: Εισαγωγή (μετάφραση)

Το πρόγραμμα κάνει πολλά πράγματα. Αρχικά, εκχωρεί λίγη μνήμη (γραμμή 7), μετά εκτυπώνει τη διεύθυνση του εκχωρημένου κελιού (γραμμή 9), γράφει μηδέν στην πρώτη υποδοχή της εκχωρημένης μνήμης. Στη συνέχεια, το πρόγραμμα εισάγει έναν βρόχο στον οποίο αυξάνει την τιμή που είναι αποθηκευμένη στη μνήμη στη διεύθυνση στη μεταβλητή "p". Εκτυπώνει επίσης το ίδιο το αναγνωριστικό διεργασίας. Το αναγνωριστικό διεργασίας είναι μοναδικό για κάθε διεργασία που εκτελείται. Έχοντας κυκλοφορήσει πολλά αντίγραφα, θα πέσει σε ένα ενδιαφέρον αποτέλεσμα: Στην πρώτη περίπτωση, αν δεν κάνετε τίποτα και απλώς εκτελέσετε πολλά αντίγραφα, τότε οι διευθύνσεις θα είναι διαφορετικές. Αλλά αυτό δεν εμπίπτει στη θεωρία μας! Σωστό, καθώς οι σύγχρονες διανομές έχουν ενεργοποιημένη την τυχαιοποίηση μνήμης από προεπιλογή. Εάν είναι απενεργοποιημένο, παίρνουμε το αναμενόμενο αποτέλεσμα - οι διευθύνσεις μνήμης δύο προγραμμάτων που εκτελούνται ταυτόχρονα θα ταιριάζουν.

Λειτουργικά Συστήματα: Three Easy Pieces. Μέρος 1: Εισαγωγή (μετάφραση)

Ως αποτέλεσμα, αποδεικνύεται ότι δύο ανεξάρτητα προγράμματα λειτουργούν με τους δικούς τους ιδιωτικούς χώρους διευθύνσεων, οι οποίοι με τη σειρά τους χαρτογραφούνται από το λειτουργικό σύστημα στη φυσική μνήμη. Επομένως, η χρήση διευθύνσεων μνήμης μέσα σε ένα πρόγραμμα δεν θα επηρεάσει τα άλλα με κανέναν τρόπο και φαίνεται σε κάθε πρόγραμμα ότι έχει το δικό του κομμάτι φυσικής μνήμης, που του έχει δοθεί εξ ολοκλήρου. Η πραγματικότητα, ωστόσο, είναι ότι η φυσική μνήμη είναι ένας κοινόχρηστος πόρος που διαχειρίζεται το λειτουργικό σύστημα.

Συνοχή

Ένα άλλο από τα σημαντικά θέματα στα λειτουργικά συστήματα είναι − συνοχή. Αυτός ο όρος χρησιμοποιείται όταν μιλάμε για προβλήματα στο σύστημα που μπορεί να προκύψουν όταν εργάζεστε με πολλά πράγματα ταυτόχρονα μέσα στο ίδιο πρόγραμμα. Προκύπτουν ζητήματα συνέπειας ακόμη και μέσα στο ίδιο το λειτουργικό σύστημα. Στα προηγούμενα παραδείγματα εικονικοποίησης μνήμης και επεξεργαστή, συνειδητοποιήσαμε ότι το λειτουργικό σύστημα διαχειρίζεται πολλά πράγματα ταυτόχρονα - ξεκινά την πρώτη διαδικασία, μετά τη δεύτερη και ούτω καθεξής. Όπως αποδείχθηκε, αυτή η συμπεριφορά μπορεί να οδηγήσει σε κάποια προβλήματα. Έτσι, για παράδειγμα, τα σύγχρονα προγράμματα πολλαπλών νημάτων αντιμετωπίζουν τέτοιες δυσκολίες.

Σκεφτείτε το ακόλουθο πρόγραμμα:

Λειτουργικά Συστήματα: Three Easy Pieces. Μέρος 1: Εισαγωγή (μετάφραση)

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

Ας τρέξουμε αυτό το πρόγραμμα με όρισμα 1000. Όπως ίσως μαντέψατε, το αποτέλεσμα θα πρέπει να είναι 2000 επειδή κάθε νήμα αύξησε τη μεταβλητή 1000 φορές. Ωστόσο, όλα δεν είναι τόσο απλά. Ας προσπαθήσουμε να εκτελέσουμε το πρόγραμμα με μια τάξη μεγέθους περισσότερες επαναλήψεις.

Λειτουργικά Συστήματα: Three Easy Pieces. Μέρος 1: Εισαγωγή (μετάφραση)

Εισάγοντας έναν αριθμό, για παράδειγμα, 100000, περιμένουμε να δούμε την έξοδο ως τον αριθμό 200000. Ωστόσο, εάν εκτελέσουμε τον αριθμό 100000 πολλές φορές, όχι μόνο δεν θα δούμε τη σωστή απάντηση, αλλά θα λάβουμε και διαφορετικές λανθασμένες απαντήσεις. Η απάντηση βρίσκεται στο γεγονός ότι για να αυξηθεί ο αριθμός, απαιτούνται τρεις λειτουργίες - εξαγωγή του αριθμού από τη μνήμη, αύξηση και μετά εγγραφή του αριθμού πίσω. Δεδομένου ότι όλες αυτές οι εντολές δεν εκτελούνται ατομικά (όλα την ίδια στιγμή), μπορεί να συμβούν περίεργα πράγματα όπως αυτό. Αυτό το πρόβλημα ονομάζεται στον προγραμματισμό κατάσταση του αγώνα. Όταν άγνωστες δυνάμεις σε μια άγνωστη στιγμή μπορούν να επηρεάσουν την απόδοση οποιασδήποτε από τις λειτουργίες σας.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο