ΔΘΝΗΚΟ ΜΔΣΟΒΗΟ ΠΟΛΤΣΔΥΝΔΗΟ ΥΟΛΗ ΗΛΔΚΣΡΟΛΟΓΩΝ ΜΗΥΑΝΙΚΩΝ ΚΑΙ ΜΗΥΑΝΙΚΩΝ ΤΠΟΛΟΓΙΣΩΝ ΣΟΜΔΑ ΣΔΥΝΟΛΟΓΙΑ ΠΛΗΡΟΦΟΡΙΚΗ ΚΑΙ ΤΠΟΛΟΓΙΣΩΝ ΔΡΓΑΣΖΡΗΟ ΤΠΟΛΟΓΗΣΗΚΩΝ ΤΣΖΜΑΣΩΝ Οδεγόο Αζύξκαηνπ Γηθηύνπ Αηζζεηήξωλ ζην Λεηηνπξγηθό ύζηεκα Linux Μάξηηνο 2016
Έθδνζε εγγξάθνπ: 28/3/2016. Δπηκέιεηα: Δ. Κνύθεο, vkoukis@cslab.ece.ntua.gr
1. Δηζαγωγή Σν παξόλ θπιιάδην πεξηέρεη ηηο βαζηθέο πιεξνθνξίεο πνπ ζα ρξεηαζηείηε γηα ηελ θαηαζθεπή ηνπ Lunix:TNG, ελόο απινύ νδεγνύ ζπζθεπήο γηα ην ιεηηνπξγηθό ζύζηεκα Linux, ζην πιαίζην ηεο εξγαζηεξηαθήο ζαο άζθεζεο. ηόρνο ηνπ είλαη ε παξνπζίαζε ησλ βαζηθώλ ζρεδηαζηηθώλ αξρώλ ηνπ ππξήλα θαη ηνπ ηξόπνπ αιιειεπίδξαζήο ηνπ κε ηνπο νδεγνύο ζπζθεπώλ (device drivers). Πνιιέο από ηηο πιεξνθνξίεο πνπ πεξηέρεη πξνέξρνληαη από ην βηβιίν Linux Device Drivers, 3 rd Edition, ηνπ εθδνηηθνύ νίθνπ O Reilly (βηβιηνγξαθηθή αλαθνξά [1]). Σν βηβιίν είλαη δηαζέζηκν ειεύζεξα ζην δίθηπν θαη απνηειεί κηα εμαηξεηηθή πεγή γλώζεο ζρεηηθήο κε ηελ θαηαζθεπή νδεγώλ γηα ηνλ ππξήλα ηνπ Linux θαη ηνλ ίδην ηνλ ππξήλα γεληθόηεξα. Οη πιεξνθνξίεο πνπ πεξηέρνληαη ζην παξόλ θπιιάδην είλαη αθξηβείο γηα ηελ έθδνζε 2.6.37.4 ηνπ ππξήλα Linux. 2. Οξγάλωζε ελόο ζύγρξνλνπ ιεηηνπξγηθνύ ζπζηήκαηνο 2.1. Υώξνη ππξήλα θαη ρξήζηε To Linux είλαη έλα ζύγρξνλν ιεηηνπξγηθό ζύζηεκα αλνηρηνύ θώδηθα, πνπ βαζίδεηαη ζηηο βαζηθέο ζρεδηαζηηθέο αξρέο θαη ηελ παξάδνζε ηνπ Unix. Αλαπηύρζεθε αξρηθά από ηνλ Linus Torvalds γηα ηνλ επεμεξγαζηή i386 ηεο Intel αιιά έρεη κεηαθεξζεί έσο ζήκεξα ζε πνιιέο δηαθνξεηηθέο αξρηηεθηνληθέο (IA-64, MIPS, Alpha, SPARC, PowerPC θ.ά.). Σν Linux πξνζθέξεη ηε δπλαηόηεηα ηαπηόρξνλεο πξνζηαηεπκέλεο εθηέιεζεο πνιιώλ δηαθνξεηηθώλ δηεξγαζηώλ, πνπ αλήθνπλ ζε δηαθνξεηηθνύο ρξήζηεο, είλαη δειαδή multi-tasking θαη multi-user. Με ηνλ όξν «πξνζηαηεπκέλε» εθηέιεζε ελλνείηαη όηη θάζε δηεξγαζία εθηειείηαη ζε απνκόλσζε από ηηο ππόινηπεο, ζε δηθό ηεο εηθνληθό ρώξν δηεπζύλζεσλ θαη ρσξίο θακία δπλαηόηεηα άκεζεο πξόζβαζεο ζην πιηθό (hardware) ηνπ ππνινγηζηηθνύ ζπζηήκαηνο. Έηζη, πηζαλή δπζιεηηνπξγία ηεο δελ επεξεάδεη ηελ εμέιημε ησλ ππνινίπσλ πνπ εθηεινύληαη ζην ζύζηεκα. Δπηπιένλ, θάζε δηεξγαζία αλήθεη ζε ζπγθεθξηκέλν ρξήζηε, νπόηε έρεη θαη αλάινγα δηθαηώκαηα πξόζβαζεο ζε πόξνπο (π.ρ. απνζεθεπκέλα δεδνκέλα ζην ζύζηεκα αξρείσλ, πεξηθεξεηαθέο ζπζθεπέο) ηνπ ζπζηήκαηνο. Σν ιεηηνπξγηθό ζύζηεκα δηαρεηξίδεηαη ηνπο πόξνπο ηνπ ζπζηήκαηνο θαη ζπληνλίδεη ηελ πξόζβαζε ησλ δηεξγαζηώλ ζε απηνύο. Σν Linux είλαη έλα κνλνιηζηθό ιεηηνπξγηθό ζύζηεκα, όπσο θαη ηα πεξηζζόηεξα ζπζηήκαηα πνπ βαζίδνληαη ζην Unix: νη πεξηζζόηεξεο ιεηηνπξγίεο ηνπ πινπνηνύληαη ζε έλα πξόγξακκα, πνπ νλνκάδεηαη ππξήλαο ηνπ Λ.., ην νπνίν εθηειείηαη νιόθιεξν ζε έλα εληαίν ρώξν δηεπζύλζεσλ θαη έρεη πιήξε, ειεύζεξε πξόζβαζε ζην πιηθό (πξνλνκηνύρνο θαηάζηαζε privileged mode). Ο ππξήλαο ηνπ Linux αλαιακβάλεη ην ζύλνιν ζρεδόλ ησλ ιεηηνπξγηώλ πνπ - 3 -
ραξαθηεξίδνπλ έλα ζύγρξνλν Λ..: Γηαρείξηζε CPU, ρξνλνδξνκνιόγεζε δηεξγαζηώλ, δηαρείξηζε κλήκεο, δηαρείξηζε ζπζθεπώλ I/O, δηαρείξηζε ζπζηεκάησλ αξρείσλ, δηαδηθηύσζε. ηνλ ππξήλα ηνπ Linux βξίζθνληαη επίζεο νη νδεγνί ζπζθεπώλ (device drivers), πνπ επηηξέπνπλ ηνλ έιεγρν ησλ δηάθνξσλ πεξηθεξεηαθώλ ζπζθεπώλ. Γίλεηαη έηζη θαλεξό όηη, ππάξρνπλ δύν εληειώο ρσξηζηά επίπεδα εθηέιεζεο θώδηθα, πνπ αλαθέξνληαη ηόζν ζε δηαθνξεηηθνύο ρώξνπο κλήκεο όζν θαη ζε δηαθνξεηηθά δηθαηώκαηα πξόζβαζεο ζην πιηθό: από ηε κία είλαη ν ρώξνο ρξήζηε (userspace), ζηνλ νπνίν δνπλ θαη εθηεινύληαη νη δηεξγαζίεο ρξήζηε θαη από ηελ άιιε είλαη ν ρώξνο ππξήλα (kernelspace), ζηνλ νπνίν δεη ν θώδηθαο ηνπ ππξήλα. Η δηάθξηζε ησλ δύν ρώξσλ θαη ησλ δηαθνξεηηθώλ δηθαησκάησλ πξόζβαζεο επηβάιιεηαη κε κεραληζκνύο ηεο CPU. ρήκα 1: Οη θιήζεηο ζπζηήκαηνο σο κεραληζκόο επηθνηλσλίαο ρώξσλ ππξήλα-ρξήζηε Δθόζνλ ν θώδηθαο ζην ρώξν ππξήλα εθηειείηαη ηόζν πεξηνξηζκέλα, είλαη αλαγθαίνο έλαο κεραληζκόο κέζσ ηνπ νπνίνπ κηα δηεξγαζία κπνξεί λα δεηήζεη από ηνλ ππξήλα λα νινθιεξώζεη εθ κέξνπο ηεο ιεηηνπξγίεο πνπ ε ίδηα δελ έρεη δηθαίσκα λα πξαγκαηνπνηήζεη: Απηόο είλαη ν κεραληζκόο ησλ θιήζεωλ ζπζηήκαηνο (system calls), ν νπνίνο ιεηηνπξγεί σο εμήο: θαηά ηελ εθηέιεζή ηεο, ε δηεξγαζία εηνηκάδεη θαη ππνβάιιεη θαηάιιειε αίηεζε ζην ιεηηνπξγηθό ζύζηεκα. Σόηε, ε CPU μεθηλά λα εθηειεί θώδηθα ππξήλα, ν νπνίνο ειέγρεη ηελ νξζόηεηα ησλ δεδνκέλσλ εηζόδνπ θαη αλ ε δηεξγαζία έρεη ηα αλάινγα δηθαηώκαηα πξαγκαηνπνηεί ηε δεηνύκελε ιεηηνπξγία (π.ρ. ιεηηνπξγίεο I/O κε ην πιηθό) θαη επηζηξέθεη ηα απνηειέζκαηά ηεο πίζσ ζηνλ ρώξν ρξήζηε (ρήκα 1). Ο έιεγρνο ηόηε επαλέξρεηαη ζε θώδηθα ηεο δηεξγαζίαο. Αο δνύκε έλα παξάδεηγκα: κηα δηεξγαζία ρξεηάδεηαη λα αλνίμεη ην αξρείν /home/user/file1 ζην δίζθν γηα αλάγλσζε. Δθηειεί ινηπόλ ηελ θιήζε ζπζηήκαηνο open( /home/user/file1, O_RDONLY), νπόηε ν έιεγρνο πεξλάεη ζηνλ ρώξν ππξήλα. Ο ππξήλαο εθηειεί κηα ζεηξά ειέγρσλ αλάκεζα ζηνπο νπνίνπο είλαη όηη ην - 4 -
αξρείν πξάγκαηη ππάξρεη θαη όηη ν ρξήζηεο κε ηα δηθαηώκαηα ηνπ νπνίνπ ηξέρεη ε δηεξγαζία έρεη δηθαίσκα αλάγλσζήο ηνπ, θαηαζθεπάδεη θαηάιιειεο δνκέο ζηε κλήκε ηνπ («αλνίγεη» ην αξρείν) θαη επηζηξέθεη κηα αξηζκεηηθή ηηκή ( file descriptor ) κέζσ ηεο νπνίαο ε δηεξγαζία κπνξεί πιένλ λα αλαθέξεηαη ζε απηό. Έσο ηώξα είραηε αζρνιεζεί πεξηζζόηεξν κε ηνλ πξνγξακκαηηζκό ζε ρώξν ρξήζηε. ηελ άζθεζε απηή θαιείζηε λα γξάςεηε θώδηθα πξννξηζκέλν λα εθηειείηαη ζε ρώξν ππξήλα, σο ηκήκα ελόο νδεγνύ γηα κηα πξαγκαηηθή πεξηθεξεηαθή ζπζθεπή. Ο θώδηθαο απηόο ζα ελζσκαηώλεηαη ζηνλ ππξήλα ηνπ Linux σο kernel module. 2.2. Linux kernel modules To Linux ππνζηεξίδεη ηε δπλακηθή εηζαγσγή λένπ θώδηθα ζην ρώξν δηεπζύλζεσλ ηνπ ππξήλα, κέζσ ηνπ κεραληζκνύ ησλ ηκεκάηωλ ππξήλα (kernel modules). Σα modules είλαη ηκήκαηα θώδηθα ηα νπνία ελζσκαηώλνληαη κε ηνλ ππξήλα θαηά ηε ιεηηνπξγία ηνπ θαη επεθηείλνπλ ηηο δπλαηόηεηέο ηνπ. Έηζη, είλαη δπλαηό γηα παξάδεηγκα ν νδεγόο ζπζθεπήο γηα ηε κνλάδα δηζθέηαο λα θνξησζεί σο module ζηνλ ππξήλα, κόιηο ππάξμεη αλάγθε λα αλαθηεζνύλ ηα πεξηερόκελα κηαο δηζθέηαο θαη λα αθαηξεζεί αξγόηεξα, όηαλ πιένλ δελ είλαη απαξαίηεηνο. Δθόζνλ θάζε ηκήκα θώδηθα πνπ βξίζθεηαη ζηνλ ππξήλα έρεη ειεύζεξε πξόζβαζε ζηε κλήκε θαη ζην hardware, είλαη αλάγθε ν θώδηθαο ηνπ ππξήλα λα είλαη όζνλ ην δπλαηό απαιιαγκέλνο από πξνγξακκαηηζηηθά ιάζε, εθόζνλ δελ ππάξρεη δίρηπ πξνζηαζίαο: ε αληίζεζε κε θώδηθα πνπ εθηειείηαη σο κία δηεξγαζία θάησ από έλα Λ.., όπνπ πηζαλή δπζιεηηνπξγία νδεγεί ζηνλ ηεξκαηηζκό ηεο δηεξγαζίαο από ην Λ.. ρσξίο λα επεξεάδνληαη νη ππόινηπεο 1, εάλ δπζιεηηνπξγήζεη θώδηθαο ηνπ ππξήλα, νη ζπλέπεηεο κπνξεί λα είλαη από ην λα «θνιιήζεη» ν ππνινγηζηήο έσο ην λα ππάξμεη ζνβαξή βιάβε ζην ζύζηεκα αξρείσλ ή ζε ζπζθεπέο πιηθνύ. Απηόο είλαη θαη ν ιόγνο γηα ηνλ νπνίν ε εηζαγσγή kernel modules ζην ρώξν κλήκεο ηνπ ππξήλα επηηξέπεηαη κόλν ζην δηαρεηξηζηή ηνπ ζπζηήκαηνο, ην ρξήζηε root. 3. Οδεγνί ζπζθεπώλ ζην Linux 3.1. Ρόινο ηωλ νδεγώλ ζπζθεπώλ Έλα ζύγρξνλν ιεηηνπξγηθό ζύζηεκα ρξεηάδεηαη λα ππνζηεξίμεη πνιιέο δηαθνξεηηθέο θαηεγνξίεο πεξηθεξεηαθώλ ζπζθεπώλ (π.ρ. θάξηεο ήρνπ, θάξηεο γξαθηθώλ, πξνζαξκνγείο δηθηύνπ, ειεγθηέο κέζσλ απνζήθεπζεο) αιιά θαη πνιιέο δηαθνξεηηθέο ζπζθεπέο ζε θάζε θαηεγνξία (π.ρ. πξνζαξκνγείο δηθηύνπ δηαθνξεηηθώλ θαηαζθεπαζηώλ). Κάζε κία από απηέο ειέγρεηαη πηζαλά κε δηαθνξεηηθέο εληνιέο, 1 ην ζεκείν απηό αμίδεη λα αλαθεξζεί ην αγαπεκέλν κήλπκα όισλ: Segmentation fault - 5 -
νπόηε ρξεηάδεηαη αθξηβήο γλώζε ηνπ ηξόπνπ πξνγξακκαηηζκνύ ηεο γηα ηε ζσζηή ιεηηνπξγία ηεο θαη εηδηθόο θώδηθαο γηα ην ρεηξηζκό ηεο. Πξνθαλώο δελ είλαη δπλαηό λα απαηηνύληαη αιιαγέο ζηνλ θώδηθα ησλ εθαξκνγώλ ησλ ρξεζηώλ γηα λα ππνζηεξίδνληαη λέεο πεξηθεξεηαθέο ζπζθεπέο πνπ αλαπηύζζνληαη θαη θπθινθνξνύλ. Δπηπρώο, ην ιεηηνπξγηθό ζύζηεκα απνθξύπηεη ηηο ιεπηνκέξεηεο ηνπ ειέγρνπ ησλ ζπζθεπώλ, πίζσ από ηνλ κεραληζκό ησλ θιήζεσλ ζπζηήκαηνο. Ο θώδηθαο νξγαλώλεηαη ζε επίπεδα, κε ηηο εθαξκνγέο λα ρξεζηκνπνηνύλ πςειόηεξνπ επηπέδνπ αθαηξέζεηο (abstractions), όπσο «αξρείν», ή «TCP/IP socket» γηα λα επηθνηλσλήζνπλ κε ην έμσ θόζκν. Ωζηόζν θαη ν ίδηνο ν θώδηθαο ηνπ ππξήλα είλαη ζε κεγάιν βαζκό αλεμάξηεηνο από ηε ζπζθεπή πνπ ρξεζηκνπνηείηαη θάζε θνξά, αθξηβώο γηαηί ν ππξήλαο είλαη νξγαλσκέλνο ζε ζηξώκαηα: θάπνηα είλαη αλεμάξηεηα από ην πιηθό (π.ρ. ν ρξνλνδξνκνινγεηήο, ηα ζπζηήκαηα αξρείσλ, ε ππνζηήξημε TCP/IP), άιια όρη. Οη ιεπηνκέξεηεο ηνπ πξνγξακκαηηζκνύ θαη ειέγρνπ κηαο ζπζθεπήο πεξηθιείνληαη κέζα ζε ηκήκα θώδηθα πνπ νλνκάδεηαη νδεγόο ζπζθεπήο θαη έρεη ζπγθεθξηκέλν ηξόπν (πξνγξακκαηηζηηθή δηεπαθή interface) επηθνηλσλίαο κε ηνλ ππόινηπν ππξήλα. Έηζη κπνξεί λα αληηθαηαζηαζεί όηαλ ππάξμεη αλάγθε (π.ρ. όηαλ πξνζηεζεί κηα θάξηα δηθηύνπ ζην ζύζηεκα πνπ πξνγξακκαηίδεηαη κε δηαθνξεηηθό ηξόπν), ρσξίο λα ρξεηάδνληαη αιιαγέο ζηα ππόινηπα ηκήκαηα ηνπ ππξήλα (π.ρ. ζην ζηξώκα δηθηύνπ IP). Ωζηόζν, δελ κπνξνύλ όινη νη νδεγνί ζπζθεπώλ λα αληηκεησπηζηνύλ κε ηνλ ίδην ηξόπν από ηνλ ππξήλα, γηαηί δελ ηαηξηάδεη ε ίδηα πξνγξακκαηηζηηθή δηεπαθή ζε όιεο ηηο ζπζθεπέο. Έρεη λόεκα λα αληηκεησπίδνληαη όιεο νη θάξηεο δηθηύνπ Ethernet κε ηνλ ίδην ηξόπν (ζε ηειηθή αλάιπζε, όιεο ζηέιλνπλ θαη ιακβάλνπλ πιαίζηα Ethernet πξνο θαη από ην θαιώδην δηθηύνπ), αιιά δελ κπνξνύλ λα κπνπλ ζηελ ίδηα θαηεγνξία κε έλαλ ζθιεξό δίζθν πνπ δηαβάδεη θαη γξάθεη ηπραία κπινθ ή κε έλα πιεθηξνιόγην. Ο ππξήλαο ινηπόλ νκαδνπνηεί ηνπο νδεγνύο ζπζθεπώλ ζε έλα κηθξό αξηζκό από θαηεγνξίεο. Μέζα ζε κία θαηεγνξία, όινη νη νδεγνί πινπνηνύλ ην ίδην interface θαη αληηκεησπίδνληαη κε όκνην ηξόπν. Έηζη, γηα λα πξνζηεζεί ππνζηήξημε γηα κηα λέα ζπζθεπή πιηθνύ, ρξεηάδεηαη λα επηιεγεί κία από ηηο ππάξρνπζεο θαηεγνξίεο, ζηελ νπνία ηαηξηάδεη θαιύηεξα ε ιεηηνπξγία ηεο θαη λα γξαθεί θαηάιιεινο νδεγόο ζπζθεπήο γηα ην αληίζηνηρν interface. Σα παξαθάησ ζα γίλνπλ θαιύηεξα αληηιεπηά ζηε ζπλέρεηα, όπνπ αλαιύνληαη νη βαζηθόηεξνη ηύπνη νδεγώλ ζπζθεπώλ ζην Linux. 3.2. Καηεγνξίεο νδεγώλ ζην Linux Ο ππξήλαο ηνπ Linux δηαθξίλεη ηξεηο θύξηεο θαηεγνξίεο νδεγώλ ζπζθεπώλ (βι. θαη [1], ζει. 6). Γηα θάζε κία πξνβιέπεηαη αλάινγν interface, δειαδή έλαο ζπλδπαζκόο - 6 -
δνκώλ δεδνκέλσλ θαη ιεηηνπξγηώλ (νπζηαζηηθά, ζπλαξηήζεσλ C) πνπ ρξεηάδεηαη λα πινπνηεί ν νδεγόο. Σπζθεπέο ραξαθηήξωλ: ηελ θαηεγνξία απηή αλήθνπλ ζπζθεπέο πνπ αληηκεησπίδνληαη από ηνλ ππξήλα σο αθνινπζίεο ραξαθηήξσλ. Η πξνζπέιαζε ζε απηέο γίλεηαη κε έλα interface πνπ ζπκίδεη πξόζβαζε ζε αξρεία ζην δίζθν: νη θπξηόηεξεο ιεηηνπξγίεο πνπ πινπνηνύληαη από ηνλ νδεγό ζπζθεπήο είλαη ε ιεηηνπξγία «δηάβαζε δεδνκέλα», αληίζηνηρε ηεο read() από αξρείν, ε «γξάςε δεδνκέλα», αληίζηνηρε ηεο write(), θαη ε «κεηαθίλεζε ην ζεκείν αλάγλσζεο/εγγξαθήο», αληίζηνηρε ηεο lseek(). Οη θπξηόηεξεο ζπζθεπέο πιηθνύ πνπ ηαηξηάδνπλ ζε απηό ην κνληέιν είλαη ζεηξηαθέο θαη παξάιιειεο ζύξεο επηθνηλσλίαο, πνληίθηα, ηεξκαηηθά ρξεζηώλ, θάξηεο ήρνπ, ηαηλίεο γηα αληίγξαθα εθεδξείαο. Ση πξαγκαηηθά ζεκαίλνπλ νη ιεηηνπξγίεο αλάγλσζεο/εγγξαθήο εμαξηάηαη από ηελ ίδηα ηε ζπζθεπή: «δηάβαζε/γξάςε δεδνκέλα» από/πξνο κία ζεηξηαθή ζύξα ζεκαίλεη απνζηνιή θαη ιήςε bytes, «δηάβαζε/γξάςε δεδνκέλα» από θαη πξνο κία θάξηα ήρνπ ζεκαίλεη «θάλε δεηγκαηνιεςία ηνπ ζήκαηνο από ην κηθξόθσλν» θαη «απηά ηα bytes είλαη δείγκαηα PCM, ζηείιε ην αληίζηνηρν αλαινγηθό ζήκα ζηα ερεία», αληίζηνηρα. Σπζθεπέο κπινθ: Πξόθεηηαη γηα ζπζθεπέο ζηηο νπνίεο ε βαζηθή κνλάδα I/O είλαη ην κπινθ δεδνκέλσλ, κηα νκάδα ζηαζεξνύ αξηζκνύ bytes. Κάζε ζπζθεπή κνληεινπνηείηαη σο κηα ζπιινγή από αξηζκεκέλα κπινθ, ζηα νπνία κπνξεί λα γίλεη αλαθνξά κε ηπραία ζεηξά. Σν interface κε ηνλ ππξήλα είλαη εληειώο δηαθνξεηηθό από απηό ησλ ζπζθεπώλ ραξαθηήξα: ν ππξήλαο ρξεζηκνπνηεί ηνλ νδεγό γηα λα πξαγκαηνπνηήζεη δύν θύξηεο ιεηηνπξγίεο: ηε ιεηηνπξγία «δηάβαζε ην κπινθ κε αξηζκό n θαη γξάςε ηα δεδνκέλα ηνπ ζηε ζέζε κλήκεο buf» θαη ηε ιεηηνπξγία «πάξε ηα δεδνκέλα πνπ βξίζθνληαη ζηε ζέζε κλήκεο buf θαη γξάςε ηα ζην κπινθ n». Ωο ζπζθεπέο κπινθ κνληεινπνηνύληαη ζπλήζσο ζθιεξνί δίζθνη ATA/SATA/SCSI θαη κνλάδεο CD/DVD- ROM/DVD-RW. Σπζθεπέο δηθηύνπ: Ωο ζπζθεπέο δηθηύνπ κνληεινπνηνύληαη πεξηθεξεηαθά ηα νπνία κπνξνύλ λα ζηείινπλ θαη λα ιάβνπλ παθέηα δεδνκέλσλ από θαη πξνο άιια ππνινγηζηηθά ζπζηήκαηα. Η θαηεγνξία απηή πεξηιακβάλεη πξαγκαηηθέο, θπζηθέο, θάξηεο δηθηύνπ (π.ρ. eth0, eth1 γηα ηνλ πξώην θαη δεύηεξν πξνζαξκνγέα δηθηύνπ Ethernet) αιιά θαη εηθνληθνύο πξνζαξκνγείο δηθηύνπ, όπσο ηνπο lo θαη ppp0 πνπ ρξεζηκνπνηνύληαη γηα παθέηα πνπ ην κεράλεκα ζηέιλεη ζηνλ εαπηό ηνπ θαη γηα παθέηα πνπ αληαιιάζζνληαη πάλσ από ζεηξηαθέο γξακκέο κέζσ ηνπ πξσηνθόιινπ PPP, αληίζηνηρα. - 7 -
3.3. Πξόζβαζε ζε ζπζθεπέο κέζω εηδηθώλ αξρείωλ Οη δύν πξώηεο θαηεγνξίεο ηεο πξνεγνύκελεο παξαγξάθνπ, νη ζπζθεπέο ραξαθηήξσλ θαη νη ζπζθεπέο κπινθ δειαδή, είλαη πξνζβάζηκεο από πξνγξάκκαηα ρξήζηε απεπζείαο, κέζσ εηδηθώλ αξρείσλ («θόκβσλ») ζην ζύζηεκα αξρείσλ (βι. θαη [1], ζει. 43). Όπσο δειαδή κηα εθαξκνγή κπνξεί λα αλνίμεη ην αξρείν /home/users/file1 γηα αλάγλσζε θαη εγγξαθή, νπόηε ηα δεδνκέλα αληαιιάζζνληαη κε ην ζύζηεκα αξρείσλ, έηζη κπνξεί λα αλνίμεη θαη κηα ζεηξά από εηδηθά αξρεία, ώζηε λα ρξεζηκνπνηήζεη κηα ζπζθεπή ραξαθηήξσλ ή κηα ζπζθεπή κπινθ απεπζείαο. Σα εηδηθά απηά αξρεία δελ πεξηέρνπλ δειαδή δεδνκέλα πνπ απνζεθεύνληαη ζην ζύζηεκα αξρείσλ, αιιά απνηεινύλ πύιεο πξόζβαζεο ζε ζπζθεπέο ηνπ ζπζηήκαηνο, κέζσ ησλ θαζηεξσκέλσλ θιήζεσλ ζπζηήκαηνο open(), read(), write(), close() θιπ. Λόγσ ηεο εηδηθήο ηνπο ζεκαζίαο βξίζθνληαη ζπλήζσο απνζεθεπκέλα κε θαηάιιεια νλόκαηα θάησ από ηνλ θαηάινγν /dev. Απηό πνπ ηα θάλεη εηδηθά σζηόζν δελ είλαη νύηε ε ζέζε ηνπο, νύηε ην όλνκά ηνπο, παξόιν πνπ ζπλήζσο απηό αθνινπζεί ζπγθεθξηκέλε ζύκβαζε ώζηε λα μέξνπλ νη εθαξκνγέο πνύ κπνξνύλ λα ηα βξνπλ. Αλ έρεηε εγθαηεζηεκέλν έλα ζύζηεκα Linux, ηώξα είλαη κηα θαιή ώξα λα δείηε ηα πεξηερόκελα ηνπ θαηαιόγνπ /dev: 2 $ ls l /dev crw-rw---- 1 root audio 14, 3 2008-05-21 20:53 /dev/dsp crw-rw-rw- 1 root root 1, 3 2008-05-21 20:52 /dev/null crw-rw-rw- 1 root root 1, 8 2008-05-21 20:52 /dev/random crw------- 1 root root 4, 1 2008-05-21 22:42 /dev/tty1 crw-rw---- 1 root dialout 4, 64 2008-05-21 20:52 /dev/ttys0 crw-rw---- 1 root dialout 4, 65 2008-05-21 20:52 /dev/ttys1 πολλέσ ανάλογεσ εγγραφέσ brw-rw---- 1 root disk 8, 0 2008-05-21 20:53 /dev/sda brw-rw---- 1 root disk 8, 1 2008-05-21 20:53 /dev/sda1 brw-rw---- 1 root disk 8, 2 2008-05-21 20:53 /dev/sda2 brw-rw---- 1 root disk 8, 16 2008-05-21 20:53 /dev/sdb brw-rw---- 1 root disk 8, 17 2008-05-21 20:53 /dev/sdb1 Χακειώζηε ηελ έληαζε ησλ ερείσλ ζην ειάρηζην θαη δνθηκάζηε λα δώζεηε κηα εληνιή όπσο απηή: $ cat /vmlinuz >/dev/dsp ^C γηα λα αθνύζεηε ην απνηέιεζκα ηνπ λα γξάθεηε ζην εηδηθό αξρείν ηεο θάξηαο ήρνπ ηπραία δείγκαηα από έλα αξρείν, ζηε ζπγθεθξηκέλε πεξίπησζε ηνλ θώδηθα ηνπ 2 Με έληνλα γξάκκαηα εκθαλίδνληαη νη ραξαθηήξεο πνπ πιεθηξνινγεί ν ρξήζηεο. Πξνηείλεηαη λα πεηξακαηηζηείηε κε ηηο εληνιέο πνπ πεξηγξάθνληαη θαη ζην δηθό ζαο ζύζηεκα. - 8 -
ππξήλα πνπ ηξέρεηε (αξρείν /vmlinuz). εθηέιεζή ηεο. Με Ctrl-C κπνξείηε λα δηαθόςεηε ηελ Η πξώηε ζηήιε ηνπ θαηαιόγνπ ηεο ls πεξηέρεη ην γξάκκα c αλ πξόθεηηαη γηα θόκβνπο πνπ αληηζηνηρνύλ ζε ζπζθεπέο ραξαθηήξσλ ή ην γξάκκα b αλ πξόθεηηαη γηα θόκβνπο πνπ αληηζηνηρνύλ ζε ζπζθεπέο κπινθ. Γηα παξάδεηγκα, ην αξρείν ttys0 αληηζηνηρεί ζηελ πξώηε ζεηξηαθή ζύξα ηνπ ζπζηήκαηνο, ελώ ην αξρείν /dev/sdb ζην δεύηεξν δίζθν SCSI. ε αληίζεζε κε ό,ηη ζπκβαίλεη γηα ζπλεζηζκέλα αξρεία, γηα απηά ηα αξρεία (ηνπο θόκβνπο ζπζθεπώλ, device nodes) ε ls δελ εκθαλίδεη κέγεζνο, θαζώο δελ αληηζηνηρνύλ ζε απνζεθεπκέλα δεδνκέλα. Αληίζεηα, εκθαλίδεη δύν αξηζκνύο, ρσξηζκέλνπο κε θόκκα. Οη αξηζκνί απηνί θαη όρη ην όλνκα ηνπ αξρείνπ, θαζνξίδνπλ πνηα ζπζθεπή αθνξά θάζε θόκβνο θαη νλνκάδνληαη major θαη minor number αληίζηνηρα. Ο major number ρξεζηκνπνηείηαη από ηνλ ππξήλα γηα λα πξνζδηνξίζεη ηνλ νδεγό ζπζθεπήο πνπ αθνξά ν ζπγθεθξηκέλνο θόκβνο. Γηα παξάδεηγκα, όινη νη δίζθνη SCSI αληηζηνηρνύλ ζηνλ ίδην major number, ηνλ 8. O minor number δελ αθνξά ηνλ θώδηθα ηνπ ππξήλα αιιά ηνλ ίδην ηνλ νδεγό ηεο ζπζθεπήο θαη ρξεζηκνπνηείηαη ώζηε λα κπνξεί λα δηαθξίλεη πνηα ζπγθεθξηκέλε ζπζθεπή από όιεο όζεο κπνξεί λα ρεηξηζηεί αθνξά ην ζπγθεθξηκέλν αξρείν. Έηζη, παξόιν πνπ θαη ην /dev/sda θαη ην /dev/sdb αληηζηνηρνύλ ζηνλ ίδην νδεγό, ηνλ νδεγό ζθιεξώλ δίζθσλ SCSI, ην sda έρεη minor 0 θαη αλαθέξεηαη ζηνλ πξώην δίζθν, ελώ ην sdb έρεη minor 16 θαη αλαθέξεηαη ζηνλ δεύηεξν. Όπσο θαη νη ππόινηπνη νδεγνί, έηζη θαη ην Lunix:TNG ζα ρξεζηκνπνηήζεη έλα ζπγθεθξηκέλν major number. Ωζηόζν, ε επηινγή δελ κπνξεί λα γίλεη απζαίξεηα, εθόζνλ πνιινί ρξεζηκνπνηνύληαη ήδε. ην αξρείν Documentation/devices.txt ζηνλ θώδηθα ηνπ ππξήλα, θάησ από ηνλ θαηάινγν /usr/src/linux, ππάξρεη κηα ιίζηα κε ηελ ηξέρνπζα αληηζηνηρία. Οξηζκέλνη αξηζκνί είλαη δεζκεπκέλνη γηα πεηξακαηηθή ρξήζε, όπσο ν 60, ηνλ νπνίν πξνηείλεηαη λα ρξεζηκνπνηήζεηε. Οη αξηζκνί πνπ ρξεζηκνπνηνύληαη θάζε ζηηγκή από ηνλ ππξήλα θαίλνληαη κε ρξήζε ηεο εληνιήο cat /proc/devices. Σα εηδηθά αξρεία θαηαζθεπάδνληαη κε ρξήζε ηεο εληνιήο mknod, νπόηε θαζνξίδεηαη ην είδνο ηνπο (character ή block node) θαη νη major/minor numbers πνπ ηνπο αληηζηνηρνύλ. Σν Lunix:TNG ζα ρξεζηκνπνηεί πεξηζζόηεξα ηνπ ελόο εηδηθά αξρεία, έλα γηα θάζε αηζζεηήξα ηνπ δηθηύνπ θαη είδνο κέηξεζεο πνπ ππνζηεξίδεηαη. ε θάζε δεύγνο {αξηζκόο αηζζεηήξα, κέηξεζε} ρξεηάδεηαη λα αλαηεζεί ζπγθεθξηκέλν όλνκα αξρείνπ θαη αληίζηνηρνο minor number. Πξνηείλεηαη ηα 3 ιηγόηεξν ζεκαληηθά bits θάζε minor number λα θαζνξίδνπλ ην είδνο ηεο κέηξεζεο [νη κεηξήζεηο αξηζκνύληαη κε ηε ζεηξά «ηάζε κπαηαξίαο = 0, ζεξκνθξαζία, θσηεηλόηεηα» θαη ππάξρεη ρώξνο γηα ην πνιύ 8 κεηξήζεηο αλά αηζζεηήξα], ελώ ηα ππόινηπα ηνλ αξηζκό ηνπ αηζζεηήξα. Έηζη ε ηηκή ηνπ minor number πξνθύπηεη σο minor = αιςθητήρασ * 8 + μέτρηςη. - 9 -
Σν αξρείν /dev/lunix0-batt πνπ αληηζηνηρεί ζηελ ηάζε ηεο κπαηαξίαο ηνπ πξώηνπ αηζζεηήξα θηηάρλεηαη κε ηελ εληνιή: # mknod /dev/lunix0-batt c 60 0 Δλώ ην αξρείν /dev/lunix1-temp πνπ αληηζηνηρεί ζηε ζεξκνθξαζία ηνπ δεύηεξνπ ζα είρε minor number 9. αο δίλεηαη ην script lunix_dev_nodes.sh, ην νπνίν θαηαζθεπάδεη απηόκαηα ηνπο αλάινγνπο θόκβνπο κε βάζε απηή ηε ζύκβαζε, γηα 16 αηζζεηήξεο. 4. Πεξηζζόηεξα γηα ηελ εξγαζηεξηαθή άζθεζε 4.1. Αξρηηεθηνληθή ζπζηήκαηνο αζύξκαηνπ δηθηύνπ αηζζεηήξωλ Αληηθείκελν ηεο εξγαζηεξηαθήο άζθεζεο είλαη ε πινπνίεζε ελόο νδεγνύ ζπζθεπήο γηα έλα αζύξκαην δίθηπν αηζζεηήξσλ θάησ από ην ιεηηνπξγηθό ζύζηεκα Linux. Σν αζύξκαην δίθηπν κε ην νπνίν ζα εξγαζηείηε δηαζέηεη έλαλ αξηζκό από αηζζεηήξεο (αζύξκαηεο θάξηεο Crossbow MPR2400CA κε αηζζεηήξεο ηάζεο, ζεξκνθξαζίαο θαη θσηεηλόηεηαο MDA100CB) θαη έλα ζηαζκό βάζεο (θάξηα MPR2400CA θαη δηαζύλδεζε USB MIB520CB). Ο ζηαζκόο βάζεο ζπλδέεηαη κέζσ USB κε ππνινγηζηηθό ζύζηεκα Linux ζην νπνίν θαη ζα εθηειείηαη ν δεηνύκελνο νδεγόο ζπζθεπήο. sensor2 sensor0 Wireless Mesh sensor1 Serial over USB Base Station Driver running on Linux PC ρήκα 2: Αξρηηεθηνληθή ηνπ ππό εμέηαζε ζπζηήκαηνο Οη αηζζεηήξεο αλαθέξνπλ πεξηνδηθά ην απνηέιεζκα ηξηώλ δηαθνξεηηθώλ κεηξήζεσλ: ηεο ηάζεο ηεο κπαηαξίαο πνπ ηνπο ηξνθνδνηεί, ηεο ζεξκνθξαζίαο θαη ηεο θσηεηλόηεηαο ηνπ ρώξνπ όπνπ βξίζθνληαη. Οη αηζζεηήξεο νξγαλώλνληαη ζε έλα πιέγκα (mesh), έηζη ώζηε ηα δεδνκέλα ηνπο λα κεηαθέξνληαη από ελαιιαθηηθέο δηαδξνκέο θαη ην δίθηπν λα πξνζαξκόδεηαη απηόκαηα ζηελ πεξίπησζε όπνπ έλαο νη πεξηζζόηεξνη αηζζεηήξεο είλαη εθηόο ηεο εκβέιεηαο ηνπ ζηαζκνύ βάζεο (ρήκα 2). Απηό δελ ρξεηάδεηαη λα ζαο απαζρνιήζεη, νη αιγόξηζκνη πνπ ρξεηάδνληαη έρνπλ ήδε πινπνηεζεί ζε θαηάιιειν ελζσκαησκέλν ινγηζκηθό πνπ εθηειείηαη από ηνπο ίδηνπο ηνπο αηζζεηήξεο θαη ηνπο επηηξέπεη λα αλαθαιύπηνπλ ν έλαο ηνλ άιιν. - 10 -
Ο ζηαζκόο βάζεο ιακβάλεη παθέηα κε δεδνκέλα κεηξήζεσλ, ηα νπνία πξνσζεί κέζσ δηαζύλδεζεο USB ζην ππνινγηζηηθό ζύζηεκα. Η δηαζύλδεζε πινπνηείηαη κε θύθισκα Serial over USB, κε ην ηζηπ FTDI FT2232C γηα ην νπνίν ν ππξήλαο δηαζέηεη ελζσκαησκέλνπο νδεγνύο. ηελ πεξίπησζε απηή (ε pre-existing approach ζην ρήκα 3), δε γίλεηαη θακία δηάθξηζε αλάκεζα ζηα δηαθνξεηηθά παθέηα δεδνκέλσλ: ηα δεδνκέλα όισλ ησλ κεηξήζεσλ όισλ ησλ αηζζεηήξσλ εκθαλίδνληαη ζε κία εηθνληθή ζεηξηαθή ζύξα, /dev/ttyusb1. Δπηπιένλ, δελ ππνζηεξίδεηαη ηαπηόρξνλε πξόζβαζε από πνιιέο δηαθνξεηηθέο δηεξγαζίεο κόλν κία έρεη λόεκα λα αλνίγεη θάζε θνξά ηελ εηθνληθή ζεηξηαθή ζύξα. Υξεηάδεηαη ινηπόλ ε αλάπηπμε ελόο νδεγνύ ζπζθεπήο ν νπνίνο λα πξνζθέξεη θαηάιιειν κεραληζκό, αληηκεησπίδνληαο αλεμάξηεηα ηνπο αηζζεηήξεο θαη ηα κεηξνύκελα κεγέζε, επηηξέπνληαο ηαπηόρξνλε πξόζβαζε ζηα εηζεξρόκελα δεδνκέλα θαη θάλνληαο δπλαηή ηελ επηβνιή δηαθνξεηηθήο πνιηηηθήο από ην δηαρεηξηζηή ηνπ ζπζηήκαηνο όζνλ αθνξά ηελ πξόζβαζε ζε απηά. 4.2. Λεηηνπξγηθέο απαηηήζεηο νδεγνύ ζπζθεπήο Ο δεηνύκελνο νδεγόο ζπζθεπήο ρξεηάδεηαη λα πξνζθέξεη ηε δπλαηόηεηα ρσξηζηήο πξόζβαζεο αλά αηζζεηήξα θαη κεηξνύκελν κέγεζνο κέζσ δηαθνξεηηθώλ εηδηθώλ αξρείσλ. Σν πιήζνο ησλ απαηηνύκελσλ αξρείσλ ζα είλαη ίζν κε ηνλ αξηζκό ησλ ππνζηεξηδόκελσλ αηζζεηήξσλ επί ηνλ αξηζκό ησλ ππνζηεξηδόκελσλ κεηξήζεσλ, πνπ είλαη ηξεηο: ηάζε κπαηαξίαο, ζεξκνθξαζία, θσηεηλόηεηα. Κάζε δεύγνο {αξηζκόο κεηξεηή, κέηξεζε} ζα αληηζηνηρηζηεί ζε δηαθνξεηηθό εηδηθό αξρείν, κε δηαθνξεηηθό minor number, όπσο πεξηγξάθεηαη ζηελ 3.3. Η πξώηε πξνζπάζεηα αλάγλσζεο από εηδηθό αξρείν ζα επηζηξέθεη έλαλ αξηζκό από bytes πνπ ζα αλαπαξηζηνύλ ηελ πην πξόζθαηε ηηκή ηνπ κεηξνύκελνπ κεγέζνπο, ζε αλαγλώζηκε κνξθή, κνξθνπνηεκέλε σο δεθαδηθό αξηζκό. Αλ δελ έρνπλ αθόκε παξαιεθζεί δεδνκέλα γηα ηε ζπγθεθξηκέλε κέηξεζε, ή αλ γίλνπλ επόκελεο πξνζπάζεηεο αλάγλσζεο, ν νδεγόο ζα πξέπεη λα θνηκίδεη ηε δηεξγαζία (βι. 7.3) έσο όηνπ παξαιεθζνύλ λέα δεδνκέλα. Έηζη, απηή δελ ζα θαηαλαιώλεη ρξόλν ζηελ CPU ηνπ ζπζηήκαηνο. Οξίζηε έλα παξάδεηγκα ρξήζεο ηνπ ζπζηήκαηνο, κε ζρνιηαζκό: Ο απιόο ρξήζηεο user, αθνύ θάλεη login κεηαγισηηίδεη ηνλ θώδηθα ηνπ module δίλνληαο ηελ εληνιή make: - 11 -
[αλ ν πεγαίνο θώδηθαο ηνπ ππξήλα γηα ηνλ νπνίν γίλεηαη ε κεηαγιώηηηζε είλαη ζε αζπλήζηζηε ζέζε, ρξεηάδεηαη λα ηεζεί ε κεηαβιεηή πεξηβάιινληνο KERNELDIR] user@machine:~/lunix-tng$ export KERNELDIR=~/utopia/linux-2.6.37.4 user@machine:~/lunix-tng$ make gcc -Wall -Werror -m32 -o mk_lookup_tables mk_lookup_tables.c -lm./mk_lookup_tables >lunix-lookup.h make -C /home/user/utopia/linux-2.6.37.4 M=/home/user/lunix-tng modules make[1]: Entering directory `/home/user/utopia/linux-2.6.37.4' CC [M] /home/user/lunix-tng/lunix-module.o CC [M] /home/user/lunix-tng/lunix-chrdev.o CC [M] /home/user/lunix-tng/lunix-ldisc.o CC [M] /home/user/lunix-tng/lunix-protocol.o CC [M] /home/user/lunix-tng/lunix-sensors.o LD [M] /home/user/lunix-tng/lunix.o Building modules, stage 2. MODPOST 1 modules CC /home/user/lunix-tng/lunix.mod.o LD [M] /home/user/lunix-tng/lunix.ko make[1]: Leaving directory `/home/user/utopia/linux-2.6.37.4' gcc -Wall -Werror -o lunix-attach lunix-attach.c ηε ζπλέρεηα, απνθηά δηθαηώκαηα δηαρεηξηζηή (su), γηα λα θνξηώζεη ην module (insmod), λα δεκηνπξγήζεη κηα ζεηξά από εηδηθά αξρεία ηεο ζπζθεπήο (lunix_dev_nodes.sh) θαη λα ελεξγνπνηήζεη ηελ είζνδν δεδνκέλσλ από ηε ζεηξηαθή ζύξα USB /dev/ttyusb1 (lunix-attach): user@machine:~/lunix-tng$ su Password: machine:~# cd ~user/lunix-tng machine:/home/user/lunix-tng# insmod./lunix.ko machine:/home/user/lunix-tng#./lunix_dev_nodes.sh machine:/home/user/lunix-tng#./lunix-attach /dev/ttyusb1 tty_open: looking for lock tty_open: trying to open /dev/ttyusb1 tty_open: /dev/ttyusb1 (fd=3) Line discipline set on /dev/ttyusb1, press ^C to release the TTY... Σέινο, δεηά ηε ζεξκνθξαζία ηνπ 3νπ αηζζεηήξα. user@utopia:~$ cat /dev/lunix2-temp [αλ ν αηζζεηήξαο είλαη θιεηζηόο, εδώ ε cat θαίλεηαη λα έρεη θνιιήζεη] 27.791 [κηθξή παύζε αλάκεζα ζε θάζε γξακκή, αλάινγα κε ηε ζπρλόηεηα αλαλέωζεο ηωλ δεδνκέλωλ] 27.791 27.693 27.791 ^C - 12 -
4.3. Πξνηεηλόκελε αξρηηεθηνληθή νδεγνύ ζπζθεπήο Η πξνηεηλόκελε αξρηηεθηνληθή ηνπ ππό ζρεδίαζε ζπζηήκαηνο παξνπζηάδεηαη ζην αθόινπζν ζρήκα. Σν παξαθάησ απνηειεί κηα πιήξε πεξηγξαθή ηεο αξρηηεθηνληθήο ηνπ θαη ζπκπεξηιακβάλεη ηόζν ηα ηκήκαηα πνπ ζαο δίλνληαη ήδε πινπνηεκέλα όζν θαη ην ηκήκα πνπ ζα πξέπεη εζείο λα θαηαζθεπάζεηε (ηα ηκήκαηα (g) θαη (h) ηνπ παξαθάησ ζρήκαηνο). Η πεξηγξαθή γίλεηαη κε ζθνπό ηελ επθνιόηεξε αλάγλσζε ηνπ θώδηθα πνπ ζαο δίλεηαη θαη ηελ θαιύηεξε θαηαλόεζε ηνπ πιαηζίνπ ζην νπνίν ζα εληαρζεί ε δνπιεηά ζαο. Pre-existing approach User Application /dev/ttyusb1 /dev/lunix0-batt, /dev/lunix1-temp /dev/lunix2-light System Calls User TTY Core layer Standard line discipline Lunix line discipline c d Lunix character device driver h Lunix sensor buffers g f Serial over USB driver Lunix protocol e Kernel b Hardware Wireless network base station a ρήκα 3: Αξρηηεθηνληθή ινγηζκηθνύ ηνπ ππό εμέηαζε ζπζηήκαηνο Σν ζύζηεκα νξγαλώλεηαη ζε δύν θύξηα κέξε: Σν πξώην (ηκήκαηα (c), (d), (e) ηνπ ζρήκαηνο) αλαιακβάλεη ηε ζπιινγή ησλ δεδνκέλσλ από ην ζηαζκό βάζεο θαη ηελ επεμεξγαζία ηνπο κε ζπγθεθξηκέλν πξσηόθνιιν, έηζη ώζηε λα εμαρζνύλ νη ηηκέο ησλ κεηξνύκελσλ κεγεζώλ, νη νπνίεο θαη θξαηνύληαη ζε θαηάιιειεο δνκέο πξνζσξηλήο απνζήθεπζεο (buffers) ζηε κλήκε (ηκήκα (f)). Σν δεύηεξν (ηκήκαηα (g), (h)), αλαιακβάλεη ηελ εμαγωγή ησλ δεδνκέλσλ ζην ρώξν ρξήζηε, πινπνηώληαο κηα ζεηξά από ζπζθεπέο ραξαθηήξσλ. Σα δεδνκέλα πξνέξρνληαη από αλάγλσζε ησλ ρώξσλ ελδηάκεζεο απνζήθεπζεο. Σν ηειηθό ζύζηεκα ζα ιεηηνπξγεί σο εμήο: Σα δεδνκέλα ησλ κεηξήζεσλ αθνύ (a) ιακβάλνληαη από ην ζηαζκό βάζεο (b) ζα πξνσζνύληαη κέζσ USB ζην ππνινγηζηηθό ζύζηεκα. ηε ζπλέρεηα όκσο δελ ζα αθνινπζνύλ ηε ζπλήζε πνξεία ηνπο, πξνο ην /dev/ttyusb1 αιιά (c) ζα παξαιακβάλνληαη από έλα θίιηξν, ηε δηάηαμε γξακκήο - 13 -
(line discipline) ηνπ Lunix, ε νπνία (d) ζα ηα πξνσζεί ζε θαηάιιειν ζηξώκα εξκελείαο ηνπ πξσηνθόιινπ ησλ αηζζεηήξσλ (e). Σν ηκήκα απηό εξκελεύεη ην πεξηερόκελν ησλ παθέησλ θαη απνζεθεύεη ηα δεδνκέλα ησλ κεηξήζεσλ ζε δηαθνξεηηθνύο buffers αλά αηζζεηήξα (f). Η δεηνύκελε ζπζθεπή ραξαθηήξσλ (g), αλαιόγσο κε ην πνην εηδηθό αξρείν ρξεζηκνπνηεί ε εθαξκνγή ρξήζηε, ζα επηηξέπεη ηελ αλάθηεζε (h) από ηνπο buffers ησλ δεδνκέλσλ πνπ αληηζηνηρνύλ ζε θάζε πεξίπησζε. Η πινπνίεζε ησλ ηκεκάησλ (b), (c), (d), (e), (f) ζαο δίλεηαη έηνηκε, σο ηκήκαηα θώδηθα καδί κε ηηο θαηάιιειεο δνκέο δεδνκέλσλ πνπ νξίδνπλ ηηο δηεπαθέο (interfaces) αλάκεζά ηνπο. Από εζάο δεηείηαη ε πινπνίεζε ηνπ (g) θαη ν έιεγρνο (h) ηεο ζσζηήο ιεηηνπξγίαο ηνπ ζπζηήκαηνο, κέζσ ελόο πξνγξάκκαηνο ρξήζηε. ηε ζπλέρεηα αλαιύεηαη ν ξόινο θαζελόο από ηα παξαπάλσ ηκήκαηα ηνπ ινγηζκηθνύ θαη ν ηξόπνο αιιειεπίδξαζήο ηνπ κε ηα ππόινηπα. 5. Σκήκα εμαγωγήο δεδνκέλωλ ζην ρώξν ρξήζηε 5.1. Interface ζπζθεπώλ ραξαθηήξωλ Όπσο είπακε θαη πξνεγνύκελα, ην Linux παξνπζηάδεη ζρεδόλ όιεο ηηο ζπζθεπέο σο αξρεία. Σα εηδηθά αξρεία ζπζθεπώλ, κέζσ ηνπ νπνίνπ είλαη δπλαηή ε αιιειεπίδξαζε κε ζπζθεπέο Δ/Δ απνηεινύλ θαη απηά κέξνο ηνπ ζπζηήκαηνο αξρείσλ (filesystem), όπσο θαη ηα αξρεία δεδνκέλσλ. Ο νδεγόο ζπζθεπήο κνηάδεη κε έλα θαλνληθό αξρείν ην νπνίν κπνξείηε λα αλνίμεηε (open()), θιείζεηε (close()), δηαβάζεηε (read()) θαη λα γξάςεηε (write()). Ο ππξήλαο βιέπεη απηέο ηηο ιεηηνπξγίεο σο εηδηθέο αηηήζεηο θαη ηηο κεηαθξάδεη ζε θιήζεηο πξνο ηνλ αληίζηνηρν νδεγό ζπζθεπήο. ηελ πεξίπησζε ησλ ζπζθεπώλ ραξαθηήξσλ (όρη όκσο θαη ησλ ζπζθεπώλ κπινθ, όπνπ ην interface είλαη εληειώο δηαθνξεηηθό), ππάξρεη ζρεδόλ 1-1 αληηζηνηρία αλάκεζα ζε θιήζεηο ζπζηήκαηνο θαη θιήζεηο πξνο ηνλ νδεγό ζπζθεπήο. Όηαλ γηα παξάδεηγκα αλνίμνπκε (open()) έλα εηδηθό αξρείν, ν ππξήλαο ςάρλεη ηελ αληίζηνηρε ζπλάξηεζε ζηνλ θώδηθα ηνπ νδεγνύ θαη ηελ εθηειεί. Όκσο πώο θαηαθέξλεη θαη βξίζθεη ηελ θαηάιιειε ζπλάξηεζε γηα θάζε ζπζθεπή; Σν θαηαθέξλεη, δηόηη θάζε νδεγόο γηα ζπζθεπή ραξαθηήξσλ πινπνηεί κηα ζπγθεθξηκέλε δηεπαθή (interface) πξνο ηνλ ππξήλα. Σν interface απηό πεξηγξάθεηαη ζηε ζπλέρεηα. Όινη νη νδεγνί παξέρνπλ έλα ζύλνιν από ξνπηίλεο. Κάζε νδεγόο παξέρεη κηα δνκή struct file_operations πνπ πεξηέρεη δείθηεο ζηηο ξνπηίλεο απηέο. Καηά ηελ αξρηθνπνίεζε ηνπ νδεγνύ, απηή ε δνκή "αγθηζηξώλεηαη" ζε έλα πίλαθα πνπ γλσξίδεη ν ππξήλαο. Κάζε θνξά πνπ γίλεηαη αίηεζε γηα άλνηγκα ελόο εηδηθνύ αξρείνπ, ν αξηζκόο major ηνπ αξρείνπ ρξεζηκνπνηείηαη από ηνλ ππξήλα σο δείθηεο ζε απηόλ ηνλ πίλαθα, ώζηε λα εληνπίζεη ηνλ θαηάιιειν νδεγό ζπζθεπήο θαη ηελ αλάινγε δνκή file_operations. - 14 -
Δθηόο από ηε δνκή file_operations, πνιύ ζεκαληηθό ξόιν ζηελ αιιειεπίδξαζε ηνπ νδεγνύ ζπζθεπήο κε ηνλ ππξήλα παίδεη θαη ε δνκή struct file. Η δνκή απηή αλαπαξηζηά θάπνην αλνηρηό αξρείν κηαο δηεξγαζίαο κέζα ζηνλ θώδηθα ηνπ ππξήλα. Ο ππξήλαο δεκηνπξγεί κηα λέα δνκή file θάζε θνξά πνπ κηα δηεξγαζία εθηειεί ηελ θιήζε ζπζηήκαηνο open() γηα λα αλνίμεη θάπνην αξρείν. Μηα δνκή file δεκηνπξγείηαη θαη όηαλ κηα δηεξγαζία αλνίμεη εηδηθό αξρείν πνπ αλαθέξεηαη ζην Lunix:TNG. Η δνκή απηή αληηζηνηρίδεηαη, κέζσ ελόο δείθηε, κε ηε δνκή file_operations πνπ έρεη δειώζεη ν νδεγόο ζπζθεπήο ζηνλ ππξήλα. Έηζη, θάζε θνξά πνπ ε δηεξγαζία δεηά ηελ εθηέιεζε κηαο θιήζεο ζπζηήκαηνο επάλσ ζην αλνηρηό αξρείν (π.ρ. ηεο read() γηα ηελ αλάγλσζε δεδνκέλσλ), ν ππξήλαο βξίζθεη ηε δνκή file πνπ αληηζηνηρεί ζην αλνηρηό αξρείν, αθνινπζεί ην ζύλδεζκν πξνο ηε δνκή file_operations ηνπ νδεγνύ ζπζθεπήο, αθνινπζεί ην δείθηε ηεο δνκήο πνπ αλαθέξεηαη ζηε ιεηηνπξγία read θαη θηάλεη έηζη ζηελ ξνπηίλα ηνπ νδεγνύ ζπζθεπήο, ηελ νπνία θαη εθηειεί. Η παξαπάλσ δηαδηθαζία ζα γίλεη πεξηζζόηεξν θαηαλνεηή όηαλ παξνπζηαζηνύλ ηα πεδία ησλ δνκώλ file_operations θαη file. 5.2. Λεηηνπξγίεο αξρείνπ - Ζ δνκή file_operations ηε ζπλέρεηα παξνπζηάδνληαη ηα πεδία ηεο δνκήο file_operations (βι. θαη [1], ζει. 49) Κάζε πεδίν ηεο δνκήο απηήο αληηζηνηρεί ζε κία ιεηηνπξγία πνπ αλαιακβάλεη λα επηηειέζεη ν νδεγόο ζπζθεπήο πνπ πινπνηνύκε, όηαλ ηνπ δεηεζεί από άιια ηκήκαηα ηνπ ππξήλα. Η ζπζθεπή αλαγλσξίδεηαη εζσηεξηθά ζηνλ ππξήλα κέζσ ηεο δνκήο file πνπ πξνθύπηεη από άλνηγκα ελόο εηδηθνύ αξρείνπ, π.ρ. ηνπ /dev/sensor1-light από θάπνηα δηεξγαζία. Σν εηδηθό αξρείν έρεη θαηαζθεπαζηεί εθ ησλ πξνηέξσλ, όπσο αλαιύεηαη ζηελ 3.3. Σα πεδία ηεο δνκήο file_operations νλνκάδνληαη ζπρλά θαη «κέζνδνη» ηεο ζπζθεπήο, ζύκθσλα κε ηελ νξνινγία ηνπ αληηθεηκελνζηξεθνύο πξνγξακκαηηζκνύ, ζεσξώληαο όηη ν ππξήλαο δεηά από ηνλ νδεγό ζπζθεπήο ηελ εθηέιεζε κηαο ιεηηνπξγίαο θαιώληαο ηελ αληίζηνηρε κέζνδν ηνπ αληηθεηκέλνπ «αλνηρηό αξρείν». H δνκή file_operations απνηειείηαη από δείθηεο ζε ζπλαξηήζεηο θαη νξίδεηαη ζην <linux/fs.h>. ηε ζπλέρεηα παξνπζηάδνληαη πεξηιεπηηθά ηα ζεκαληηθόηεξα από ηα πεδία ηεο. Αλ ν νδεγόο ζπζθεπήο δελ ππνζηεξίδεη ηε ζπγθεθξηκέλε ιεηηνπξγία θαη δελ παξέρεη ξνπηίλα πνπ ηελ πινπνηεί, ν δείθηεο ηεο δνκήο file_operations είλαη NULL θαη ε ζπκπεξηθνξά ηνπ ππξήλα εμαξηάηαη από ην είδνο ηεο ιεηηνπξγίαο πνπ δελ παξέρεηαη. Η εθηέιεζε κηαο ζπλάξηεζεο ζεσξείηαη επηηπρήο όηαλ ε επηζηξεθόκελε ηηκή είλαη κεδέλ, ελώ αξλεηηθή επηζηξεθόκελε ηηκή ππνδειώλεη θάπνην ζθάικα. Μπνξεί λα επηζηξαθεί θαη ζεηηθόο αξηζκόο κεξηθέο θνξέο, νπόηε ζα επηζεκαίλεηαη ζηελ πεξηγξαθή ηεο ιεηηνπξγίαο. - 15 -
loff_t llseek (struct file *, loff_t, int); Η κέζνδνο llseek() ρξεζηκνπνηείηαη γηα λα αιιάμνπκε ηελ ζέζε αλάγλσζεο / εγγξαθήο ζε έλα αξρείν θαη ε λέα ηηκή επηζηξέθεηαη σο κηα ζεηηθή ηηκή. Σα ιάζε ζεκαηνδνηνύληαη από αξλεηηθή ηηκή. Αλ ε ζπλάξηεζε δελ νξίδεηαη ζηνλ νδεγό (ππάξρεη NULL ζηελ αλάινγε ζέζε ζηε δνκή struct file_operations), ν ππξήλαο πξνζθέξεη κηα πξνθαζνξηζκέλε (default) πινπνίεζε ηεο llseek(), ζύκθσλα κε ηελ νπνία νη ιεηηνπξγίεο seek σο πξνο ην ηέινο ηνπ αξρείνπ απνηπγράλνπλ, δηαθνξεηηθά επηηπγράλνπλ αιιάδνληαο ηνλ κεηξεηή ζέζεο ζηε δνκή file. ssize_t read(struct file *, char user *, size_t, loff_t *); Υξεζηκνπνηείηαη γηα λα δηαβάδεη δεδνκέλα από ηε ζπζθεπή. Αλ ν νδεγόο ζπζθεπήο δελ ππνζηεξίδεη απηή ηε ιεηηνπξγία, νπόηε ν δείθηεο ζηε ζέζε απηή είλαη NULL, ε θιήζε ζπζηήκαηνο read() απνηπγράλεη κε ηελ ηηκή -EINVAL ( Invalid argument ). Μηα κε αξλεηηθή επηζηξεθόκελε ηηκή θαλεξώλεη ην πιήζνο ησλ bytes πνπ δηαβάζηεθαλ επηηπρώο, ελώ ε ηηκή 0 ππνδειώλεη όηη ε αλάγλσζε έθηαζε ζην ηέινο ηνπ αξρείνπ (EOF). Η κέζνδνο απηή ζα είλαη ε θαξδηά ηεο πινπνίεζήο ζαο. Υξεηάδεηαη λα ιακβάλεη δεδνκέλα από ηνπο sensor buffers, λα θξνληίδεη γηα ηε ζσζηή κνξθνπνίεζή ηνπο θαη λα ηα πεξλά ζην ρώξν ρξήζηε. Γηα ηνλ ηξόπν κε ηνλ νπνίν πινπνηείηαη θαη ηηο ζπκβάζεηο πνπ αθνινπζνύληαη, δείηε ηα αληίζηνηρα ζρόιηα ζηνλ θώδηθα πνπ ζα ζαο δνζεί θαη ηελ πινπνίεζε ηεο αληίζηνηρεο read() ηνπ scull ζην [1]. ssize_t write(struct file *, const char user *, size_t, loff_t *); ηέιλεη δεδνκέλα ζηελ ζπζθεπή. Αλ δελ παξέρεηαη από ηνλ νδεγό ζπζθεπήο, επηζηξέθεηαη -EINVAL ζην πξόγξακκα πνπ θάιεζε ηελ θιήζε ζπζηήκαηνο write(). Η επηζηξεθόκελε ηηκή, αλ δελ είλαη αξλεηηθή, θαλεξώλεη ην πιήζνο ησλ bytes πνπ γξάθηεθαλ επηηπρώο. int unlocked_ioctl(struct file *, unsigned int, unsigned long); Η θιήζε ζπζηήκαηνο ioctl() πξνζθέξεη έλα ηξόπν γηα λα δώζνπκε εηδηθέο εληνιέο γηα ηε ζπζθεπή πιηθνύ, πνπ δελ είλαη κπνξνύλ λα παξαζηαζνύλ νύηε σο αλάγλσζε νύηε σο εγγξαθή δεδνκέλσλ. Γηα παξάδεηγκα, κηα ηέηνηα εληνιή ζα ήηαλ ε κνξθνπνίεζε ηεο δηζθέηαο γηα ηε ζπζθεπή /dev/fd0, ή ε κεηαβνιή ηνπ baud rate γηα κηα ζεηξηαθή ζύξα (/dev/ttys0). Μεξηθέο εληνιέο ioctl ηθαλνπνηνύληαη άκεζα από ηνλ ππξήλα, ρσξίο λα θιεζεί ν νδεγόο ζπζθεπήο. Αλ ν νδεγόο δελ πξνζθέξεη ηελ ioctl(), ηόηε ε θιήζε ζπζηήκαηνο επηζηξέθεη -EINVAL. Μηα κε αξλεηηθή - 16 -
επηζηξεθόκελε ηηκή πεξλά ακεηάβιεηε ζηνλ θαινύληα γηα λα θαλεξώζεη ηελ επηηπρία ηεο θιήζεο. int open (struct inode *, struct file *) Αλ θαη απηή ε ζπλάξηεζε είλαη ε πξώηε πνπ θαιείηαη ζηνλ θόκβν ζπζθεπήο, ν νδεγόο ζπζθεπήο δελ ρξεηάδεηαη λα νξίζεη κηα ηέηνηα κέζνδν. ηελ πεξίπησζε απηή ην άλνηγκα ζπζθεπήο ζεσξείηαη πάληα επηηπρέο, αιιά ν νδεγόο καο δελ ελεκεξώλεηαη πνηέ. Δκείο ζα νξίδνπκε ηε ζπλάξηεζε απηή, επεηδή ζέινπκε λα ελεκεξώλεηαη ν νδεγόο καο γηα ην άλνηγκα ηεο ζπζθεπήο, ώζηε λα καο δίλεηαη ε επθαηξία λα θάλνπκε αξρηθνπνηήζεηο ζε δνκέο δεδνκέλσλ ηνπ νδεγνύ. Σν όξηζκα ηύπνπ struct inode αθνξά ζην εηδηθό αξρείν πνπ ρξεζηκνπνηήζεθε θαηά ηελ θιήζε ζπζηήκαηνο. Με ρξήζε ησλ καθξνεληνιώλ unsigned int iminor(struct inode *inode); unsigned int imajor(struct inode *inode); κπνξνύκε λα αλαθηήζνπκε ηνλ major θαη minor number ηνπ αξρείνπ, ώζηε ην αλνηρηό αξρείν πνπ ζα πξνθύςεη λα αθνξά ζπγθεθξηκέλν αηζζεηήξα θαη κέηξεζε ηνπ δηθηύνπ. ηελ πεξίπησζή πνπ εμεηάδεηε, ε open νθείιεη λα δεζκεύεη ρώξν γηα ηε δνκή ηύπνπ lunix_chrdev_state_struct πνπ πεξηγξάθεη ηελ ηξέρνπζα θαηάζηαζε ηεο ζπζθεπήο θαη λα ηε ζπλδέεη κε ηε δνκή file κέζσ ηνπ δείθηε private_data (βι. παξαθάησ). void (*release) (struct inode *, struct file *); Απηή ε κέζνδνο θαιείηαη όηαλ κηα δηεξγαζία ρξήζηε εθηειέζεη ηελ θιήζε ζπζηήκαηνο close() γηα ην θιείζηκν ηνπ αλνηρηνύ αξρείνπ ηεο ζπζθεπήο, νπόηε θαηαζηξέθεηαη ε αληίζηνηρε δνκή file. Όκνηα κε ηελ open(), δελ ρξεηάδεηαη λα νξηζηεί κέζνδνο release() θαη ζα είλαη πάληα επηηπρέο ην θιείζηκν. ηελ δηθή καο πεξίπησζε, ζα νξίδνπκε ζπλάξηεζε γηα ην δείθηε release, γηα λα ελεκεξσλόκαζηε όηαλ ην πξόγξακκα πνπ είρε αλνίμεη ηε ζπζθεπή καο θιείζεη ην αλνηρηό αξρείν θαη λα απειεπζεξώλνπκε ηνπο αληίζηνηρνπο πόξνπο (δεζκεπκέλε κλήκε). Η κνξθή ηεο δνκήο file_operations γηα ην Lunix:TNG ζα είλαη θάπσο έηζη: static struct file_operations lunix_chrdev_fops = {.owner = THIS_MODULE,.open = lunix_chrdev_open,.release = lunix_chrdev_release,.read = lunix_chrdev_read }; - 17 -
5.3. Αλνηρηά αξρεία - Ζ δνκή file Η δνκή struct file, πνπ νξίδεηαη ζην <linux/fs.h>, (βι. [1] ζει. 53) είλαη ε δεύηεξε ζεκαληηθόηεξε δνκή πνπ ρξεζηκνπνηείηαη ζηνπο νδεγνύο ζπζθεπώλ. Πξνζέμηε όηη έλα file δελ έρεη ζρέζε κε ηα FILEs ησλ πξνγξακκάησλ userspace. Η δνκή FILE νξίδεηαη ζηελ βηβιηνζήθε ηεο C θαη δελ εκθαλίδεηαη πνηέ ζε θώδηθα ζηνλ ππξήλα. Έλα struct file, από ηελ άιιε, είλαη κηα δνκή ηνπ ππξήλα θαη πνηέ δελ εκθαλίδεηαη ζηα πξνγξάκκαηα ησλ ρξεζηώλ. Η δνκή file αλαπαξηζηά έλα «αλνηρηό αξρείν». Γεκηνπξγείηαη από ηνλ ππξήλα θαηά ηελ εθηέιεζε ηεο open θαη πεξληέηαη ζε θάζε ζπλάξηεζε πνπ ιεηηνπξγεί ζην file, κέρξη ην θιείζηκό ηνπ (θιήζε ζπζηήκαηνο close()). Μεηά ην θιείζηκν ηνπ αξρείνπ, ν ππξήλαο απνδεζκεύεη ηελ αληίζηνηρε δνκή file. Έλα open file είλαη δηαθνξεηηθό από έλα disk file, πνπ αλαπαξίζηαηαη από έλα struct inode. Σα πεδία ηεο δνκήο file αλαπαξηζηνύλ ηελ θαηάζηαζε ελόο αξρείνπ αλνηρηνύ γηα θάπνηα δηεξγαζία ρξήζηε, δειαδή ηα δηθαηώκαηα πξόζβαζεο ηεο δηεξγαζίαο ζην αξρείν, ηε ζέζε ηνπ δείθηε αλάγλσζεο / εγγξαθήο θιπ. Σα ζεκαληηθόηεξα από απηά είλαη: mode_t f_mode; Σα bits ηνπ πεδίνπ f_mode θαζνξίδνπλ ην είδνο ηεο πξόζβαζεο πνπ επηηξέπεηαη λα έρεη ε δηεξγαζία ζην αλνηρηό αξρείν. Γηα παξάδεηγκα, αλ ην αξρείν έρεη αλνηρηεί γηα αλάγλσζε, ην bit FMODE_READ ζα είλαη 1 θαη ε παξάζηαζε f_mode & FMODE_READ ζα είλαη κε κεδεληθή. loff_t f_pos; ην πεδίν απηό απνζεθεύεηαη ε ηξέρνπζα ζέζε ηνπ δείθηε αλάγλσζεο / εγγξαθήο. Ο ηύπνο loff_t είλαη κηα ηηκή εύξνπο 64bit (long long ζηελ νξνινγία ηνπ gcc). Ο νδεγόο κπνξεί λα δηαβάζεη ηελ ηηκή απηή αλ ρξεηάδεηαη λα κάζεη ηελ ηξέρνπζα ζέζε. Η κέζνδνο llseek, εθόζνλ νξίδεηαη, αλαιακβάλεη λα αλαλεώλεη ηελ ηηκή f_pos. Οη κέζνδνη read θαη write πξέπεη ηελ αλαλεώλνπλ όηαλ κεηαθέξνπλ δεδνκέλα. unsigned short f_flags; Σα flags απηά θαζνξίδνπλ θάπνηεο άιιεο ηδηόηεηεο πξόζβαζεο, όπσο O_RDONLY, O_NONBLOCK, θαη O_SYNC. Έλαο νδεγόο ειέγρεη ζπλήζσο γηα ην flag γηα ηηο ιεηηνπξγίεο nonblocking, ελώ ηα άιια ζπάληα ρξεζηκνπνηνύληαη. Όια ηα flags νξίδνληαη ζην αξρείν επηθεθαιίδαο <linux/fcntl.h>. struct file_operations *f_op; - 18 -
Απηό είλαη ην πεδίν ηεο δνκήο file πνπ επηηξέπεη ηελ αληηζηνίρηζε ηνπ αλνηρηνύ αξρείνπ κε ζπγθεθξηκέλε δνκή file_operations, άξα θαη κε ζπγθεθξηκέλν νδεγό ζπζθεπήο. Ο ππξήλαο αξρηθνπνηεί ηνλ δείθηε απηό θαηά ην άλνηγκα θαη ηνλ αθνινπζεί όπνηε ρξεηάδεηαη λα θαιέζεη θάπνηα ζπλάξηεζε γηα λα εθηειέζεη θάπνηα ιεηηνπξγία επάλσ ζην αλνηρηό αξρείν. Γελ πξνβιέπεηαη λα ρξεζηκνπνηεζεί άκεζα από ηνλ νδεγό ζπζθεπήο καο. void *private_data; H θιήζε ζπζηήκαηνο open() ζέηεη ην δείθηε απηό ζε NULL πξηλ ηελ θιήζε ηεο κεζόδνπ open ηνπ νδεγνύ. Ο νδεγόο είλαη ειεύζεξνο λα θάλεη ρξήζε ηνπ δείθηε απηνύ όπσο ζεσξεί θαιύηεξν, αθόκα θαη λα ηνλ αγλνήζεη εληειώο. Υξεζηκνπνηείηαη ζπλήζσο ώζηε λα αληηζηνηρηζηεί ην αλνηρηό αξρείν ζε ηδησηηθέο δνκέο δεδνκέλσλ ηνπ νδεγνύ ζπζθεπήο. Ο δείθηεο κπνξεί λα ρξεζηκνπνηεζεί ώζηε λα δείρλεη ζε δεζκεπκέλα δεδνκέλα, αιιά απηά πξέπεη λα απειεπζεξσζνύλ από ηε κέζνδν release πξηλ ν ππξήλαο θαηαζηξέςεη ηε δνκή file. O δείθηεο private_data είλαη έλαο πνιύ ρξήζηκνο ηξόπνο γηα λα θξαηάκε πιεξνθνξίεο γηα ηελ θαηάζηαζε ηεο ζπζθεπήο (state information) αλάκεζα ζηηο δηάθνξεο θιήζεηο ζπζηήκαηνο. ηελ πεξίπησζή πνπ εμεηάδεηε, ζα ρξεζηκνπνηείηαη ώζηε λα δείρλεη ζε δνκή ηύπνπ lunix_chrdev_state_struct, ε νπνία πεξηγξάθεη ηελ ηξέρνπζα θαηάζηαζε ηεο ζπζθεπήο. Η πξαγκαηηθή δνκή struct file δηαζέηεη κεξηθά αθόκε πεδία, αιιά δελ καο είλαη ρξήζηκα. Θπκίδνπκε όηη όπνηνο ζέιεη λα κάζεη πεξηζζόηεξα, κπνξεί λα θνηηάμεη ζην αξρείν <linux/fs.h> όπνπ νξίδεηαη ε δνκή. 6. Σκήκα ζπιινγήο θαη επεμεξγαζίαο δεδνκέλωλ ην θεθάιαην απηό πεξηγξάθεηαη ν ηξόπνο κε ηνλ νπνίν έρεη ήδε ζρεδηαζηεί θαη πινπνηεζεί ην ηκήκα ζπιινγήο θαη επεμεξγαζίαο δεδνκέλσλ, ην νπνίν ζα παξέρεη ηηο ηηκέο ησλ κεηξνύκελσλ κεγεζώλ ζηνλ νδεγό ζπζθεπήο ραξαθηήξσλ πνπ θαηαζθεπάδεηε. 6.1. πιινγή δεδνκέλωλ από ζεηξηαθέο ζύξεο Καηά ηε ζρεδίαζε ηνπ Lunix:TNG πξνθύπηεη ε αλάγθε ζπιινγήο δεδνκέλσλ πνπ πξνέξρνληαη από ην ζηαζκό βάζεο θαη πξνώζεζήο πξνο ην ηκήκα επεμεξγαζίαο ηνπ πξσηνθόιινπ, έηζη ώζηε λα είλαη δπλαηή ε εμαγσγή θαη πξνζσξηλή απνζήθεπζε ησλ κεηξνύκελσλ ηηκώλ. Όηαλ έλαο νδεγόο ζπζθεπήο γξάθεηαη από κεδεληθή βάζε, ε αλάγθε απηή θαιύπηεηαη κε άκεζε, απεπζείαο αιιειεπίδξαζε κε ην πιηθό. Τπάξρνπλ δύν ηξόπνη λα γίλεη - 19 -
απηό: Ο πξώηνο ηξόπνο είλαη ζύγρξνλνο: όηαλ ν νδεγόο ηεο ζπζθεπήο ρξεηαζηεί λέα δεδνκέλα απνζηέιιεη εληνιέο Δ/Δ ζην πιηθό. Απηό ηηο επεμεξγάδεηαη ελώ ν επεμεξγαζηήο πεξηκέλεη θαη ηειηθά ην πιηθό επηζηξέθεη ηηο ηηκέο πνπ ηνπ δεηήζεθαλ. Ο δεύηεξνο ηξόπνο είλαη αζύγρξνλνο θαη είλαη απηόο πνπ ππνζηεξίδεηαη από ηηο πεξηζζόηεξεο ζπζθεπέο ζήκεξα, αθξηβώο γηαηί δελ απαηηεί άκεζε θαη ζπλερή εκπινθή ηνπ επεμεξγαζηή: όηαλ ππάξρνπλ δηαζέζηκεο λέεο ηηκέο (π.ρ. όηαλ παηεζεί έλα πιήθηξν ζην πιεθηξνιόγην), ελεξγνπνηείηαη θαηάιιειν ζήκα δηαθνπήο (interrupt) πξνο ηνλ επεμεξγαζηή. Ο ππξήλαο μεθηλά λα επεμεξγάδεηαη ηε δηαθνπή θαη ηελ πξνσζεί ζηνλ νδεγό ζπζθεπήο, ν νπνίνο έρεη δεηήζεη λα ηελ εμππεξεηεί. Ο νδεγόο εμεηάδεη ηε ζπζθεπή θαη αληηγξάθεη ζε ρώξνπο πξνζσξηλήο απνζήθεπζεο ηηο λέεο πιεξνθνξίεο. ηελ πεξίπησζε ηνπ Lunix:TNG όκσο, δελ ππάξρεη ιόγνο λα μεθηλήζνπκε λα γξάθνπκε θώδηθα από ην κεδέλ γηα ην ζηαζκό βάζεο ηνπ δηθηύνπ. Ο ιόγνο είλαη όηη απηόο βαζίδεηαη ζε έλα γλσζηό ηζηπ Serial over USΒ, γηα ην νπνίν ήδε ππάξρεη βαζηθή ππνζηήξημε από ηνλ ππξήλα. Απηό ζεκαίλεη όηη ήδε έρεη γξαθηεί θώδηθαο πνπ ζπλεξγάδεηαη κε ην ππνζύζηεκα USB ηνπ ππξήλα, έηζη ώζηε λα κπνξεί λα αλαθαιύςεη ηε ζπζθεπή, λα ιάβεη δεδνκέλα από απηή θαη λα ηα εκθαλίζεη ζε κία εηθνληθή ζεηξηαθή ζύξα (πεξηζζόηεξα γηα νδεγνύο ζπζθεπώλ USB κπνξείηε λα βξείηε ζην [1], θεθ. 13). Δπηπιένλ, δελ απνθιείεηαη άιινη, παξόκνηνη ζηαζκνί βάζεο πνπ ρξεζηκνπνηνύλ ην ίδην πξσηόθνιιν λα ζπλδένληαη κέζσ κηαο πξαγκαηηθήο ζεηξηαθήο ζύλδεζεο ζην κεράλεκα αληί γηα USB, νπόηε ηα δεδνκέλα ηνπο εκθαλίδνληαη ζε κηα ζπζθεπή όπσο ε /dev/ttys0. Ο νδεγόο καο δελ έρεη ιόγν λα κελ κπνξεί λα ππνζηεξίμεη θαη απηή ηελ πεξίπησζε, εθόζνλ ην πξσηόθνιιν επηθνηλσλίαο (ε κνξθή ησλ bytes πνπ ηειηθά κεηαθέξνληαη) είλαη νπζηαζηηθά ην ίδην. Απηό ινηπόλ πνπ ρξεηάδεηαη είλαη έλαο γεληθόο ηξόπνο ην Lunix:TNG λα ιακβάλεη δεδνκέλα από ζπζθεπέο εηζόδνπ όπσο ε /dev/ttys0 θαη ε /dev/ttyusb1 βαζηδόκελν ζε ήδε ππάξρνληεο νδεγνύο γηα ζεηξηαθέο θαη USB ζύξεο πνπ ππάξρνπλ κέζα ζηνλ ππξήλα. Γηα λα ην πεηύρνπκε απηό ρξεηάδεηαη λα δνύκε πεξηζζόηεξν δηεμνδηθά ην ξόιν ηνπ ζηξώκαηνο TTY, ηνπ ζηξώκαηνο δειαδή ηνπ ππξήλα πνπ ππνζηεξίδεη ηεξκαηηθέο ζπζθεπέο, όπσο είλαη νη ζεηξηαθέο ζύξεο. 6.2. Σν ζηξώκα TTY ηνπ ππξήλα ηνπ Linux Ο όξνο TTY είλαη κηα ζύληκεζε ηνπ ΣeleΣΤpewriter θαη αλαθέξεηαη ζε πξαγκαηηθά αξραίεο ζπζθεπέο, ηα ηειέηππα, [2] νη νπνίεο ρξεζηκνπνηνύληαλ σο ηεξκαηηθά γηα είζνδν εληνιώλ ζε κεραλήκαηα UNIX θαη παξνπζίαζε απνηειεζκάησλ. Ωο ζύξα TTY ραξαθηεξίδεηαη θάζε ζύξα πνπ κπνξεί λα ππνζηεξίμεη ηεξκαηηθό, ζηελ νπνία κπνξνύκε λα θάλνπκε login θαη λα δώζνπκε εληνιέο ζην ζύζηεκα. ε έλα ζύγρξνλν ζύζηεκα Linux νη ζύξεο TTY ζπκπεξηιακβάλνπλ ηηο ζεηξηαθέο ζύξεο (ttys0, ttys1), ηηο ζεηξηαθέο πάλσ από USB (ttyusb0, ttyusb1), ηηο - 20 -
θνλζόιεο ηνπ ζπζηήκαηνο (tty0, tty1, tty2) αιιά θαη εηθνληθέο θνλζόιεο πνπ δεκηνπξγνύληαη όηαλ γηα παξάδεηγκα αλνίγεηε έλα λέν παξάζπξν ηεξκαηηθνύ (π.ρ. xterm, konsole, gnome-terminal) θάησ από ηα X. Με ηελ εληνιή tty κπνξείηε λα δείηε ηε ζύξα ζηελ νπνία έρεηε ζπλδεζεί θάζε θνξά. Όιεο νη ζύξεο TTY πθίζηαληαη εληαία δηαρείξηζε από ηνλ ππξήλα, θαζώο ρξεηάδεηαη λα ππνζηεξίδνπλ έλα ζύλνιν από θνηλά ραξαθηεξηζηηθά. Τπάξρεη νξγάλσζε ζε ζηξώκαηα: ζην θαηώηεξν ζηξώκα ππάξρεη θώδηθαο (ν νδεγόο TTY) πνπ κηιάεη άκεζα κε ην πιηθό (π.ρ. ην ηζηπ πνπ ρεηξίδεηαη ηε ζεηξηαθή ζύξα), ελώ ζην αλώηεξν ζηξώκα ππάξρεη θώδηθαο πνπ πινπνηεί ηε δηεπαθή ζπζθεπήο ραξαθηήξσλ, ώζηε νη TTYs λα εκθαλίδνληαη σο ζπζθεπέο ραξαθηήξσλ ζην ζύζηεκα (ρήκα 4). User Application user buffer read() /dev/ttyusb1 User TTY Core (struct file_operations *) tty_read Line discipline (struct tty_ldisc_ops *) Low-level device driver (struct tty_driver *) tty buffer flip buffer interrupt handler ldisc read() ldisc receive_buf() tty_flip_buffer_push Lunix:TNG protocol processing? Kernel interrupt Hardware Serial device Data transfer Function call Incoming data ρήκα 4: Αξρηηεθηνληθή ηνπ ζηξώκαηνο TTY ηνπ Linux Σν ζηξώκα TTY ηνπ ππξήλα ρσξίδεηαη ζε ηξία θύξηα κέξε: Σν ηκήκα TTY core, ην ηκήκα ηεο δηάηαμεο γξακκήο (line discipline) θαη ην ηκήκα ηνπ θαηώηεξνπ νδεγνύ ζπζθεπήο. Σν ηκήκα ηνπ θαηώηεξνπ νδεγνύ ζπζθεπήο αλαιακβάλεη ηελ απεπζείαο επηθνηλσλία κε ηε ζεηξηαθή ζπζθεπή, π.ρ. ην ρεηξηζκό ζεκάησλ δηαθνπήο, αιιά δε ρξεηάδεηαη λα γλσξίδεη ηίπνηε γηα ην πώο ε ζπζθεπή απνζεθεύεη πξνζσξηλά δεδνκέλα ζηα αλώηεξα επίπεδα ή ππνζηεξίδεη ιεηηνπξγίεο ηεξκαηηθνύ. Σν ηκήκα TTY core - 21 -
θξνληίδεη ώζηε νη ζεηξηαθέο ζπζθεπέο λα εκθαλίδνληαη σο ζπζθεπέο ραξαθηήξσλ ζην ζύζηεκα. Σν ηκήκα πνπ καο ελδηαθέξεη πεξηζζόηεξν είλαη απηό ηεο line discipline: ιεηηνπξγεί σο θίιηξν θαη θξνληίδεη γηα ηελ πξνζσξηλή απνζήθεπζε ησλ δεδνκέλσλ. Σν ζεκαληηθό είλαη όηη κπνξεί λα αιιάμεη. Γηαθνξεηηθέο δηαηάμεηο κπνξνύλ λα επηιεγνύλ αλαιόγσο κε ηε ρξήζε πνπ πξόθεηηαη λα έρνπλ ηα δεδνκέλα. Η ζπλεζηζκέλε line discipline νλνκάδεηαη N_TTY θαη απιά πεξλά δεδνκέλα ζην αληίζηνηρν /dev/tty. Αο δνύκε πεξηιεπηηθά ηη ζπκβαίλεη ζηε ζπλεζηζκέλε πεξίπησζε όπνπ κηα δηεξγαζία δεηά λα δηαβάζεη δεδνκέλα από κηα ζεηξηαθή ζύξα, έζησ ηε /dev/ttyusb1. Η δηαδηθαζία ηεο παξαιαβήο ησλ δεδνκέλσλ ιεηηνπξγεί αζύγρξνλα ζε ζρέζε κε ηε δηαδηθαζία αλάγλσζεο/θαηαλάισζήο ηνπο από ηε δηεξγαζία, νπόηε ρξεηάδεηαη ηα δεδνκέλα πνπ ιακβάλνληαη λα απνζεθεύνληαη πξνζσξηλά έσο όηνπ δεηεζνύλ. Όηαλ παξαιεθζνύλ δεδνκέλα από ηε ζπζθεπή, απηή πξνθαιεί έλα ζήκα δηαθνπήο, ην νπνίν εμππεξεηείηαη από ηνλ θαηώηεξν νδεγό TTY. Σα εηζεξρόκελα δεδνκέλα αληηγξάθνληαη κέζα ζε έλαλ από δύν ρώξνπο πνπ νλνκάδνληαη flip buffers θαη ρξεζηκνπνηνύληαη ελαιιάμ: θάζε θνξά έλαο από ηνπο δύν είλαη δηαζέζηκνο γηα ρξήζε από ηε ζπζθεπή, ελώ ν άιινο πξνσζείηαη πξνο ηε line discipline. Όηαλ απηόο πνπ ρξεζηκνπνηείηαη γεκίζεη, νη buffers αιιάδνπλ ξόινπο ( flip ). Όηαλ έλαο flip buffer γεκίζεη, ν θαηώηεξνο νδεγόο θαιεί ηελ ζπλάξηεζε tty_flip_buffer_push() (αξρείν drivers/tty/tty_buffer.c ηνπ θώδηθα ηνπ ππξήλα) ε νπνία κε ηε ζεηξά ηεο πεξλά ηα δεδνκέλα ζηε δηάηαμε γξακκήο αληηγξάθνληάο ηα ζηνλ TTY buffer (flush_to_ldisc()). Η δηάηαμε γξακκήο ελεκεξώλεηαη όηη λέα δεδνκέλα έρνπλ θηάζεη όηαλ θαιείηαη ε κέζνδνο ldisc receive_buf() γηα λα ηα επεμεξγαζηεί. Σέινο, ηα δεδνκέλα αλαθηώληαη από ηελ tty_read() ε νπνία ρξεζηκνπνηεί ηελ ldisc read() γηα λα ηα αληηγξάςεη από ηνλ TTY buffer ζην ρώξν ρξήζηε. Η δηαδηθαζία πνπ κόιηο πεξηγξάςακε αληαπνθξίλεηαη ζηε ζπλεζηζκέλε πεξίπησζε όπνπ ηα δεδνκέλα πξνσζνύληαη απεπζείαο ζην ρώξν ρξήζηε. Ωζηόζν, κε ρξήζε δηαθνξεηηθώλ δηαηάμεσλ γξακκήο είλαη δπλαηό λα επεθηαζεί ε ιεηηνπξγία ηνπ ζπζηήκαηνο. Γηα παξάδεηγκα, ρξεζηκνπνηείηε δηαθνξεηηθή δηάηαμε γξακκήο θάζε θνξά πνπ ζπλδέεζηε κέζσ PPP ζην δίθηπν: Αληί γηα ηε ζπλεζηζκέλε δηάηαμε N_TTY, παξεκβάιιεηαη ε δηάηαμε N_PPP, ε νπνία αληί λα πεξλά ηα δεδνκέλα ζην ρώξν ρξήζηε, ηα νκαδνπνηεί ζε παθέηα δηθηύνπ θαη ηα πεξλά ζην δηθηπαθό ππνζύζηεκα ηνπ ππξήλα. Λίζηα ησλ πξνθαζνξηζκέλσλ δηαηάμεσλ ππάξρεη ζην αξρείν <linux/tty.h>. - 22 -
6.3. Ζ δηάηαμε γξακκήο ηνπ Lunix:TNG Ο απινύζηεξνο ηξόπνο ώζηε ην ππό θαηαζθεπή ζύζηεκα λα έρεη πξόζβαζε ζηα παθέηα απνζηέιινληαη από ην ζηαζκό βάζεο, είλαη λα θαηαζθεπαζηεί κηα λέα δηάηαμε γξακκήο, ε Lunix:TNG line discipline, ε νπνία ζα ζπιιακβάλεη ηα δεδνκέλα εηζόδνπ θαη ζα ηα πξνσζεί όρη απεπζείαο ζην ρώξν ρξήζηε αιιά ζε θαηάιιειν ηκήκα επεμεξγαζίαο ηνπ πξσηνθόιινπ ησλ αηζζεηήξσλ, ην νπνίν θαη ζα εμάγεη ηηο ηηκέο ησλ κεηξνύκελσλ κεγεζώλ. Η δηάηαμε απηή έρεη ήδε πινπνηεζεί, ν θώδηθάο ηεο ζαο δίλεηαη ζηα αξρεία lunixldisc.h θαη lunix-ldisc.c. Η ζπλάξηεζε αξρηθνπνίεζεο ηνπ lunix-ldisc.c εγθαζηζηά ηε λέα δηάηαμε κέζσ ηεο θιήζεο tty_register_ldisc(), έηζη ώζηε απηή λα είλαη δηαζέζηκε ζην ππόινηπν ζύζηεκα. Σν ζύλνιν ηεο απαηηνύκελεο ιεηηνπξγηθόηεηαο πινπνηείηαη ζηελ lunix_ldisc_receive_buf(), ε νπνία πξνσζεί ηα εηζεξρόκελα δεδνκέλα ζην ηκήκα πινπνίεζεο ηνπ πξσηνθόιινπ επηθνηλσλίαο. Δπηπιένλ, παξέρεηαη ν θώδηθαο ηνπ κηθξνύ βνεζεηηθνύ πξνγξάκκαηνο lunixattach.c ην νπνίν ελεξγνπνηεί ηε ζπγθεθξηκέλε δηάηαμε ζε θάπνηα ζεηξηαθή ζύξα ηνπ ζπζηήκαηνο, κέζσ θαηάιιειεο θιήζεο ioctl(). Με ρξήζε απηνύ ηνπ εξγαιείνπ, νξίδεηαη έηζη πνηα ζύξα ζα ρξεζηκνπνηείηαη από ην ζύζηεκα γηα παξαιαβή δεδνκέλσλ από ηνπο αηζζεηήξεο. Πεξηζζόηεξα γηα ηελ νξγάλσζε ηνπ ζηξώκαηνο TTY ηνπ Linux κπνξείηε λα βξείηε ζην [5] θαη ζην θεθ. 18 ηνπ [1]. 6.4. Δπεμεξγαζία ηωλ παθέηωλ θαη εμαγωγή κεηξήζεωλ Σν ηκήκα επεμεξγαζίαο ηνπ πξσηνθόιινπ επηθνηλσλίαο ησλ αηζζεηήξσλ ηνπ δηθηύνπ πινπνηείηαη ζηα αξρεία lunix-protocol.h θαη lunix-protocol.c πνπ ζαο δίλνληαη. Η επεμεξγαζία ησλ παθέησλ βαζίδεηαη ζε κία απιή κεραλή θαηαζηάζεσλ, ε νπνία γλσξίδεη πόζα bytes δεδνκέλσλ ρξεηάδεηαη λα πεξηκέλεη ζε θάζε θάζε ηεο επεμεξγαζίαο, έσο όηνπ ζπκπιεξσζεί έλα πιήξεο παθέην κεηξήζεσλ. Οη εηζεξρόκελνη ραξαθηήξεο παξέρνληαη ζηνλ θώδηθα επεμεξγαζίαο ηνπ πξσηνθόιινπ κέζσ ηεο lunix_protocol_received_buf() πνπ θαιείηαη από ηε lunix_ldisc_receive_buf(). Οη ηηκέο ησλ κεηξνύκελσλ κεγεζώλ εμάγνληαη σο αξηζκεηηθέο πνζόηεηεο ησλ 16 bit ρσξίο πξόζεκν (ηύπνο uint16_t ηεο C) θαη απνζεθεύνληαη ζε ρώξνπο πξνζσξηλήο απνζήθεπζεο. Ο θώδηθαο πνπ πινπνηεί ηε δέζκεπζε θαη δηαρείξηζή ηνπο πεξηέρεηαη ζην αξρείν lunix-sensors.c, ελώ ν νξηζκόο ηεο δνκήο δεδνκέλσλ πνπ ηνπο πεξηγξάθεη (struct lunix_sensor_struct) βξίζθεηαη ζην αξρείν lunix.h. Οη πνζόηεηεο απηέο ρξεηάδεηαη λα κεηαηξαπνύλ κε βάζε ζπγθεθξηκέλεο ζπλαξηήζεηο πνπ δίλνληαη από ηνλ θαηαζθεπαζηή ησλ αηζζεηήξσλ έηζη ώζηε λα εμαρζνύλ πξνζεκαζκέλεο δεθαδηθέο ηηκέο θαηάιιειεο γηα παξνπζίαζε θαη θαηαγξαθή. Η - 23 -
κεηαηξνπή απηή ρξεηάδεηαη ιεηηνπξγίεο θηλεηήο ππνδηαζηνιήο, γηα παξάδεηγκα δηαίξεζε, πνιιαπιαζηαζκό θαη ππνινγηζκό ινγαξίζκσλ γηα πνζόηεηεο ηύπνπ float. Ωζηόζν, ε ζρεδίαζε ηνπ ππξήλα ηνπ Linux θαζηζηά απαγνξεπηηθή ηελ εθηέιεζε πξάμεσλ θηλεηήο ππνδηαζηνιήο από θώδηθα ηνπ kernelspace. Οη ιόγνη είλαη θπξίσο δύν: Η θαηάζηαζε ηεο κνλάδαο εθηέιεζεο ππνινγηζκώλ θηλεηήο ππνδηαζηνιήο (Floating Point Unit FPU) δε ζώδεηαη θαη δελ επαλαθέξεηαη όηαλ ν επεμεξγαζηήο πεξλά από ηελ εθηέιεζε ρώξνπ ρξήζηε ζηελ εθηέιεζε ρώξνπ ππξήλα. Έηζη, αλ ν ππξήλαο αιιάμεη ηελ ηηκή θαηαρσξεηώλ ηεο είλαη ζρεδόλ ζίγνπξν όηη ζα επεξεαζηεί ε νξζόηεηα ηεο εθηέιεζεο πξνγξακκάησλ ρξήζηε. Οξηζκέλεο από ηηο αξρηηεθηνληθέο ζηηο νπνίεο έρεη κεηαθεξζεί ν ππξήλαο (π.ρ. ε αξρηθή αξρηηεθηνληθή i386 θαη ε αξρηηεθηνληθή ARM) δελ ππνζηεξίδνπλ θαλ εληνιέο θηλεηήο ππνδηαζηνιήο ζην πιηθό, αιιά απηέο αλαιακβάλνληαη από βηβιηνζήθεο πνπ ηηο πινπνηνύλ κέζσ πξάμεσλ αθεξαίσλ, νη νπνίεο δε ζπκπεξηιακβάλνληαη ζηνλ ππξήλα. Τπάξρνπλ δύν πηζαλέο ιύζεηο γηα ην πξόβιεκα πνπ δεκηνπξγείηαη: Να πξνσζνύληαη ζην userspace απεπζείαο νη 16-bit πνζόηεηεο, ρσξίο θακία κεηαβνιή. Να ζεσξείηαη επζύλε ηνπ πξνγξάκκαηνο ρξήζηε ε κεηαηξνπή ηνπο ζε ηηκέο αλαγλώζηκεο από ην ρξήζηε. Σν πξόγξακκα είλαη ειεύζεξν λα ρξεζηκνπνηήζεη ρσξίο πεξηνξηζκό ππνινγηζκνύο θηλεηήο ππνδηαζηνιήο. Δθόζνλ κε 16 bits θσδηθνπνηνύληαη ην πνιύ 65536 θαηαζηάζεηο, κπνξεί ε απεηθόληζε ησλ ηηκώλ απηώλ ζε αλαγλώζηκεο ηηκέο λα ππνινγηζηεί εθ ησλ πξνηέξσλ ζε πίλαθεο αλαδήηεζεο (lookup tables). Μηα δεθαδηθή ηηκή ζηαζεξήο αθξίβεηαο, ηεο κνξθήο ±xx.yyy κπνξεί λα απνζεθεύεηαη σο ν αθέξαηνο ±xxyyy, νπόηε ρξεηάδεηαη απιά κηα δηαίξεζε θαη κηα πξάμε ππνινίπνπ γηα ηνλ ππνινγηζκό ηνπ δεθαδηθνύ θαη ηνπ αθέξαηνπ κέξνπο ηεο. αο δίλεηαη θώδηθαο πνπ πινπνηεί ηε δεύηεξε ιύζε. Σν αξρείν mk_lookup_tables.c πεξηέρεη ηηο θαηάιιειεο ζπλαξηήζεηο ώζηε λα ππνινγίζεη ηηο απεηθνλίζεηο όινπ ηνπ εύξνπο κε πξνζεκαζκέλσλ ηηκώλ από 0x0000 έσο 0xFFFF θαη γηα ηξία κεηξνύκελα κεγέζε. Σν απνηέιεζκα απνζεθεύεηαη ζε ηξεηο πίλαθεο αλαδήηεζεο, ζην αξρείν lunix-lookup.h. 7. Εεηήκαηα πινπνίεζεο ην θεθάιαην απηό παξνπζηάδνληαη νξηζκέλα ηερληθά δεηήκαηα πνπ πξνθύπηνπλ θαηά ηνλ πξνγξακκαηηζκό ζε ρώξν ππξήλα. Δπεηδή απηά εκθαλίδνληαη πνιύ ζπρλά θαη αθνξνύλ ην ζύλνιν ζρεδόλ ησλ νδεγώλ ζπζθεπώλ, ν ππξήλαο πξνζθέξεη - 24 -