Βιβλιοθήκη (υπολογιστές): Διαφορά μεταξύ των αναθεωρήσεων

Περιεχόμενο που διαγράφηκε Περιεχόμενο που προστέθηκε
JohnMad (συζήτηση | συνεισφορές)
JohnMad (συζήτηση | συνεισφορές)
μΧωρίς σύνοψη επεξεργασίας
Γραμμή 1:
Στην [[επιστήμη υπολογιστών]] καλούμε '''βιβλιοθήκη''' (library) μια συλλογή από έτοιμα [[Διαδικασία (υπολογιστές)|υποπρογράμματα]] που χρησιμοποιείται για την ανάπτυξη [[λογισμικό|λογισμικού]]. Οι βιβλιοθήκες περιέχουν υποβοηθητικό κώδικα και δεδομένα, παρέχοντας, με αυτόν τον τρόπο, υπηρεσίες σε προγράμματα. Αυτό επιτρέπει τον διαμοιρασμό και τη χρήση του κώδικα και των δεδομένων με [[άρθρωμα (υπολογιστές)|αρθρωτό]] τρόπο. Η έννοια της βιβλιοθήκης είναι αναπόσπαστο τμήμα του [[δομημένος προγραμματισμός|δομημένου προγραμματισμού]] και αναπτύχθηκε παράλληλα με αυτόν.
 
Κάποια [[εκτελέσιμο (υπολογιστές)|εκτελέσιμα]] αρχεία (executables) είναι προγράμματα και βιβλιοθήκες ταυτόχρονα, αλλά οι περισσότερες βιβλιοθήκες δεν είναι εκτελέσιμες. Τα εκτελέσιμα αρχεία και οι βιβλιοθήκες αναφέρονται το ένα στον κώδικα και τα δεδομένα του άλλου μέσω μιας διαδικασίας που ονομάζεται ''σύνδεση'' και την πραγματοποιεί ο '''συνδέτης'''. Τα σύγχρονα [[λειτουργικό σύστημα|λειτουργικά συστήματα]] παρέχουν βιβλιοθήκες που υλοποιούν την πλειονότητα των υπηρεσιών του συστήματος. Έτσι, ο περισσότερος κώδικας που χρησιμοποιούν οι σύγχρονες εφαρμογές παρέχεται από αυτές τις βιβλιοθήκες και δεν χρειάζεται να γραφεί από την αρχή για κάθε νέο πρόγραμμα.
Γραμμή 6:
Ένα αρχείο πηγαίου κώδικα υψηλού επιπέδου γραμμένο σε κάποια γλώσσα προγραμματισμού, μεταγλωττίζεται σε ένα αντίστοιχο αρχείο [[assembly|συμβολικού κώδικα]] (assembly) από τον κατάλληλο [[μεταγλωττιστής|μεταγλωττιστή]] (compiler). Το προκύπτον αρχείο στη συνέχεια μετασχηματίζεται σε [[αντικειμενικό αρχείο]] [[γλώσσα μηχανής|γλώσσας μηχανής]] από έναν [[assembler|συμβολομεταφραστή]] (assembler), μία διαδικασία που μετατρέπει τον κώδικα σε αρχείο άμεσα εκτελέσιμο από τον [[μικροεπεξεργαστής|επεξεργαστή]]. Η συμβολική γλώσσα και η γλώσσα μηχανής είναι ίδιου επιπέδου και υπάρχει αμφιμονοσήμαντη αντιστοιχία μεταξύ τους, απλώς η συμβολική αποτελείται από χαρακτήρες του λατινικού αλφαβήτου και δεκαεξαδικά ψηφία, ώστε να είναι κάπως κατανοητή από τον άνθρωπο, ενώ η γλώσσα μηχανής συντίθεται αποκλειστικά από [[bit]].
 
