Λειτουργικά Συστήματα: Three Easy Pieces. Μέρος 3: Διαδικασία API (μετάφραση)

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

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

Εργαστήριο για αυτό το θέμα μπορείτε να βρείτε εδώ:

Άλλα μέρη:

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

Τρομάζω! Υπάρχει ένα εργαστήριο για αυτή τη διάλεξη! Κοίτα github

API διαδικασίας

Ας δούμε ένα παράδειγμα δημιουργίας διεργασίας σε σύστημα UNIX. Συμβαίνει μέσω δύο κλήσεων συστήματος πιρούνι() и exec().

Call fork()

Λειτουργικά Συστήματα: Three Easy Pieces. Μέρος 3: Διαδικασία API (μετάφραση)

Σκεφτείτε ένα πρόγραμμα που κάνει μια κλήση fork(). Το αποτέλεσμα της εκτέλεσής του θα είναι το εξής.

Λειτουργικά Συστήματα: Three Easy Pieces. Μέρος 3: Διαδικασία API (μετάφραση)

Πρώτα από όλα, εισάγουμε τη συνάρτηση main() και εκτυπώνουμε τη συμβολοσειρά στην οθόνη. Η γραμμή περιέχει το αναγνωριστικό διεργασίας που στο πρωτότυπο καλείται PID ή αναγνωριστικό διαδικασίας. Αυτό το αναγνωριστικό χρησιμοποιείται στο UNIX για να αναφέρεται σε μια διεργασία. Η επόμενη εντολή θα καλέσει το fork(). Σε αυτό το σημείο δημιουργείται ένα σχεδόν ακριβές αντίγραφο της διαδικασίας. Για το λειτουργικό σύστημα, φαίνεται ότι υπάρχουν 2 αντίγραφα του ίδιου προγράμματος που εκτελούνται στο σύστημα, το οποίο με τη σειρά του θα βγει από τη συνάρτηση fork(). Η νέα θυγατρική διεργασία (σε σχέση με τη γονική διαδικασία που τη δημιούργησε) δεν θα εκτελείται πλέον, ξεκινώντας από τη συνάρτηση main(). Θα πρέπει να θυμόμαστε ότι μια θυγατρική διεργασία δεν είναι ακριβές αντίγραφο της γονικής διαδικασίας· συγκεκριμένα, έχει το δικό της χώρο διευθύνσεων, τους δικούς της καταχωρητές, το δικό της δείκτη σε εκτελέσιμες εντολές και παρόμοια. Έτσι, η τιμή που επιστρέφεται στον καλούντα της συνάρτησης fork() θα είναι διαφορετική. Συγκεκριμένα, η γονική διαδικασία θα λάβει την τιμή PID της θυγατρικής διεργασίας ως επιστροφή και το παιδί θα λάβει μια τιμή ίση με 0. Χρησιμοποιώντας αυτούς τους κωδικούς επιστροφής, μπορείτε στη συνέχεια να διαχωρίσετε τις διεργασίες και να αναγκάσετε καθεμία από αυτές να κάνει τη δική της δουλειά . Ωστόσο, η εκτέλεση αυτού του προγράμματος δεν είναι αυστηρά καθορισμένη. Αφού χωριστεί σε 2 διαδικασίες, το ΛΣ αρχίζει να τις παρακολουθεί, καθώς και να σχεδιάζει τη δουλειά τους. Εάν εκτελεστεί σε επεξεργαστή μονού πυρήνα, μία από τις διεργασίες, σε αυτήν την περίπτωση ο γονέας, θα συνεχίσει να λειτουργεί και στη συνέχεια η θυγατρική διαδικασία θα λάβει τον έλεγχο. Κατά την επανεκκίνηση, η κατάσταση μπορεί να είναι διαφορετική.

Αναμονή κλήσης ()

Λειτουργικά Συστήματα: Three Easy Pieces. Μέρος 3: Διαδικασία API (μετάφραση)

Σκεφτείτε το παρακάτω πρόγραμμα. Σε αυτό το πρόγραμμα, λόγω της παρουσίας κλήσης Περίμενε() Η γονική διαδικασία θα περιμένει πάντα να ολοκληρωθεί η θυγατρική διαδικασία. Σε αυτήν την περίπτωση, θα λάβουμε μια αυστηρά καθορισμένη έξοδο κειμένου στην οθόνη

