TinyOS:Έκδοση 1.1.0
Από DistrSys
Το λειτουργικό σύστημα TinyOS
Η επιτυχία και η δημοτικότητα που γνωρίζουν γενικά τα ασύρματα δίκτυα αισθητήρων τα τελευταία χρόνια οφείλεται σε μεγάλο βαθμό και στο TinyOS, ένα λειτουργικό σύστημα που σχεδιάστηκε για δίκτυα τέτοιου τύπου.
Οι συσκευές που χρησιμοποιούνται σε αυτά τα δίκτυα ονομάζονται και motes. Το TinyOS μας προσφέρει μεγάλη ευελιξία και ευκολία στη δημιουργία εφαρμογών ασύρματων δικτύων αισθητήρων, παρά τις περιορισμένες δυνατότητες των motes. Γενικά, μας παρέχει ένα σύνολο από βασικές υπηρεσίες, οι οποίες μπορούν να μας φανούν χρήσιμες για την υλοποίηση κατανεμημένων αλγορίθμων.
Αυτό όμως που έχει μεγαλύτερη σημασία είναι όχι τόσο οι υπηρεσίες τις οποίες μας προσφέρει το TinyOS, οι οποίες εκ των πραγμάτων δεν μπορούν να είναι πολλές, αλλά το γεγονός ότι η φιλοσοφία και ο σχεδιασμός του είναι εναρμονισμένα με το πλαίσιο στο καλούνται να λειτουργήσουν τα motes.
Η έκδοση του TinyOS που θα χρησιμοποιήσουμε στο μάθημα είναι η 1.1.0, η οποία κυκλοφόρησε τον Σεπτέμβρη του 2003. Πριν από αυτή, κυκλοφόρησαν η έκδοση 1.1.0 τον Μάιο του 2002 και η έκδοση 0.6.1 το 2001. Η έκδοση 1.1.0 ήταν μια μεγάλη βελτίωση σε σχέση με την 0.6.1 και περιέχει αρκετές αλλαγές. Μια βασική αλλαγή, σε σχέση με τις προηγούμενες εκδόσεις, είναι ότι ολόκληρο το σύστημα γράφτηκε ξανά στη γλώσσα nesC, οπότε έχει αλλάξει και το προγραμματιστικό παράδειγμα για εφαρμογές στο TinyOS. Περισσότερα για τη nesC στο σχετικό link του μαθήματος. Πρόσφατα (Νοέμβρης 2006), κυκλοφόρησε και η έκδοση 2.0 του TinyOS.
Σχεδίαση του TinyOS
Ας δούμε τώρα πιο αναλυτικά τη σχεδίαση του TinyOS. Οι προκλήσεις που είχε να αντιμετωπίσει και να λύσει το TinyOS ήταν:
- Η χαμηλή κατανάλωση ενέργειας.
- Ιδιαίτερα υψηλές απαιτήσεις για συγχρονισμό:
- Ροή πληροφορίας από πολλές πηγές (αισθητήρες, πομποδέκτης)
- Μικρή μνήμη, που σημαίνει ότι δεν μπορεί να γίνει buffering, άρα πρέπει να επεξεργαστούμε γρήγορα τα μηνύματα που δεχόμαστε, αλλιώς μπορεί να τα χάσουμε
- Μικρό μέγεθος συνολικά του συστήματος
- Η σχεδίαση να είναι modular για να μπορούμε να φτιάξουμε γρήγορα και εύκολα εφαρμογές.
Μια απλοποιημένη εκδοχή της αρχιτεκτονικής του TinyOS φαίνεται στο διπλανό σχήμα.
Όταν λέμε ότι ένα mote τρέχει TinyOS, εννοούμε ότι έχει εγκατεστημένο στη flash μνήμη του ένα binary εκτελέσιμο image με τις βιβλιοθήκες του TinyOS που χρειαζόμαστε, συνδεδεμένες με την εφαρμογή που θέλουμε να εκτελέσουμε. Το image αυτό από εδώ και πέρα θα το αναφέρουμε ως εφαρμογή TOS (TinyOS application). Το TinyOS από μόνο του δεν εκτελεί κάποια ιδιαίτερη λειτουργία και ούτε έχει κάποιο user interface (όπως π.χ το shell στο Unix), οπότε δεν έχει κανένα νόημα να το εγκαταστήσουμε μόνο του σε ένα mote.
Επίσης, στο TinyOS δεν υπάρχει καθόλου η έννοια της διεργασίας (process) όπως την έχουμε συνηθίσει στα σύγχρονα λειτουργικά συστήματα. Αντίθετα, υπάρχει η κυρίαρχη έννοια του component, το οποίο είναι κατά κάποιο τρόπο η αφαίρεση ενός λειτουργικού module του συστήματος. Κατ' ουσία είναι ένα πεπερασμένο αυτόματο και θυμίζει τα module που συναντάμε σε γλώσσες περιγραφής υλικού όπως η Verilog και η VHDL, αν και υπάρχουν αρκετές διαφορές. Αν και τα περισσότερα component είναι software modules, μερικά απλά χρησιμοποιούνται ως ένα απλό interface για το hardware του συστήματος.
Ακόμα, πρέπει να ξεχάσουμε έννοιες όπως kernel, διαχείριση διαδικασιών (process management), εικονική μνήμη (virtual memory), δυναμική κατανομή μνήμης (dynamic memory allocation) και software σήματα (signals). Αφού δεν υπάρχει kernel πρέπει να γίνει απευθείας διαχείριση του hardware, υπάρχει μόνο μια διαδικασία στο σύστημα, υπάρχει γραμμικός χώρος διευθύνσεων και η μνήμη ανατίθεται στατικά την ώρα που γίνεται compile η εφαρμογή στο PC μας. Αυτά όλα βέβαια έχουν σαν αποτέλεσμα το πολύ μικρό μέγεθος του TinyOS, το οποίο δεν ξεπερνά τα 3400 bytes αν συμπεριληφθούν όλα τα components του συστήματος.
Προχωράμε τώρα στην έννοια του event. Τα events χρησιμοποιούνται για την επικοινωνία μεταξύ των components, κάτι σαν software interrupt δηλαδή, και οι αντίστοιχοι handlers που υπάρχουν μέσα στα components μεταβάλλουν την εσωτερική κατάσταση των components τους. Τα events μπορούν να είναι δύο ειδών:
- Εξωτερικά, προκαλούνται από hardware interrupts. Τέτοια interrupts έχουμε μόνο από τον timer και τον πομποδέκτη.
- Εσωτερικά, προκαλούνται από event handlers μέσα στα components τα οποία αρχικά ξύπνησαν από κάποιο εξωτερικό event και στη συνέχεια έστειλαν ένα event σε κάποιο άλλο component.
Μια εφαρμογή TOS αποτελείται από ένα scheduler και ένα γράφημα από components, η διασύνδεση των οποίων δείχνει την επικοινωνία μεταξύ τους και τη ροή των events. Αυτή η διασύνδεση ονομάζεται wiring specification και είναι ανεξάρτητη από τα components. Η εφαρμογή συνδέει μόνο τα components τα οποία χρειάζεται για να λειτουργήσει και έτσι στο image που φορτώνουμε στη flash περιέχονται μόνο αυτά και όχι όλα τα components του συστήματος. Οι συνδέσεις αυτές μεταξύ components, οι οποίες ονομάζονται interfaces, είναι διπλής κατεύθυνσης (bidirectional).
Ο scheduler είναι μια απλή FIFO στοίβα και περιέχει δύο ειδών αντικείμενα, events και tasks. Τα tasks χρησιμοποιούνται για εργασίες οι οποίες δεν είναι απαραίτητο να εκτελεστούν αμέσως. Όπως είδαμε, είναι σημαντικό να μην χάνουμε μηνύματα και μετρήσεις από τους αισθητήρες. Για το λόγο αυτό, προσπαθούμε να γράφουμε όσο το δυνατόν πιο απλά components, ώστε η λογική τους να εκτελείται πολύ γρήγορα. Αν υπάρχουν εργασίες που μπορούν να εκτελεστούν χωρίς να μας ενδιαφέρει το πότε θα γίνει αυτό, τις γράφουμε ως tasks και τις στέλνουμε στη στοίβα αυτή. Τα tasks μπορούν να καλέσουν άλλες συναρτήσεις ή να προκαλέσουν ένα event.
Τώρα, ένα event έχει μεγαλύτερη σημασία από ένα task, οπότε αν υπάρχουν μόνο tasks στη στοίβα και ξαφνικά έρθει ένα event, μπορεί να διακοπεί η εκτέλεση του task και να αρχίσει η εκτέλεση του event. Με άλλα λόγια, ένα task μπορεί να γίνει pre-empted από ένα event, δεν μπορεί να γίνει όμως το αντίθετο. Η εκτέλεση των events είναι ατομική μεταξύ τους, όπως ατομική είναι και η εκτέλεση μεταξύ διαφορετικών tasks.
Μια Απλή Εφαρμογή
Ας δούμε τώρα ένα παράδειγμα μιας εφαρμογής στο TinyOS. Έστω ότι έχουμε μια εφαρμογή, την οποία ονομάζουμε Sense, και κάνει τα εξής δύο απλά πράγματα:
- Παίρνει δείγματα από τον αισθητήρα φωτός σε περιοδικά χρονικά διαστήματα.
- Με κάποιο πρωτόκολλο στέλνει τις μετρήσεις που παίρνει από το πεδίο που βρίσκεται σε ένα βασικό σταθμό, μέσω μηνυμάτων που στέλνει με τον πομπό του.
Στo ακόλουθο σχήμα βλέπουμε το γράφημα με τα components για το οποίο μιλήσαμε προηγουμένως. Αμέσως βλέπουμε ότι υπάρχουν μόνο όσα components χρειαζόμαστε. Από κει και πέρα, βλέπουμε ότι το sense component συνδέεται με τρία components, το timer, το netproto και το photo. Τα ονόματα επάνω στα βέλη είναι τα ονόματα των interfaces που χρησιμοποιεί. Όπως είπαμε τα interfaces είναι ανεξάρτητα από τα components και μπορούμε να χρησιμοποιήσουμε το ίδιο interface για διαφορετικά components (π.χ οι αισθητήρες φωτός και θερμοκρασίας λειτουργούν με τον ίδιο τρόπο). Το sense component λοιπόν είναι ένα αυτόματο που θέτει αρχικά τον hardware timer χρησιμοποιώντας το αντίστοιχο interface. Όταν έρθει το event που δηλώνει ότι το χρονικό διάστημα που θέσαμε πέρασε, το sense χρησιμοποιεί το ADC interface για να πάρει μια μέτρηση από τον αισθητήρα. Ένα αναλυτικό παράδειγμα ακολουθεί στην επόμενη ενότητα.
Στο τελευταίο σχήμα φαίνεται η κατανομή της μνήμης ανάμεσα στα διάφορα μέρη από τα οποία αποτελείται το TinyOS.