Έτσι, τελικά, σε κάθε αρχείο πηγαίου κώδικα, είτε αυτό είναι αυτόνομο (με «σημείο εισόδου εκτέλεσης», π.χ. στη γλώσσα [[C (γλώσσα προγραμματισμού)|C]] η συνάρτηση <code>main()</code> από την οποία εκκινεί η εκτέλεση κάθεενός προγράμματος) είτε όχι (π.χ. αρχείο βιβλιοθήκης), αντιστοιχίζεται ένα αντικειμενικό αρχείο με κώδικα μηχανής (αρχεία με επέκταση «.o» στο [[Unix]] και «.obj» στα [[Windows]]). Ένα αντικειμενικό αρχείο περιέχει εκτελέσιμο κώδικα, δηλώσεις δεδομένων, ένα πίνακα συμβόλων, όπου ορίζονται τα αναγνωριστικά (ονόματα μεταβλητών, σταθερών ή διαδικασιών) που εξάγονται από το αρχείο -δηλώνονται δηλαδή σε αυτό- ή εισάγονται στο αρχείο -χρησιμοποιούνται δηλαδή χωρίς να δηλώνονται-, και λοιπές πληροφορίες για τον «συνδέτη» (linker). Ο τελευταίος συνήθως καλείται αυτομάτως αμέσως μετά τον συμβολομεταφραστή, δέχεται ως είσοδο ένα ή περισσότερα αντικειμενικά αρχεία, τα συνενώνει κατάλληλα και παράγει ένα μοναδικό, τελικό εκτελέσιμο αρχείο. Αυτή η συνένωση που επιτελεί όμως ο συνδέτης, δεν αφορά μόνο πολλαπλά αντικειμενικά αρχεία (που προκύπτουν προφανώς από αντίστοιχα πολλαπλά πηγαία αρχεία) της ίδιας εφαρμογής, αλλά επεκτείνεται και στο να «επιλύει αναφορές εισαγόμενων συμβόλων»: σαρώνει δηλαδή τον πίνακα συμβόλων κάθε αντικειμενικού αρχείου εισόδου, ανακαλύπτει ποια αναγνωριστικά παρέχονται από κάποια βιβλιοθήκη, αναζητά τον αντικειμενικό κώδικα της βιβλιοθήκης και εισάγει στο τελικό εκτελέσιμο της εφαρμογής τα κατάλληλα τμήματά του.
 
Προκειμένου να επιτύχει τους στόχους του ο συνδέτης, ανάμεσα στ' άλλα, προβαίνει σε ένα πρώτο βήμα ''επανατοποθέτησης''. Αυτό σημαίνει ότι κάθε τμήμα κώδικα μηχανής που εισάγει και τακτοποιεί στο τελικό εκτελέσιμο αρχείο, είτε είναι από αντικειμενικό αρχείο που έδωσε ως είσοδο στον συνδέτη ο χρήστης είτε από αντικειμενικό αρχείο βιβλιοθήκης, το τροποποιεί κατάλληλα ώστε τελικά όλες οι [[διεύθυνση μνήμης|διευθύνσεις μνήμης]] εντολών και δεδομένων στο τελικό εκτελέσιμο να είναι συνεπείς μεταξύ τους, να μην επικαλύπτονται και να είναι σχετικές ως προς μία κοινή διεύθυνση βάσης. Αυτό το βήμα είναι απαραίτητο γιατί ο μεταγλωττιστής νωρίτερα είχε δράσει θεωρώντας ξεχωριστό [[χώρος διευθύνσεων|χώρο διευθύνσεων]] για κάθε αντικειμενικό αρχείο με διαφορετικές διευθύνσεις βάσης. Συνήθως, για διευκόλυνση του προγραμματιστή, ο μεταγλωττιστής, ο συμβολομεταφραστής και ο συνδέτης καλούνται με μία μόνο εντολή και με τη σωστή σειρά· αν ωστόσο ο προγραμματιστής το επιθυμεί, μπορεί περνώντας κάποια κατάλληλη παράμετρο να τροποποιήσει αυτήν τη συμπεριφορά (π.χ. στον μεταγλωττιστή της C [[gcc]] με την παράμετρο «-c» παραλείπεται η σύνδεση). Τα αντικειμενικά αρχεία υπακούν σε διάφορεςδιάφορα προτυποποιημένεςπροτυποποιημένα μορφέςμορφότυπα (format), οιτα οποίεςοποία καθορίζουν τη δομή τους και, συνήθως, είναι ίδιεςίδια και για τα τελικά εκτελέσιμα αρχεία. Επιπλέον, οιτα μορφέςμορφότυπα αυτέςαυτά είναι ίδιεςίδια τόσο για τα αυτόνομα εκτελέσιμα αρχεία όσο και για τις βιβλιοθήκες. ΣυνήθηςΣύνηθες μορφήμορφότυπο εκτελέσιμου αρχείου στα Windows είναι το ''PE'', ενώ στο Unix το ''ELF''.
 
