Περιγραφείς Αρχείων & Ανακατεύθυνση EE 1 lalis@inf.uth.gr
Περιγραφέας αρχείου Όταν ανοίγεται ένα αρχείο, το λειτουργικό επιστρέφει ένα περιγραφέα (fil dscriptor) μέσω του οποίου πραγματοποιούνται οι λειτουργίες πρόσβασης δίνεται ως παράμετρος στις rad, writ,clos, Ένα πρόγραμμα μπορεί να δημιουργεί/διατηρεί ξεχωριστούς περιγραφείς για το ίδιο αρχείο Κάθε περιγραφέας «έχει» την δική του θέση ανάγνωσης/εγγραφής πάνω στο αρχείο Λειτουργίες που εκτελούνται μέσω ενός περιγραφέα δεν επηρεάζουν την θέση ανάγνωση/εγγραφής των άλλων περιγραφέων 2 lalis@inf.uth.gr
fd1 fd2 oprating systm 3 lalis@inf.uth.gr
int fd1,fd2; fd1=opn("tst",o_rdwr Ο_CREAT Ο_TRUNC,S_IRWXU); fd2=opn("tst",o_rdwr,0); writ(fd1,"a boring lctur",16); writ(fd2,"a suprb",8); ftruncat(fd1,2); writ(fd2,"lctur",7); clos(fd1); clos(fd2); 4 lalis@inf.uth.gr
int fd1,fd2; fd1=opn("tst",o_rdwr Ο_CREAT Ο_TRUNC,S_IRWXU); fd2=opn("tst",o_rdwr,0); writ(fd1,"a boring lctur",16); writ(fd2,"a suprb",8); ftruncat(fd1,2); writ(fd2,"lctur",7); clos(fd1); clos(fd2); fd1 tst 5 lalis@inf.uth.gr
int fd1,fd2; fd1=opn("tst",o_rdwr Ο_CREAT Ο_TRUNC,S_IRWXU); fd2=opn("tst",o_rdwr,0); writ(fd1,"a boring lctur",16); writ(fd2,"a suprb",8); ftruncat(fd1,2); writ(fd2,"lctur",7); clos(fd1); clos(fd2); fd1 fd2 tst 6 lalis@inf.uth.gr
int fd1,fd2; fd1=opn("tst",o_rdwr Ο_CREAT Ο_TRUNC,S_IRWXU); fd2=opn("tst",o_rdwr,0); writ(fd1,"a boring lctur",16); writ(fd2,"a suprb",8); ftruncat(fd1,2); writ(fd2,"lctur",7); clos(fd1); clos(fd2); fd2 fd1 tst a b o r i n g l c t u r 7 lalis@inf.uth.gr
int fd1,fd2; fd1=opn("tst",o_rdwr Ο_CREAT Ο_TRUNC,S_IRWXU); fd2=opn("tst",o_rdwr,0); writ(fd1,"a boring lctur",16); writ(fd2,"a suprb",8); ftruncat(fd1,2); writ(fd2,"lctur",7); clos(fd1); clos(fd2); fd2 fd1 tst a s u p r b l c t u r 8 lalis@inf.uth.gr
int fd1,fd2; fd1=opn("tst",o_rdwr Ο_CREAT Ο_TRUNC,S_IRWXU); fd2=opn("tst",o_rdwr,0); writ(fd1,"a boring lctur",16); writ(fd2,"a suprb",8); ftruncat(fd1,2); writ(fd2,"lctur",7); clos(fd1); clos(fd2); fd2 fd1 tst a s u p r b l c t u r 9 lalis@inf.uth.gr
int fd1,fd2; fd1=opn("tst",o_rdwr Ο_CREAT Ο_TRUNC,S_IRWXU); fd2=opn("tst",o_rdwr,0); writ(fd1,"a boring lctur",16); writ(fd2,"a suprb",8); ftruncat(fd1,2); writ(fd2,"lctur",7); clos(fd1); clos(fd2); fd2 fd1 tst a 10 lalis@inf.uth.gr
int fd1,fd2; fd1=opn("tst",o_rdwr Ο_CREAT Ο_TRUNC,S_IRWXU); fd2=opn("tst",o_rdwr,0); writ(fd1,"a boring lctur",16); writ(fd2,"a suprb",8); ftruncat(fd1,2); writ(fd2,"lctur",7); clos(fd1); clos(fd2); fd2 fd1 tst a 00 00 00 00 00 00 l c t u r 11 lalis@inf.uth.gr
int fd1,fd2; fd1=opn("tst",o_rdwr Ο_CREAT Ο_TRUNC,S_IRWXU); fd2=opn("tst",o_rdwr,0); writ(fd1,"a boring lctur",16); writ(fd2,"a suprb",8); ftruncat(fd1,2); writ(fd2,"lctur",7); clos(fd1); clos(fd2); fd2 tst a 00 00 00 00 00 00 l c t u r 12 lalis@inf.uth.gr
int fd1,fd2; fd1=opn("tst",o_rdwr Ο_CREAT Ο_TRUNC,S_IRWXU); fd2=opn("tst",o_rdwr,0); writ(fd1,"a boring lctur",16); writ(fd2,"a suprb",8); ftruncat(fd1,2); writ(fd2,"lctur",7); clos(fd1); clos(fd2); tst a 00 00 00 00 00 00 l c t u r 13 lalis@inf.uth.gr
Δομή πρόσβασης Όταν ανοίγει ένα αρχείο, το λειτουργικό δημιουργεί (εσωτερικά) μια ξεχωριστή δομή πρόσβασης Η δομή πρόσβασης περιέχει πληροφορία για το είδος πρόσβασης στο αρχείο (mod στην opn) καθώς και για την τρέχουσα θέση ανάγνωσης/εγγραφής Το λειτουργικό διατηρεί (εσωτερικά) έναν πίνακα από δείκτες στις δομές πρόσβασης που έχουν δημιουργηθεί στο πλαίσιο κάθε προγράμματος Ο πίνακας αυτός δεν είναι άμεσα προσπελάσιμος από τον κώδικα της εφαρμογής (επίπεδο χρήστη) 14 lalis@inf.uth.gr
Τι είναι τελικά ο περιγραφέας αρχείου; Η θέση στον πίνακα όπου βρίσκεται ο δείκτης στην νέα δομή πρόσβασης που δημιουργήθηκε μέσω opn Είναι ένας «απλός» ακέραιος Στις λειτουργίες rad, writ, clos δεν πρέπει απαραίτητα να δοθεί μια τιμή που επέστρεψε η opn Μπορεί να δοθεί μια οποιαδήποτε τιμή ακεραίου με ευθύνη του προγραμματιστή π.χ., προκαθορισμένες τιμές 0,1,2 για stdin, stdout, stdrr Θα χρησιμοποιηθεί η (όποια) δομή πρόσβασης «τυχαίνει» να βρίσκεται σε αυτή τη θέση του πίνακα 15 lalis@inf.uth.gr
Κόμβος πληροφορίας i-nod Για κάθε ανοιχτό αρχείο, το λειτουργικό διατηρεί μια ξεχωριστή δομή (information nod) όπου αποθηκεύονται διάφορες πληροφορίες ιδιοκτήτης, ομάδα άδειες πρόσβασης μέγεθος, αριθμός μπλοκ αριθμός συσκευής που βρίσκεται το αρχείο χρονοσφραγίδα πρόσφατης πρόσβασης/αλλαγής δεδομένα που κρατιούνται προσωρινά στην μνήμη Για κάθε ανοιχτό αρχείο, υπάρχει μόνο ένα i-nod, στο οποίο συνδέονται όλες οι δομές πρόσβασης Το i-nod μπορεί να προσπελαστεί μέσω των λειτουργιών stat, lstat, fstat 16 lalis@inf.uth.gr
0 1 2 3 4 fr slots fil dscriptor tabl i-nod i-nod fil1 fil2 17 lalis@inf.uth.gr
0 1 2 3 4 fr slots fil dscriptor tabl i-nod fil 18 lalis@inf.uth.gr
Αντίγραφα περιγραφέων int dup(int fd): δημιουργεί ένα αντίγραφο του περιγραφέα fd, που δείχνει στην ίδια δομή πρόσβασης, και επιστρέφει την θέση του νέου περιγραφέα στον πίνακα των δομών πρόσβασης int dup2(int fd, int id): δημιουργεί ένα αντίγραφο του fd, στην θέση id του πίνακα αν στην θέση id ήδη υπάρχει δείκτης σε κάποια άλλη δομή πρόσβασης, γίνεται αντικατάσταση Τα αντίγραφα δείχνουν στην ίδια δομή πρόσβασης! έχουν την ίδια θέση ανάγνωσης/εγγραφής 19 lalis@inf.uth.gr
3 4 fil dscriptor tabl dvic/fil dvic/fil 20 lalis@inf.uth.gr
3 4 5 nxt fr slot fil dscriptor tabl dup(3); dvic/fil dvic/fil 21 lalis@inf.uth.gr
3 4 5 fil dscriptor tabl dvic/fil dvic/fil 22 lalis@inf.uth.gr
3 4 5 fil dscriptor tabl dup2(4,3); dvic/fil dvic/fil 23 lalis@inf.uth.gr
3 4 5 fil dscriptor tabl dvic/fil dvic/fil 24 lalis@inf.uth.gr
int fd1,fd2; fd1=opn("tst",o_rdwr Ο_CREAT O_TRUNC,S_IRWXU); fd2=dup(fd1); writ(fd1,"hav a nic",11); writ(fd2," day",4); clos(fd1); clos(fd2); 25 lalis@inf.uth.gr
int fd1,fd2; fd1=opn("tst",o_rdwr Ο_CREAT O_TRUNC,S_IRWXU); fd2=dup(fd1); writ(fd1,"hav a nic",11); writ(fd2," day",4); clos(fd1); clos(fd2); fd1 tst 26 lalis@inf.uth.gr
int fd1,fd2; fd1=opn("tst",o_rdwr Ο_CREAT O_TRUNC,S_IRWXU); fd2=dup(fd1); writ(fd1,"hav a nic",11); writ(fd2," day",4); clos(fd1); clos(fd2); fd1,fd2 tst 27 lalis@inf.uth.gr
int fd1,fd2; fd1=opn("tst",o_rdwr Ο_CREAT O_TRUNC,S_IRWXU); fd2=dup(fd1); writ(fd1,"hav a nic",11); writ(fd2," day",4); clos(fd1); clos(fd2); fd1,fd2 tst h a v a n i c 28 lalis@inf.uth.gr
int fd1,fd2; fd1=opn("tst",o_rdwr Ο_CREAT O_TRUNC,S_IRWXU); fd2=dup(fd1); writ(fd1,"hav a nic",11); writ(fd2," day",4); clos(fd1); clos(fd2); fd1,fd2 tst h a v a n i c d a y 29 lalis@inf.uth.gr
int fd1,fd2; fd1=opn("tst",o_rdwr Ο_CREAT O_TRUNC,S_IRWXU); fd2=dup(fd1); writ(fd1,"hav a nic",11); writ(fd2," day",4); clos(fd1); clos(fd2); fd2 tst h a v a n i c d a y 30 lalis@inf.uth.gr
int fd1,fd2; fd1=opn("tst",o_rdwr Ο_CREAT O_TRUNC,S_IRWXU); fd2=dup(fd1); writ(fd1,"hav a nic",11); writ(fd2," day",4); clos(fd1); clos(fd2); tst h a v a n i c d a y 31 lalis@inf.uth.gr
Είσοδος-έξοδος προγράμματος Κατά σύμβαση, οι θέσεις 0, 1 και 2 του πίνακα δομών πρόσβασης παίζουν ξεχωριστό ρόλο καθιερωμένη είσοδος, έξοδος, έξοδος λαθών Αρχικά, στις θέσεις αυτές αποθηκεύονται δομές πρόσβασης για την τερματική συσκευή μέσω της οποίας γίνεται η αλληλεπίδραση με τον χρήστη 0 = είσοδος τερματικού = πληκτρολόγιο 1,2 = έξοδος τερματικού = οθόνη Οι αντίστοιχες δομές πρόσβασης δημιουργούνται από το λειτουργικό / περιβάλλον εκτέλεσης, χωρίς να πρέπει να γραφτεί/εκτελεστεί κώδικας εφαρμογής 32 lalis@inf.uth.gr
0 1 2 fil dscriptor tabl 33 lalis@inf.uth.gr
0 1 2 scanf(...); fil dscriptor tabl rad(0,...); 34 lalis@inf.uth.gr
0 1 2 printf(...); fil dscriptor tabl writ(1,...); 35 lalis@inf.uth.gr
Ανακατεύθυνση εισόδου/εξόδου Η είσοδος/έξοδος ενός προγράμματος δεν είναι παγιωμένη στην τερματική συσκευή του χρήστη Αυτό που είναι παγιωμένο (καθαρά ως σύμβαση) είναι ο ρόλος των δομών πρόσβασης που «τυχαίνει» να βρίσκονται στις θέσεις 0, 1, 2 Μπορεί να γίνει αντικατάσταση των δομών πρόσβασης που βρίσκονται σε αυτές τις θέσεις με dup2, κατά την διάρκεια της εκτέλεσης οι νέες δομές πρόσβασης πρέπει να έχουν ανοίξει για διάβασμα και γράψιμο, αντίστοιχα Αυτό γίνεται εν αγνοία του όποιου κώδικα έχει ήδη γραφτεί να χρησιμοποιεί τους περιγραφείς 0, 1, 2 36 lalis@inf.uth.gr
0 1 2 3 printf(...); fil dscriptor tabl writ(1,...); 37 lalis@inf.uth.gr
0 1 2 3 fil dscriptor tabl dup2(3,1); 38 lalis@inf.uth.gr
0 1 2 3 printf(...); fil dscriptor tabl writ(1,...); 39 lalis@inf.uth.gr
0 1 2 3 scanf(...); fil dscriptor tabl rad(0,...); 40 lalis@inf.uth.gr
0 1 2 3 fil dscriptor tabl dup2(3,0); 41 lalis@inf.uth.gr
0 1 2 3 scanf(...); fil dscriptor tabl rad(0,...); 42 lalis@inf.uth.gr
int fd,oldout,oldin; char buf[16]; fd=opn("tst",o_rdwr Ο_CREAT O_TRUNC,S_IRWXU); writ(fd,"hllo ",6); // to fil oldout = dup(stdout_fileno); // copy stdout dup2(fd,stdout_fileno); // rdirct stdout to fd writ(stdout_fileno,"and hllo\n",10); // to fil dup2(oldout,stdout_fileno); // rstor stdout 0 1 43 lalis@inf.uth.gr
int fd,oldout,oldin; char buf[16]; fd=opn("tst",o_rdwr Ο_CREAT O_TRUNC,S_IRWXU); writ(fd,"hllo ",6); // to fil oldout = dup(stdout_fileno); // copy stdout dup2(fd,stdout_fileno); // rdirct stdout to fd writ(stdout_fileno,"and hllo\n",10); // to fil dup2(oldout,stdout_fileno); // rstor stdout fd 0 1 tst 44 lalis@inf.uth.gr
int fd,oldout,oldin; char buf[16]; fd=opn("tst",o_rdwr Ο_CREAT O_TRUNC,S_IRWXU); writ(fd,"hllo ",6); // to fil oldout = dup(stdout_fileno); // copy stdout dup2(fd,stdout_fileno); // rdirct stdout to fd writ(stdout_fileno,"and hllo\n",10); // to fil dup2(oldout,stdout_fileno); // rstor stdout fd 0 1 tst h l l o 45 lalis@inf.uth.gr
int fd,oldout,oldin; char buf[16]; fd=opn("tst",o_rdwr Ο_CREAT O_TRUNC,S_IRWXU); writ(fd,"hllo ",6); // to fil oldout = dup(stdout_fileno); // copy stdout dup2(fd,stdout_fileno); // rdirct stdout to fd writ(stdout_fileno,"and hllo\n",10); // to fil dup2(oldout,stdout_fileno); // rstor stdout 0 fd oldout,1 tst h l l o 46 lalis@inf.uth.gr
int fd,oldout,oldin; char buf[16]; fd=opn("tst",o_rdwr Ο_CREAT O_TRUNC,S_IRWXU); writ(fd,"hllo ",6); // to fil oldout = dup(stdout_fileno); // copy stdout dup2(fd,stdout_fileno); // rdirct stdout to fd writ(stdout_fileno,"and hllo\n",10); // to fil dup2(oldout,stdout_fileno); // rstor stdout 0 fd,1 oldout tst h l l o 47 lalis@inf.uth.gr
int fd,oldout,oldin; char buf[16]; fd=opn("tst",o_rdwr Ο_CREAT O_TRUNC,S_IRWXU); writ(fd,"hllo ",6); // to fil oldout = dup(stdout_fileno); // copy stdout dup2(fd,stdout_fileno); // rdirct stdout to fd writ(stdout_fileno,"and hllo\n",10); // to fil dup2(oldout,stdout_fileno); // rstor stdout 0 oldout fd,1 tst h l l o a n d h l l o \n 48 lalis@inf.uth.gr
int fd,oldout,oldin; char buf[16]; fd=opn("tst",o_rdwr Ο_CREAT O_TRUNC,S_IRWXU); writ(fd,"hllo ",6); // to fil oldout = dup(stdout_fileno); // copy stdout dup2(fd,stdout_fileno); // rdirct stdout to fd writ(stdout_fileno,"and hllo\n",10); // to fil dup2(oldout,stdout_fileno); // rstor stdout 0 oldout,1 fd tst h l l o a n d h l l o \n 49 lalis@inf.uth.gr
int fd,oldout,oldin; char buf[16]; lsk(fd,0,seek_set); oldin = dup(stdin_fileno); // copy stdin dup2(fd,stdin_fileno); // rdirct stdin to fd rad(stdin_fileno,buf,16); // from fil dup2(oldin,stdin_fileno); // rstor stdin clos(fd); clos(oldout); clos(oldin); 0 oldout,1 fd tst h l l o a n d h l l o \n 50 lalis@inf.uth.gr
int fd,oldout,oldin; char buf[16]; lsk(fd,0,seek_set); oldin = dup(stdin_fileno); // copy stdin dup2(fd,stdin_fileno); // rdirct stdin to fd rad(stdin_fileno,buf,16); // from fil dup2(oldin,stdin_fileno); // rstor stdin clos(fd); clos(oldout); clos(oldin); fd 0 oldout,1 tst h l l o a n d h l l o \n 51 lalis@inf.uth.gr
int fd,oldout,oldin; char buf[16]; lsk(fd,0,seek_set); oldin = dup(stdin_fileno); // copy stdin dup2(fd,stdin_fileno); // rdirct stdin to fd rad(stdin_fileno,buf,16); // from fil dup2(oldin,stdin_fileno); // rstor stdin clos(fd); clos(oldout); clos(oldin); fd 0,oldin oldout,1 tst h l l o a n d h l l o \n 52 lalis@inf.uth.gr
int fd,oldout,oldin; char buf[16]; lsk(fd,0,seek_set); oldin = dup(stdin_fileno); // copy stdin dup2(fd,stdin_fileno); // rdirct stdin to fd rad(stdin_fileno,buf,16); // from fil dup2(oldin,stdin_fileno); // rstor stdin clos(fd); clos(oldout); clos(oldin); fd,0 oldin oldout,1 tst h l l o a n d h l l o \n 53 lalis@inf.uth.gr
int fd,oldout,oldin; char buf[16]; lsk(fd,0,seek_set); oldin = dup(stdin_fileno); // copy stdin dup2(fd,stdin_fileno); // rdirct stdin to fd rad(stdin_fileno,buf,16); // from fil dup2(oldin,stdin_fileno); // rstor stdin clos(fd); clos(oldout); clos(oldin); oldin oldout,1 fd,0 tst h l l o a n d h l l o \n 54 lalis@inf.uth.gr
int fd,oldout,oldin; char buf[16]; lsk(fd,0,seek_set); oldin = dup(stdin_fileno); // copy stdin dup2(fd,stdin_fileno); // rdirct stdin to fd rad(stdin_fileno,buf,16); // from fil dup2(oldin,stdin_fileno); // rstor stdin clos(fd); clos(oldout); clos(oldin); 0,oldin oldout,1 fd tst h l l o a n d h l l o \n 55 lalis@inf.uth.gr
int fd,oldout,oldin; char buf[16]; lsk(fd,0,seek_set); oldin = dup(stdin_fileno); // copy stdin dup2(fd,stdin_fileno); // rdirct stdin to fd rad(stdin_fileno,buf,16); // from fil dup2(oldin,stdin_fileno); // rstor stdin clos(fd); clos(oldout); clos(oldin); 0,oldin oldout,1 tst h l l o a n d h l l o \n 56 lalis@inf.uth.gr
int fd,oldout,oldin; char buf[16]; lsk(fd,0,seek_set); oldin = dup(stdin_fileno); // copy stdin dup2(fd,stdin_fileno); // rdirct stdin to fd rad(stdin_fileno,buf,16); // from fil dup2(oldin,stdin_fileno); // rstor stdin clos(fd); clos(oldout); clos(oldin); 0,oldin 1 tst h l l o a n d h l l o \n 57 lalis@inf.uth.gr
int fd,oldout,oldin; char buf[16]; lsk(fd,0,seek_set); oldin = dup(stdin_fileno); // copy stdin dup2(fd,stdin_fileno); // rdirct stdin to fd rad(stdin_fileno,buf,16); // from fil dup2(oldin,stdin_fileno); // rstor stdin clos(fd); clos(oldout); clos(oldin); 0 1 tst h l l o a n d h l l o \n 58 lalis@inf.uth.gr
Αφαίρεση περιγραφέων αρχείων Οι δομές πρόσβασης, οι περιγραφείς αρχείων και οι βασικές λειτουργίες opn, rad, writ, clos αποτελούν έναν γενικό μηχανισμό πρόσβασης για οποιεσδήποτε «συσκευές» δεδομένων αρχεία δίσκου, συσκευή τερματικού αγωγούς, υποδοχείς Μπορεί να γραφτεί κώδικας και βιβλιοθήκες που χρησιμοποιούν περιγραφείς αρχείων «αφαιρετικά», χωρίς να (πολύ-)ενδιαφέρει σε τι είδους «αρχείο» (ή συσκευή) αναφέρονται στην πραγματικότητα Η βιβλιοθήκη stdio είναι ένα τέτοιο παράδειγμα 59 lalis@inf.uth.gr