Κλήση συστήματος

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

Συνήθως οι γλώσσες προγραμματισμού παρέχουν προτυποποιημένες βιβλιοθήκες που αποκρύπτουν αυτήν τη διαδικασία από τον προγραμματιστή και παρέχουν φορητότητα  πηγαίου κώδικα από ΛΣ σε ΛΣ. Π.χ. η απλή συνάρτηση fopen() της πρότυπης βιβλιοθήκης της γλώσσας C, με κοινή σύνταξη για όλες τις αρχιτεκτονικές και λειτουργικά συστήματα αλλά με διαφορετική υλοποίηση για το καθένα, όταν κληθεί καλεί με τη σειρά της την αντίστοιχη κλήση συστήματος - κατά κανόνα πιο πολύπλοκη - που παρέχει το υποκείμενο ΛΣ. Ο κώδικας που υλοποιεί τις κλήσεις συστήματος είναι ουσιαστικά τμήμα του πυρήνα, οπότε η fopen() του συγκεκριμένου παραδείγματος ζητά μετάβαση του επεξεργαστή σε «κατάσταση πυρήνα», κατά την οποία μπορούν να εκτελεστούν εντολές με άμεση επίδραση στο υλικό και στους πόρους του υπολογιστή, και μεταφέρει τον έλεγχο στον κώδικα της κλήσης συστήματος. Όταν ο τελευταίος τερματίσει ο επεξεργαστής μεταβαίνει πάλι σε «κατάσταση χρήστη» και η fopen() συνεχίζει την εκτέλεσή της από την εντολή που ακολουθεί την κλήση συστήματος. Φυσικά τα προγράμματα χρήστη μπορούν να παρακάμψουν την fopen() και να καλέσουν κατευθείαν τον πυρήνα, κάτι που γίνεται αναγκαστικά όταν η βιβλιοθήκη της γλώσσας προγραμματισμού δεν παρέχει υψηλού επιπέδου διασύνδεση (όπως την fopen()) για κάποια λειτουργία. Ακόμα και σε αυτή την περίπτωση όμως οι κλήσεις συστήματος είναι προσπελάσιμες από τα προγράμματα χρήστη μόνο μέσω της μεσολάβησης των βιβλιοθηκών συστήματος (π.χ. της glibc), αφού για παράδειγμα η κλήση συστήματος OPEN των ΛΣ τύπου Unix καθίσταται προσβάσιμη μέσω της συνάρτησης συστήματος open(), η οποία είναι αυτή που καλείται εσωτερικά από την υψηλότερου επιπέδου fopen() στις υλοποιήσεις της πρότυπης βιβλιοθήκης της C για Unix.

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

Unix

Στα συστήματα Unix οι κλήσεις συστήματος, οι οποίες χαρακτηρίζονται από ένα αναγνωριστικό όνομα και έναν αριθμό παραμέτρων, εκτελούνται μέσα από κατάλληλες συναρτήσεις της γλώσσας προγραμματισμού C, ομαδοποιημένες σε βιβλιοθήκες του συστήματος. Οι βιβλιοθήκες αυτές συνήθως διατηρούν εσωτερική «κατάσταση» (καθολικές μεταβλητές και δομές δεδομένων), οπότε συνδέονται στατικά κατά τη μεταγλώττιση ενός προγράμματος με αυτό· έτσι κάθε εφαρμογή έχει ενσωματωμένο το δικό της στιγμιότυπο των βιβλιοθηκών συστήματος που χρησιμοποιεί.

Κάθε κλήση συστήματος επιστρέφει έναν ακέραιο αριθμό στη συνάρτηση που την κάλεσε· αρνητική τιμή επιστροφής σημαίνει αποτυχία ενώ θετική σημαίνει επιτυχία. Σε περίπτωση αποτυχίας ο κωδικός λάθους αποθηκεύεται στην errno, μία εσωτερική καθολική μεταβλητή που διατηρεί αυτομάτως το λειτουργικό σύστημα για κάθε διεργασία ξεχωριστά. Η τιμή της errno διατηρείται μέχρι την επόμενη κλήση συστήματος, ασχέτως αν αυτή θα είναι επιτυχής ή αποτυχημένη. Το μήνυμα που αντιστοιχεί στον τρέχοντα κωδικό λάθους της errno επιστρέφεται από τη συνάρτηση strerror() που παρέχει η γλώσσα C σε περιβάλλοντα Unix, ενώ εκτύπωση αυτού του μηνύματος γίνεται με την αντίστοιχη συνάρτηση perror().

Η προγραμματιστική διασύνδεση των κλήσεων συστήματος των διαφόρων εκδοχών του Unix οριστικοποιήθηκε με τη σειρά προτύπων POSIX (IEEE 1003), τα οποία επίσης καθόριζαν και άλλες λεπτομέρειες του ΛΣ όπως το κέλυφος γραμμής εντολών. Έτσι ο πηγαίος κώδικας ενός προγράμματος μπορεί να μεταγλωττιστεί επιτυχώς σε οποιοδήποτε λειτουργικό σύστημα ακολουθεί το πρότυπο POSIX χωρίς να χρειαστεί αλλαγές, ενώ η συμμόρφωση με το POSIX αποτελεί προϋπόθεση για να μπορεί ένα λειτουργικό σύστημα να αποκαλείται Unix.

Windows

Πηγές 
Αρχιτεκτονική Υπολογιστών: Μια Δομημένη Προσέγγιση, Tanenbaum Andrew S., Εκδ. Κλειδάριθμος
Σύγχρονα Λειτουργικά Συστήματα, Tanenbaum Andrew S., Εκδ. Κλειδάριθμος

Τεχνολογία λειτουργικών συστημάτων