Όταν επίκειται το «τρέξιμο» (εκτέλεση) ενός εκτελέσιμου αρχείου, εκτελείται πρώτα ένα κατάλληλο πρόγραμμα του λειτουργικού συστήματος (ΛΣ): ο '''φορτωτής''' (loader). Ο τελευταίος αντιγράφει τα περιεχόμενα του εκτελέσιμου από τον δίσκο στη μνήμη, δίνει κατάλληλες τιμές σε εσωτερικές δομές του πυρήνα (αφού ουσιαστικά εκκινείται μία νέα [[διεργασία (υπολογιστές)|διεργασία]]) και ειδοποιεί σχετικά το υποσύστημα εικονικής μνήμης, ενώ, αν το τελευταίο δεν είναι διαθέσιμο, κάτι σπάνιο σήμερα αφού όλα τα μοντέρνα ΛΣ χρησιμοποιούν [[εικονική μνήμη]], τροποποιεί επιπλέον τον κώδικα του προγράμματος με ένα δεύτερο βήμα επανατοποθέτησης: η διεύθυνση βάσης, ως προς την οποία γίνονται όλες οι αναφορές μνήμης εντός του κώδικα, παίρνει την τιμή της θέσης μνήμης στην οποία πραγματικά φορτώθηκε η πρώτη εντολή του προγράμματος. Αυτή η θέση μνήμης δεν είναι γνωστή πριν από τη φόρτωση (εκτός αν το ΛΣ δεν είναι [[πολυδιεργασία|πολυδιεργασιακό]], όπως το [[MS-DOS]], κάτι πολύ σπάνιο σήμερα), οπότε αυτή η επανατοποθέτηση όλου του εκτελέσιμου πρέπει να γίνεται σε κάθε εκτέλεση. Αν όμως το ΛΣ παρέχει υποσύστημα εικονικής μνήμης, τότε αυτό το βήμα δεν είναι απαραίτητο αφού κάθε διεργασία έχει έναν πλήρη, ιδιωτικό χώρο εικονικών διευθύνσεων στη διάθεσή της, με τον μηχανισμό εικονικής μνήμης του [[πυρήνας (υπολογιστές)|πυρήνα]] να αναλαμβάνει την αντιστοίχιση με τη φυσική μνήμη (αχρηστεύοντας έτσι την επανατοποθέτηση [[χρόνος φόρτωσης|χρόνου φόρτωσης]]). Εν πάση περιπτώσει, μόλις ο φορτωτής ολοκληρώσει την εργασία του τερματίζεται και η νέα διεργασία είναι έτοιμη προς εκτέλεση. Το πότε θα αρχίσει πραγματικά να εκτελείται είναι θέμα του [[χρονοπρογραμματιστής|χρονοπρογραμματιστή]] του πυρήνα.
 