Λειτουργικά Συστήματα: Three Easy Pieces. Μέρος 3: Διαδικασία API (μετάφραση)

κλήση exec().

Λειτουργικά Συστήματα: Three Easy Pieces. Μέρος 3: Διαδικασία API (μετάφραση)

Σκεφτείτε την πρόκληση exec(). Αυτή η κλήση συστήματος είναι χρήσιμη όταν θέλουμε να εκτελέσουμε ένα εντελώς διαφορετικό πρόγραμμα. Εδώ θα καλέσουμε execvp() για να τρέξετε το πρόγραμμα wc που είναι πρόγραμμα μέτρησης λέξεων. Τι συμβαίνει όταν καλείται η exec(); Αυτή η κλήση μεταβιβάζεται το όνομα του εκτελέσιμου αρχείου και ορισμένες παραμέτρους ως ορίσματα. Στη συνέχεια, ο κώδικας και τα στατικά δεδομένα από αυτό το εκτελέσιμο αρχείο φορτώνονται και το δικό του τμήμα με τον κώδικα αντικαθίσταται. Οι υπόλοιπες περιοχές μνήμης, όπως η στοίβα και ο σωρός, αρχικοποιούνται ξανά. Μετά από αυτό το λειτουργικό σύστημα απλώς εκτελεί το πρόγραμμα, περνώντας του ένα σύνολο ορισμάτων. Επομένως, δεν δημιουργήσαμε μια νέα διαδικασία, απλώς μετατρέψαμε το τρέχον πρόγραμμα σε άλλο πρόγραμμα που εκτελείται. Μετά την εκτέλεση της κλήσης exec() στον απόγονο, φαίνεται ότι το αρχικό πρόγραμμα δεν εκτελούσε καθόλου.

Αυτή η περιπλοκή εκκίνησης είναι απολύτως φυσιολογική για ένα κέλυφος Unix και επιτρέπει σε αυτό το κέλυφος να εκτελεί κώδικα μετά την κλήση πιρούνι(), αλλά πριν την κλήση exec(). Ένα παράδειγμα τέτοιου κώδικα θα ήταν η προσαρμογή του περιβάλλοντος φλοιού στις ανάγκες του προγράμματος που εκκινείται, πριν από την εκκίνηση του.

κέλυφος - απλώς ένα πρόγραμμα χρήστη. Σου δείχνει τη γραμμή πρόσκλησης και περιμένει να γράψεις κάτι σε αυτήν. Στις περισσότερες περιπτώσεις, εάν γράψετε το όνομα ενός προγράμματος εκεί, το κέλυφος θα βρει τη θέση του, θα καλέσει τη μέθοδο fork() και στη συνέχεια θα καλέσει κάποιον τύπο exec() για να δημιουργήσει μια νέα διαδικασία και θα περιμένει να ολοκληρωθεί χρησιμοποιώντας ένα κλήση περιμένετε(). Όταν η θυγατρική διεργασία τερματιστεί, το κέλυφος θα επιστρέψει από την κλήση wait() και θα εκτυπώσει ξανά την προτροπή και θα περιμένει να εισαχθεί η επόμενη εντολή.

Ο διαχωρισμός fork() & exec() επιτρέπει στο κέλυφος να κάνει τα ακόλουθα πράγματα, για παράδειγμα:
αρχείο wc > new_file.

Σε αυτό το παράδειγμα, η έξοδος του προγράμματος wc ανακατευθύνεται σε ένα αρχείο. Ο τρόπος με τον οποίο το κέλυφος το επιτυγχάνει αυτό είναι αρκετά απλός - δημιουργώντας μια διαδικασία θυγατρικής πριν την κλήση exec(), το κέλυφος κλείνει την τυπική έξοδο και ανοίγει το αρχείο νέο αρχείο, επομένως, όλη η έξοδος από το περαιτέρω πρόγραμμα που εκτελείται wc θα ανακατευθυνθεί σε αρχείο αντί για οθόνη.

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

Πηγή: www.habr.com

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