160 γραμμές
14 KiB
Markdown
160 γραμμές
14 KiB
Markdown
|
+++
|
|||
|
title = 'Περιγραφή του proc filesystem'
|
|||
|
date = '2000-10-01T00:00:00Z'
|
|||
|
description = ''
|
|||
|
author = 'Πρατικάκης Πολύβιος(mailto:polyvios@softlab.ntua.gr)'
|
|||
|
issue = ['Magaz 27']
|
|||
|
issue_weight = 4
|
|||
|
+++
|
|||
|
|
|||
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
**1. Εισαγωγή**
|
|||
|
--------------------------------------
|
|||
|
|
|||
|
**2. Οι δομές του proc**
|
|||
|
-----------------------------------------------
|
|||
|
|
|||
|
**3. Std disclaimer**
|
|||
|
--------------------------------------------
|
|||
|
|
|||
|
|
|||
|
### [1. Εισαγωγή]{#s1}
|
|||
|
|
|||
|
Στο linux υπάρχει ένα σύστημα αρχείων, το proc, το οποίο προσαρτάται συνήθως στο **/proc** στο δένδρο καταλόγων, και το οποίο είναι εικονικό. Αυτό που δηλαδή
|
|||
|
φαίνεται ως αρχεία, στην πραγματικότητα δεν υπάρχει πουθενά στο δίσκο ή στην μνήμη του υπολογιστή. Στην πραγματικότητα, τα φαινομενικά αρχεία είναι απλές
|
|||
|
\"εγγραφές\" στο δένδρο καταλόγων που αντιστοιχούν το διάβασμα, γράψιμο κ.λ.π των \"αρχείων\" αυτών σε κλήσεις διαφόρων συναρτήσεων. Έτσι, όταν διαβάζει κάποιος
|
|||
|
το αρχείο π.χ. /proc/interrupts δεν διαβάζει τα περιεχόμενα ενός υπαρκτού αρχείου, αλλά απλώς την έξοδο μιας συνάρτησης που καλείται κάθε φορά που το αρχείο
|
|||
|
αυτό διαβάζεται.
|
|||
|
|
|||
|
Το εικονικό σύστημα αρχείων proc, χρησιμοποιείται κυρίως για την αναφορά πληροφοριών (δυναμικά) του συστήματος. Μπορεί δε να αλλάξει δυναμικά, δηλαδή να
|
|||
|
προστεθούν και να αφαιρεθούν αρχεία και κατάλογοι, ανάλογα με την τρέχουσα κατάσταση του συστήματος.\
|
|||
|
Ο προγραμματισμός του συστήματος αρχείων proc στον πυρήνα, προσφέρει ένα υπάρχον σύνολο συναρτήσεων (ελληνιστί API), που καθιστούν την επέμβαση στο proc και την
|
|||
|
προσθαφαίρεση αρχείων σχετικά εύκολη. Για να προσθέσουμε ένα αρχείο στο proc, χρησιμοποιούμε τη συνάρτηση proc\_register(), η οποία παίρνει ως όρισμα μια δομή
|
|||
|
που περιγράφει το αρχείο (όνομα, μέγεθος, ιδιότητες, κ.λ.π.), καθώς και τις συνδεδεμένες με το αρχείο συναρτήσεις. Επιπλέον, δίνεται η - πολύ χρήσιμη -
|
|||
|
δυνατότητα να περάσουμε ένα δείκτη, ο οποίος θα περαστεί ως παράμετρος στην συνάρτηση που κάθε φορά καλείται. Με αυτό τον τρόπο, μπορούμε να γράψουμε μια φορά
|
|||
|
τις συναρτήσεις που καλύπτουν πολλά \"ίδια\" αρχεία του proc.
|
|||
|
|
|||
|
Για παράδειγμα, προφανώς δεν χρειάζεται να γραφούν ξεχωριστές συναρτήσεις για το αρχείο /proc/parport/0/irq και /proc/parport/1/irq, αλλά οι ίδιες συναρτήσεις
|
|||
|
καλούνται με διαφορετικό όρισμα. Ο τρόπος για να γίνει αυτό, είναι ένας δείκτης void \*, ο οποίος \"συνδέεται\" με κάθε αρχείο, και \"κουβαλάει\" ό,τι αυτό
|
|||
|
χρειάζεται.
|
|||
|
|
|||
|
|
|||
|
### [2. Οι δομές του proc]{#s2}
|
|||
|
|
|||
|
Επειδή το καλό με το Open Source είναι το\... open source, παρατηρώντας το αρχείο linux/include/linux/proc\_fs.h, βλέπουμε τα εξής:
|
|||
|
|
|||
|
- 3-4 enum τα οποία καθορίζουν σταθερές. Οι σταθερές αυτές χρησιμοποιούνται από κάποια \"αρχεία\" του proc, το ποιά είναι φανερό από την ονομασία τους. Π.χ.,
|
|||
|
οι σταθερές PROC\_\* (το πρώτο enum), είναι τα \"είδη\" των αρχείων ή καταλόγων που βλέπει κανείς ακριβώς \"κάτω\" από το σημείο που προσαρτάται το proc,
|
|||
|
συνήθως δηλαδή στο /proc/\*. Οι σταθερές PROC\_NET\_\* βρίσκονται στο /proc/net κ.ο.κ.
|
|||
|
- Στη συνέχεια, βλέπουμε το σημαντικό μέρος του αρχείου, την δομή `proc_dir_entry`. Κάθε αρχείο του proc είναι ουσιαστικά μια τέτοια δομή. Αναλυτικά, τα πεδία
|
|||
|
της δομής είναι:
|
|||
|
|
|||
|
**`low_ino`**
|
|||
|
|
|||
|
: Στη μεταβλητή αυτή τίθεται το είδος του αρχείου, που συνήθως είναι μια από τις σταθερές που ορίζονται παραπάνω.
|
|||
|
|
|||
|
**`namelen`**
|
|||
|
|
|||
|
: Όπως ίσως φαίνεται, στη μεταβλητή αυτή αποθηκεύεται το μήκος του ονόματος του αρχείου.
|
|||
|
|
|||
|
**`name`**
|
|||
|
|
|||
|
: Πρόκειται για δείκτη σε null terminated αλφαριθμητικό, με το όνομα του αρχείου.
|
|||
|
|
|||
|
**`mode`**
|
|||
|
|
|||
|
: Στη μεταβλητή αυτή, καθορίζεται ο τύπος και τα permissions του αρχείου, δηλαδή το αν πρόκειται για αρχείο ή κατάλογο, αν και για ποιόν επιτρέπεται η
|
|||
|
εγγραφή, η ανάγνωση κ.λ.π.
|
|||
|
|
|||
|
**`nlink`**
|
|||
|
|
|||
|
: Στη μεταβλητή αυτή αποθηκεύεται ο αριθμός των συνδεδεμένων αρχείων με αυτό το αρχείο, δηλαδή 1 αν πρόκειται για απλό αρχείο που συνδέεται μόνο με τον
|
|||
|
κατάλογο που το περιέχει, ή 2 αν πρόκειται για κατάλογο. Στην περίπτωση αυτή, το nlink καταλόγου αυξάνει όταν προσθέτουμε αρχεία σε κατάλογο.
|
|||
|
|
|||
|
**`uid`**
|
|||
|
|
|||
|
: Το owner ID του αρχείου.
|
|||
|
|
|||
|
**`gid`**
|
|||
|
|
|||
|
: Το group ID του αρχείου.
|
|||
|
|
|||
|
**`size`**
|
|||
|
|
|||
|
: Το φαινομενικό μέγεθος του αρχείου, όπως αυτό φαίνεται π.χ. με την εντολή ls -l.
|
|||
|
|
|||
|
**`ops`**
|
|||
|
|
|||
|
: Μια δομή inode\_operations στην οποία περιέχονται δείκτες στις συναρτήσεις που χειρίζονται το inode (βλέπε κείμενα για συστήματα αρχείων) που
|
|||
|
δημιουργείται. Στο άρθρο αυτό, δεν θα υπάρξει εκτενής περιγραφή για τη δομή αυτή και τις πιθανές χρήσεις της. Για όποιον ενδιαφέρεται, ας κοιτάξει το
|
|||
|
linux kernel module programming guide, στο <http://www.linuxdoc.org> όπου γίνεται μια περιγραφή του proc, και χρησιμοποιείται η συγκεκριμένη δομή για
|
|||
|
είσοδο.
|
|||
|
|
|||
|
**`get_info`**
|
|||
|
|
|||
|
: Συνάρτηση που καλείται κατά την ανάγνωση από το αρχείο και επιστρέφει το μήκος.
|
|||
|
|
|||
|
**`fill_inode`**
|
|||
|
|
|||
|
: Η συνάρτηση αυτή καλείται για να συμπληρώσει τη δομή inode που αντιστοιχεί στο αρχείο, και χρησιμοποιείται μόνο όταν αυτά τα δεδομένα δεν μπορούν να
|
|||
|
καθοριστούν στατικά κατά την δημιουργία του αρχείου.
|
|||
|
|
|||
|
**`next,parent,subdir`**
|
|||
|
|
|||
|
: Πρόκειται για δείκτες σε δομές proc\_dir\_entry. Με το δείκτη next, δημιουργείται μια συνδεδεμένη λίστα από όλες τις εγγραφές (entries) στο proc, ενώ
|
|||
|
χρησιμοποιώντας τους δείκτες parent και subdir, διατηρείται στη μνήμη ένα \"δένδρο\" καταλόγων για το proc.
|
|||
|
|
|||
|
**`data`**
|
|||
|
|
|||
|
: Όπως αναφέρθηκε και στην εισαγωγή, κατά τη δημιουργία του αρχείου θέτουμε το δείκτη αυτό ώστε να δείχνει στα δεδομένα που αντικατοπτρίζει το αρχείο, και
|
|||
|
στη συνέχεια όταν καλλούνται οι διάφορες συναρτήσεις του αρχείου περνιέται ως παράμετρος. Έτσι, οι συναρτήσεις του αρχείου \"ξέρουν\" σε ποιά δεδομένα
|
|||
|
αναφέρεται το αρχείο αυτό.
|
|||
|
|
|||
|
**`read_proc`**
|
|||
|
|
|||
|
: Συνάρτηση που καλείται όταν το αρχείο διαβάζεται. Η συνάρτηση αυτή χρησιμοποιείται για έξοδο από τον πυρήνα, και επιστρέφει (γράφει σε ένα buffer)
|
|||
|
δεδομένα κάθε φορά που καλείται. Μια από τις παραμέτρους της συνάρτησης αυτής είναι ο δείκτης data που προαναφέρθηκε.
|
|||
|
|
|||
|
**`write_proc`**
|
|||
|
|
|||
|
: Συνάρτηση που καλείται κατά το γράψιμο στο αρχείο. Με τη συνάρτηση αυτή επιτυγχάνεται η είσοδος παραμέτρων προς τον πυρήνα μέσα από το σύστημα αρχείων
|
|||
|
proc. Αυτό βέβαια γίνεται και μέσω των συναρτήσεων του inode του αρχείου, αλλά ο τρόπος αυτός είναι προτιμότερος, γιατί υπάρχει και εδώ ο μηχανισμός με
|
|||
|
το δείκτη data, που επιτρέπει να υπάρχουν \"παρόμοια\" αρχεία.
|
|||
|
|
|||
|
**`readlink_proc`**
|
|||
|
|
|||
|
: Η συνάρτηση αυτή (από ότι έχω καταλάβει πάντα) καλείται όταν το αρχείο \"συνδέεται\" (link), όπως π.χ. με την εντολή ln.
|
|||
|
|
|||
|
**`count`**
|
|||
|
|
|||
|
: Μετρητής για την απαρίθμηση της χρήσης του αρχείου. Αυξάνει κάθε φορά που το αρχείο ανοίγεται, και μειώνεται όταν κλείνεται.
|
|||
|
|
|||
|
**`deleted`**
|
|||
|
|
|||
|
: Σημαία για το αν το αρχείο έχει σβηστεί.
|
|||
|
- Μετά τον ορισμό της δομής proc\_dir\_entry, ακολουθούν ορισμοί τύπων για τους δείκτες συναρτήσεων που χρησιμοποιούνται, και δηλώνονται ορισμένες μεταβλητές
|
|||
|
που αντιστοιχούν στα \"σίγουρα\" αρχεία του proc, όπως π.χ. η ρίζα του, οι υποκατάλογοι net, scsi, sys, pid, κ.λ.π.
|
|||
|
- Οι επόμενες ενδιαφέρουσες δηλώσεις στο αρχείο, είναι αυτές των συναρτήσεων proc\_register και proc\_unregister. Χρησιμοποιώντας τις συναρτήσεις αυτές,
|
|||
|
\"βάζουμε\" και \"βγάζουμε\" proc\_dir\_entries, δηλαδή αρχεία, στο και από το proc filesystem.
|
|||
|
|
|||
|
Η συνέχεια του αρχείου είναι λίγο εως πολύ συγκεκριμένες δηλώσεις που χρησιμοποιούνται για τα υπάρχοντα αρχεία του proc, ή απλώς δεν τα έχω ψάξει αρκετα ;-).
|
|||
|
|
|||
|
Η μέχρι τώρα επεξήγηση πρέπει να είναι αρκετή για να \"φτιάξετε\" ένα αρχείο στο proc που θα μπορεί από το να \"περιέχει\" ένα απλό \"hello world!\", μέχρι να
|
|||
|
κάνει dump τα στατιστικά μιας tbf queueing discipline (Αυτό είναι σίγουρα ένα άλλο θέμα!). Για το πού θα πρέπει να προσθέσετε την proc\_register() γραμμή σας,
|
|||
|
ένα πιθανό μέρος είναι η do\_basic\_setup() συνάρτηση στο αρχείο linux/init/main.c, ή η init\_module() συνάρτηση του αρχείου που θα κάνετε insmod (Αλλά κι αυτό
|
|||
|
είναι ένα άλλο θέμα\...)
|
|||
|
|
|||
|
Αν αυτή η περιγραφή σας άνοιξε την όρεξη, μπορείτε να διαβάσετε περισσότερα στον linux kernel module programmers guide, αν και οι αναφορές δεν είναι με τίποτα
|
|||
|
εκτενείς. Στο συγκεκριμένο guide υπάρχει γενικότερη αναφορά στα modules, σε IO - device drivers κ.λ.π. Μην ξεχνάτε όμως πως ο καλύτερος οδηγός είναι ο κώδικας.
|
|||
|
Άλλωστε γιατί ειναι τόσο σημαντικό το Open Source;
|
|||
|
|
|||
|
|
|||
|
### [3. Std disclaimer]{#s3}
|
|||
|
|
|||
|
Στο παρόν άρθρο, καταβλήθηκε προσπάθεια να περιγραφεί το σύστημα αρχείων proc, όπως το έχω καταλάβει προσωπικά από τα sources του πυρήνα, και διάφορα guides.
|
|||
|
Δεν είμαι σίγουρος ότι οι πληροφορίες που δίνονται ανταποκρίνονται στην πραγματικότητα, και μη βασιστείτε σε αυτο :-).
|
|||
|
|