== Κατηγορίες ==
Οι βιβλιοθήκες μπορεί να είναι στατικές ή δυναμικές, καθώς και κοινόχρηστες ή μη. Όταν ένα πρόγραμμα καλεί υποπρογράμματα από στατικές βιβλιοθήκες, ο συνδέτης (ο οποίος συμβουλεύεται κατάλληλα αρχεία ρυθμίσεων ή το ΛΣ για να βρει τις βιβλιοθήκες) ενσωματώνει πραγματικά τον αντικειμενικό τους κώδικα στο εκτελέσιμο που παράγει και επανατοποθετεί κατάλληλα τις διευθύνσεις μνήμης σε [[χρόνος σύνδεσης|χρόνο σύνδεσης]]. Αντίθετα, οι δυναμικές βιβλιοθήκες ενσωματώνονται και επανατοποθετούνται στον τελικό κώδικα απευθείας στη μνήμη και ενώ το πρόγραμμα εκτελείται, με αποτέλεσμα τα εκτελέσιμα αρχεία να έχουν σαφώς μικρότερο μέγεθος (αφού περιέχουν απλώς οδηγίες προς έναν συνδέτη [[χρόνος εκτέλεσης|χρόνου εκτέλεσης]], παρεχόμενου από το ΛΣ, αντί για τον ίδιο τον αντικειμενικό κώδικα των καλούμενων υποπρογραμμάτων βιβλιοθήκης), αλλά να απαιτείται η μόνιμη παρουσία του αντικειμενικού αρχείου της βιβλιοθήκης στο σύστημα αρχείων προκειμένου να είναι δυνατή η εκτέλεση του προγράμματος. Επίσης οι δυναμικές βιβλιοθήκες μπορούν να είναι κοινόχρηστες, δηλαδή να υπάρχει μόνο ένα αντίγραφό τους το οποίο διαμοιράζεται σε πολλαπλές διεργασίες που τις χρησιμοποιούν ταυτόχρονα. Η κοινοχρησία μπορεί να συμβαίνει είτε μόνο στον δίσκο (να υπάρχει δηλαδή ένα μόνο αντικειμενικό αρχείο της βιβλιοθήκης), όπως συμβαίνει με τα αρχεία με επέκταση «.dll» στα Windows, είτε και στη μνήμη (να φορτώνεται μόνο μία φορά η βιβλιοθήκη στη μνήμη RAM και όσα προγράμματα τη χρησιμοποιούν να απεικονίζουν το τμήμα μνήμης που καταλαμβάνει στον ιδιωτικό εικονικό χώρο διευθύνσεών τους), όπως συμβαίνει με τα αρχεία με επέκταση «.so» στο Unix. Επειδή ητο μορφήμορφότυπο αρχείου των βιβλιοθηκών είναι ίδιαίδιο με των αυτόνομων εκτελέσιμων και αντικειμενικών αρχείων, ακόμα κι ένα εκτελέσιμο μπορεί να χρησιμοποιηθεί ως κοινόχρηστη βιβλιοθήκη, αρκεί να περιέχει έναν πίνακα συμβόλων για χρήση από τον συνδέτη χρόνου εκτέλεσης, με πληροφορίες για τις συναρτήσεις και τις δομές δεδομένων που εξάγει.
 
Η εξάπλωση του [[αντικειμενοστρεφής προγραμματισμός|αντικειμενοστρεφούς προγραμματισμού]] στις αρχές της [[Δεκαετία 1990|δεκαετίας του 1990]] έκανε επιτακτική την ανάγκη προτυποποίησης μιαςενός μορφήςμορφοτύπου αντικειμενικών αρχείων βιβλιοθηκών που δεν θα περιείχαν μεμονωμένες [[δομή δεδομένων|δομές δεδομένων]] και διαδικασίες, αλλά [[Κλάση (υπολογιστές)|κλάσεις]]. Η κληρονομικότητα όμως, έμφυτο και ισχυρό χαρακτηριστικό της αντικειμενοστρέφειας, δυσχέραινε αυτήν την προσπάθεια, αφού για να οριστεί μία ''μέθοδος'' (η αντικειμενοστραφής «εκδοχή» της διαδικασίας) δεν επαρκεί το πλήρες αναγνωριστικό της και το σημείο εισόδου του κώδικά της, αλλά χρειάζεται και μια λίστα των κλάσεων από τις οποίες κληρονομείται. Παράλληλα την ίδια στιγμή είχαν γίνει δημοφιλή τα [[κατανεμημένη επεξεργασία|κατανεμημένα συστήματα]] λογισμικού, τα οποία επέτρεπαν σε ένα πρόγραμμα να εκτελεί διαφανώς κλήσεις σε απομακρυσμένες διαδικασίες, ο κώδικας των οποίων ήταν τοποθετημένος σε κάποιον άλλον κόμβο ενός [[δίκτυο υπολογιστών|δικτύου υπολογιστών]]. Οι ενδιαφερόμενες εταιρίες, λοιπόν, περί το 1995, προτυποποίησαν διάφορεςδιάφορα μορφέςμορφότυπα αντικειμενικών αρχείων βιβλιοθηκών κλάσεων, οι μέθοδοι των οποίων μπορούσαν να εκτελεστούν σε διαφορετικά ΛΣ και να προσπελαστούν από διάφορες γλώσσες προγραμματισμού. Συνήθως οι βιβλιοθήκες αυτές διατίθονταν σε δύο εκδόσεις: μία απλή και μία κατανεμημένη, η οποία λειτουργούσε ως [[ενδιάμεσο λογισμικό]] και υποστήριζε απομακρυσμένη πρόσβαση και κλήση μεθόδων.
 
Με το πέρασμα του χρόνου το μόνο που επιβίωσε από αυτά τα πρότυπα είναι το COM της [[Microsoft]] (με το DCOM να είναι η κατανεμημένη εκδοχή του). Εξαίρεση αποτέλεσε ο προγραμματιστικός κόσμος της [[Java]] ο οποίος ακολούθησε τη δική του οδό, αφού τα προγράμματα και οι βιβλιοθήκες της Java δεν μεταγλωττίζονται σε εγγενή κώδικα μηχανής αλλά σε έναν ενδιάμεσο, κοινό για όλες τις [[αρχιτεκτονική υπολογιστών|αρχιτεκτονικές υπολογιστών]], [[bytecode]], ο οποίος για να τρέξει [[διερμηνέας (πληροφορική)|διερμηνεύεται]] σε χρόνο εκτέλεσης από μία ''Εικονική Μηχανή Java'', ένα περιβάλλον εκτέλεσης που τοποθετείται πάνω από το ΛΣ. Στην Java κάθε κλάση μεταγλωττίζεται σε ένα αρχείο με επέκταση «.class», αντίστοιχο του αντικειμενικού αρχείου, το οποίο περιέχει bytecode, ενώ ένα αυτόνομο πρόγραμμα είναι απλώς μία κλάση που περιέχει μία μέθοδο με όνομα <code>main()</code> ως σημείο εισόδου. Ο συνδέτης και ο φορτωτής αποτελούν τμήματα της Εικονικής Μηχανής Java και καλούνται αυτόματα και δυναμικά όταν επίκειται εκτέλεση ενός αρχείου .class. Μία συλλογή αρχείων .class που δεν περιέχουν μεθόδους <code>main()</code>, ουσιαστικά δηλαδή μία βιβλιοθήκη κλάσεων, μπορεί να συνενωθεί σε ένα συμπιεσμένο αρχείο «.jar», το οποίο δεν είναι παρά μια,ένα ανεξάρτητηανεξάρτητο αρχιτεκτονικής, μορφήμορφότυπο μεταγλωττισμένων (σε bytecode) βιβλιοθηκών κλάσεων.
 
==Ονομασία==
Γραμμή 23:
*[[GNU]]/[[Linux]], [[Solaris (λειτουργικό σύστημα)|Solaris]] και κλώνοι του [[BSD]]: <code>libfoo.a</code> και <code>libfoo.so</code> τα αρχεία τοποθετούνται σε καταλόγους όπως <code>/lib</code>, <code>/usr/lib</code> ή <code>/usr/local/lib</code>. Τα ονόματα των αρχείων ξεκινούν πάντα με <code>lib</code>, και τελειώνουν με <code>.a</code> (αρχειοθήκες, στατικές βιβλιοθήκες) ή <code>.so</code> (δυναμικές κοινόχρηστες βιβλιοθήκες), με έναν προαιρετικό αριθμό έκδοσης. Για παράδειγμα η <code>libfoo.so.2</code> είναι η δεύτερη κύρια αναθεώρηση της δυναμικής βιβλιοθήκης <code>libfoo</code>. Παλιές εκδόσεις του Unix χρησιμοποιούσαν πρωτεύοντα και δευτερεύοντα αριθμό έκδοσης, π.χ. <code>libfoo.so.1.2</code>, ενώ οι σύγχρονες εκδόσεις μόνο τον πρωτεύοντα, π.χ. (<code>libfoo.so.1</code>). Δυναμικές βιβλιοθήκες τοποθετούνται στο <code>/usr/libexec</code> και παρόμοιους καταλόγους. Η επέκταση <code>.la</code>, που συναντάται σε αρχεία ορισμένες φορές, αφορά αρχειοθήκες [[libtool]] σε μη άμεσα χρησιμοποιήσιμη κατάσταση.
*[[Mac OS X]] και άνω: Το σύστημα κληρονομεί για τις στατικές βιβλιοθήκες τις συμβάσεις του BSD και μπορεί να χρησιμοποιεί και βιβλιοθήκες τύπου <code>.so</code> (όμως με την επέκταση <code>.dylib</code>).
*[[Microsoft Windows]]: αρχεία με επέκταση <code>.lib</code> αποτελούν στατικές βιβλιοθήκες, ενώ αρχεία με κατάληξη <code>.DLLdll</code> δυναμικές βιβλιοθήκες. Οι εκδόσεις είναι κωδικοποιημένες μέσα στα αρχεία.