\documentclass[10pt,a4paper]{article}
\usepackage{indentfirst}
\usepackage[greek]{babel}
\usepackage[iso-8859-7]{inputenc}
\usepackage[margin=3cm]{geometry}
\usepackage{latexsym}
\usepackage{fancybox}
\usepackage{fancyhdr}
\usepackage{fancyvrb}
\usepackage{framed}
\usepackage{supertabular}
\usepackage{graphicx}
\usepackage{ifthen}
\usepackage{color}
\usepackage{pstricks}

%\usepackage{kerkis}

\newif\ifpdf
\ifx\pdfoutput\undefined
	\pdffalse
\else
	\pdftrue
\fi

\ifpdf
	\usepackage[unicode,bookmarks=true]{hyperref}
	\hypersetup{%
		pdftitle={},
		pdfauthor={Nicholas Christopoulos},
		pdfsubject={},
		pdfkeywords={},
%		pdfpagemode={UseOutlines},
		pdfpagemode={None},
		bookmarksopen,
		pdfstartview={FitH},
		colorlinks,linkcolor={blue},citecolor={blue},urlcolor={red},
	}%
\fi
	
%\pagestyle{fancy}
\pagestyle{headings}

%\renewcommand{\sectionmark}[1]{\markboth{\thesection.\ #1}{}}

%\lhead{\thesection.\sectionmark}
%\chead{}
%\rhead{}
%\lfoot{}
%\rfoot{\thepage\ $/$ \pageref{EOF}}
%\cfoot{\thepage{}$/$\pageref{EOF}}

%%% ndc macro-lib %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\def\lat#1{\textlatin{#1}}				% Λατινικά
\def\gr#1{\textgreek{#1}}				% Ελληνικά

%%% Συντομογραφίες
\def\bs{\textbackslash}					% Συντομογραφία του '\'
\def\pwr{\textasciicircum}				% Συντομογραφία του '^'
\def\ano{\gr{;}}						% ’νω τελεία

\def\XOR{\textasciicircum}				% Συντομογραφία του '^'  (C's XOR)
\def\INV{\textasciitilde}				% Συντομογραφία του '~'  (C's inverse bits)
\def\OR{\textbar}						% Συντομογραφία του '|'  (C's OR)
\def\DEG{\circ}							% Μοίρες/Βαθμοί θερμ.
\def\MLT{$\ast$}						% STD Multiplication
\def\STAR{$\star$}						% pentagon star
\def\RCON{$\Rightarrow$}
\def\DCON{$\Leftrightarrow$}

%%% Εισαγωγικά 
\newcommand{\sq}[1]
{\textquoteleft{}#1\textquoteright{}}			% Αγγλικά μονά εισαγωγικά

\newcommand{\dq}[1]
%{\textquotedblleft{}#1\textquotedblright{}}	% bug on 'kerkis'
{\lat{``}#1\lat{''}}		% Αγγλικά διπλά εισαγωγικά

\newcommand{\q}[1]
{\gr{((}#1\gr{))}}								% Ελληνικά/Γαλλικά εισαγωγικά

\newcommand{\vq}[1]
{$\langle$#1$\rangle$}							% LaTeX μεταβλητές <...>

%%% Αποσπάσματα
\def\qq#1#2{
\begin{quotation}
<<\textit{#1}>>
\begin{flushright}{--- #2}\end{flushright}
\vskip 1ex
\end{quotation}
}

\def\qpoem#1#2{
\begin{quote}
\begin{center}
#1
\end{center}
\begin{flushright}{--- #2}\end{flushright}
\vskip 1ex
\end{quote}
}

%%% Στοιχεία κειμένου
\def\url#1{\lat{\texttt{#1}}}			% URL
\def\email#1{\lat{\texttt{#1}}}			% e-mail
\def\file#1{\sq{\lat{\texttt{#1}}}}		% Αρχείο
\def\key#1{[{\lat{\texttt{#1}}}]}		% Πλήκτρο
\def\code#1{\sq{\lat{\texttt{#1}}}}		% ...
\def\var#1{{\lat{\textit{#1}}}}		% ...

\def\defn#1{\sq{\lat{\textsl{#1}}}}		% 
\def\term#1{{\lat{\textsl{#1}}}}		% 
\def\gterm#1{{\gr{\textsl{#1}}}}		% 

\def\progname#1{{\lat{\textbf{\textsf{#1}}}}}		% όνομα προϊόντος

\def\qs#1#2{\lat{``}{\rm \textit{#1}}\lat{''}}

\newenvironment{susebox}[2][]%
{%
\def\@boxtext{\textbf{\large \textsf{#2}}}
\vrule{\hbox to 1em{\hrulefill}%
\raisebox{-1ex}[0pt]{%
\rule[-2ex]{0pt}{0pt}\ \@boxtext{} }\hrulefill}
\\*\nopagebreak%
\begin{minipage}{\linewidth}
\begin{list}{}{%
\setlength\topsep{0pt}%
\setlength\rightmargin\leftmargin%
}%
\item[] \ifthenelse{\equal{#1}{}}{}{\textbf{\sffamily #1}\hspace*{\fill}\\*}}%
{\nopagebreak\end{list}\end{minipage}\nopagebreak
\par%
\vglue -2ex % θέση κάτω γραμμής
{\hrulefill\raisebox{-.5ex}[0pt]%
{\rule[2.5ex]{0pt}{0pt}\ \@boxtext\ }%
\hbox to 1em{\hrulefill}}\rule{0.4pt}{2.5ex}%\vrule%
\vspace{1.5ex}%
} 

\def\WWW{\lat{World Wide Web}}

\def\typebiblio#1#2#3{
\lat{``}\textit{#1}\lat{''}, #2,\\*
{\hspace*{3em} \parbox{20cm}{#3}}
}

\def\typebook#1#2#3{
{
\latintext
\typebiblio{#1}{#2}{#3}
\greektext
}
}

% βιβλιογραφία
\def\bibgrf#1#2#3{
\lat{``}\textit{\gr{#1}}\lat{''}, \gr{#2},\\ \gr{#3}
}

\def\biblatf#1#2#3{
\lat{``}\textit{\lat{#1}}\lat{''}, \lat{#2},\\ \lat{#3}
}

\def\parref#1{(\ref{#1})}

\newcounter{countresult}
\def\result#1{
\addtocounter{countresult}{1} 
\begin{quote}
$\rhd$ \roman{countresult} $\lhd$ #1
\end{quote}
}

\def\qnote#1{
\begin{quote}
#1
\end{quote}
}

\def\proof#1{
\begin{quote}
$\rhd$ #1 $\lhd$
\end{quote}
}

%% commandchars=\\\{\},
\DefineVerbatimEnvironment%
{example}{Verbatim}
{numbers=left,tabsize=4,
 numbersep=2mm,framesep=3mm,
 frame=leftline,framerule=0.25mm}
 
\def\todo#1{
\begin{quote}
[\lat{\textsf{\textbf{ToDo}}}] #1
\end{quote}
}

%%% ndc macros end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\def\PM{\textsf{\lat{PM}}}
\def\SB{\textsf{\lat{SmallBASIC}}}
 
\title{Το \PM{} και η φιλοσοφία του}
\author{Νικόλαος Χριστόπουλος\\\url{nereus@freemail.gr}}
\date{Έκδοση 0.3\\Αθήνα, \today}

\begin{document}
\maketitle
\tableofcontents

\setlength{\parindent}{0pt}
\setlength{\parskip}{9pt}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{abstract}
Το \PM{} είναι ένα σύστημα που σχεδίασα για να λύσει συγκεκριμένα
προβλήματα, όπως τον ενιαίο τρόπο επικοινωνίας όλων των συσκευών
αλλά και διάφορων βιβλιοθηκών με το \term{desktop} περιβάλλον του 
\term{arm0nia project}. Έχει όμως πολύ μεγαλύτερες προεκτάσεις.
Το θεωρώ ιδιαίτερα απλό, αλλά δυστυχώς ο περισσότερος
κόσμος αδυνατεί να το καταλάβει, και εδώ έρχεται αυτό το έγγραφο
που σκοπό έχει να εξηγήσει αυτό το \dq{περίεργο} σύστημα πως
λειτουργεί και ποιες είναι οι δυνατότητές του. Το \PM{} εκτός
από ένα υποσύστημα, μπορεί να χρησιμοποιηθεί ως θεωρητικό
πρότυπο για ενιαίο \term{interface}, καθώς επίσης και για
υποσύστημα τύπου \term{OLE}/\term{CORBA} κ.α.
\end{abstract}

\section{Το περιβάλλον του λογισμικού}

Εμείς οι προγραμματιστές γνωρίζουμε πολύ καλά την πολυπλοκότητα των πραγμάτων.
Έχουμε να κάνουμε με ένα χαοτικό περιβάλλον στο οποίο εκατομμύρια γραμμές κώδικα,
εκατομμύρια εντολές, ταξινομημένες συνήθως σε \dq{βιβλιοθήκες}, που αλληλεπιδρούν και
συνδυάζονται για να παράγουν το τελικό έργο, είτε αυτό είναι μια \dq{εφαρμογή},
είτε ένα ολόκληρο Λ.Σ. με όλα τα συνοδευτικά αυτού.

Υπάρχουν αστρονομικά μεγέθη κώδικα, γραμμένα από διάφορους προγραμματιστές ανά τον κόσμο, για ένα επίσης μεγάλο εύρος θεμάτων\footnote{Να θυμίσω το πρόγραμμα που έγγραφε ποιήματα :)}. Μια επίσκεψη στο \term{sourceforge} ή στο \term{codeguru} ή στο \term{simtel} και αλλού, θα σας πείσει παρά το ότι είναι ένα μικρό μέρος του κώδικα που \dq{κυκλοφορεί} στο \term{internet}!

Μέσα σ' αυτό το \dq{\term{codespace}}\footnote{Ένας πρόχειρος δικός μου ορισμός, αντίστοιχος του \term{dataspace}, για να δηλώσω το σύνολο του κώδικα, \term{public domain}, \term{open/free source} αλλά και \dq{κλειδωμένου} με κάποιο νομικό τρόπο, που υπάρχει στο \term{internet}.} βρίσκουμε συχνά λύσεις τις οποίες χρειαζόμαστε ή \dq{θα ήταν χρήσιμο} ή \dq{θα ήταν όμορφο} ή \dq{θα ήταν έξυπνο} ή \dq{θα ήταν βολικό για το μέλλον} να τις προσθέσουμε. Λύσεις έτοιμες και δοκιμασμένες, λύσεις που τις συντηρούν και αναπτύσσουν άλλοι, λύσεις που εκτοξεύουν την ίδια την ανάπτυξη του λογισμικού στα ύψη μέσω της συλλογικής πια εργασίας.

\subsection{Η νέα συλλογική ανάπτυξη}

Στο \dq{\textit{Ο Καθεδρικός και το Παζάρι}} ο \lat{Raymond} προσπάθησε να εξηγήσει την δύναμη της συλλογικής εργασίας από μια παλαβή\cite[10 π.19]{bazaar}, τυπική αμερικάνικη ($\ge$ 1950) οπτική γωνία, δηλαδή, ανύπαρκτης ή προπαγανδισμένης κοινικοπολιτικής \dq{φιλοσοφίας}. Όπως και να έχει αυτό το έργο είναι σημαντικό από πολλές πλευρές και έχει ενδιαφέρουσες απόψεις\ano{} το σημαντικότερο όλων είναι ότι είναι ολοκληρωμένο και ο αναγνώστης που δεν έχει επαφή με το \term{open/free source} μπορεί να αντιληφθεί την \dq{επανάσταση} στην ανάπτυξη του λογισμικού που συντελέστηκε τις τελευταίες δεκαετίες\footnote{Το \term{open source} αρχίζει \dq{επίσημα} με το \TeX{} από όσο ξέρω...} καθώς επίσης και την δύναμη της συλλογικής εργασίας που είναι γνωστή στο ευρύ κοινό σήμερα, με το όνομα \term{Linux}.

Βάση αυτών, λοιπόν, βλέπουμε ότι υπάρχει ήδη υποδομή, προσπάθειες αλλά και μεγάλο έργο φτιαγμένο για να λειτουργεί για το σύνολο, δηλαδή για εμάς. Οι περισσότεροι της \term{free source} κοινότητας είναι ιδεολόγοι και βασίζουν τις κινήσεις αυτές στην ηθική, έτσι αποκαλούν τους εκάστοτε προγραμματιστές που συνεισφέρουν ως εθελοντές.

Εδώ όμως θα διαφωνήσω διότι βλέπω τον κώδικα διαφορετικά, τον βλέπω σαν ανταλλαγή απόψεων\footnote{Ο κώδικας είναι έκφραση όπως τα μαθηματικά και ο λόγος και όσοι διαφωνούν σ' αυτό είναι γιατί δεν είναι προγραμματιστές παρά μόνο κατ' όνομα.} ή/και εργασίας. Η ανταλλαγή των απόψεων είναι και η ρίζα της ανάπτυξης της επιστήμης και της φιλοσοφίας\footnote{Δηλαδή να περιμένουμε να πολλαπλασιαστεί σε εκπληκτικό βαθμό το ήδη τεράστιο \term{codespace}.}. Η ανταλλαγή δεν προϋποθέτει την θέληση χωρίς αντάλλαγμα που απαιτεί ο εθελοντισμός για αυτό και περιμένω να μεγαλώσει ακόμα περισσότερο ο \dq{πληθυσμός} της κοινότητας. 

Το \term{free/open source} είναι περισσότερο μια επιστημονική \dq{κολεκτίβα} παρά ένα \dq{φιλανθρωπικό ίδρυμα}. Βοηθώντας ένα έργο που χρησιμοποιούμε, βοηθάμε τον εαυτό μας διότι το έργο αυτό, θα το χρησιμοποιήσουμε και στο μέλλον. Η ανάπτυξη ενός τέτοιου έργου είναι και δικό μας θέμα αφού βασίζουμε μέρος της εργασίας μας επάνω του.

Περισσότερα για την σκληροπυρηνική ιδεολογία του \gterm{ελεύθερου λογισμικού} θα βρείτε στις σελίδες της \term{GNU}, ενώ για την μετριοπαθή ιδεολογία του \gterm{λογισμικού ανοικτού κώδικα}, στις σελίδες του \term{OSI}.
Μια περιγραφή και για τα δύο από το ΕΔΕΤ\cite{edetg4}, όχι και τόσο λεπτομερείς, αλλά χρήσιμη για τους άσχετους.

\section{Το πρόβλημα του ήδη γραμμένου κώδικα}

Συμβαίνει η κάθε ομάδα ανάπτυξης ενός έργου να διαμορφώνει την επικοινωνία με άλλο κώδικα ανάλογα με τις ανάγκες της και συμβαίνει αυτή η επικοινωνία να είναι κάθε φορά διαφορετική
από έργο σε έργο, ακόμα και όταν αναφέρεται στο ίδιο θέμα. Αυτό είναι φυσικό να συμβαίνει διότι η συλλογική εργασία παραμένει σε επίπεδο έργου και όχι συνόλου πράγμα έτσι και αλλιώς πολύ δύσκολο.

Αυτό όμως έχει σαν αποτέλεσμα, να αναγκάζει τους προγραμματιστές να αποφεύγουν συχνά την χρήση τέτοιων έργων διότι:

\begin{enumerate}
\item Απαιτεί από αυτούς να δώσουν χρόνο για την εκμάθηση του διαφορετικού \term{interface}.
\item Συχνά δεν ταιριάζει το \term{interface} με την δομή του ήδη υπάρχων κώδικα.
\item Είναι αναγκασμένοι να γράψουν ειδικό κώδικα για την υποστήριξη του καθενός με αποτέλεσμα, εκτός από κουραστικό και χρονοβόρο, να είναι και ανασφαλές διότι ο κώδικας όσο πιο περίπλοκος είναι τόσο πιο πιθανό είναι να κάνει σφάλματα.
\end{enumerate}

\subsection{I/O}

Το κάθε πρόγραμμα χαρακτηρίζεται από την \dq{είσοδο} και την \dq{έξοδο}. Ώς \dq{είσοδο} ονομάζουμε το σύστημα εισαγωγής στοιχείων, όπου αυτό μπορεί να είναι μια συσκευή όπως το ποντίκι ή τα αποτελέσματα κάποιας επεξεργασίας όπως ένα αρχείο, ή και άλλα. Αντίστοιχα και η \dq{έξοδος} είναι τα αποτελέσματα του προγράμματος τα οποία μπορεί να είναι ένα αρχείο, κάποια ή κάποιες γραφικές παραστάσεις στην οθόνη και πάει λέγοντας.

Στην σημερινή κατάσταση τα συστήματα εισόδου/εξόδου κατά κανόνα απαιτούν απόλυτα διαφορετικό τρόπο χειρισμού από το πρόγραμμα. Όταν για παράδειγμα σχεδιάζουμε ένα διάγραμμα στην οθόνη, χρειάζεται να γράψουμε και νέο διαφορετικό κώδικα για να το εκτυπώσουμε ή να το πάρουμε σε μορφή αρχείου.

\subsection{Η είσοδος της εξόδου}

Τα πράγματα γίνονται ιδιαίτερα πολύπλοκα όταν θέλουμε να επεξεργαστούμε τα αποτελέσματα μιας εφαρμογής, καθώς επίσης και τα αποτελέσματα της δικής μας εργασίας να είναι δυνατό να επεξεργαστούν από άλλες εφαρμογές.

Κατά κανόνα, η επικοινωνία των προγραμμάτων γίνετε μέσω αρχείων, ενώ χρειάζεται ειδικό χειρισμό για την επικοινωνία της κάθε εφαρμογής. Για παράδειγμα για ένα διανυσματικό σχέδιο, είμαστε αναγκασμένοι να χρησιμοποιήσουμε διάφορες μορφές αρχείων που χρησιμοποιούνται από τα προγράμματα \term{CAD}, και αν θέλουμε να κάνουμε καλή δουλειά θα πρέπει να υποστηρίζουμε 2-3 τουλάχιστον τέτοιες μορφές.

\subsection{Νεκρή φύση}

Τα αρχεία, εκτός των άλλων, είναι \dq{νεκρή φύση}. Δεν κάνουν υπολογισμούς, δεν συμπεριφέρονται ανάλογα με τις ανάγκες μας, αλλά είναι στατικά, νεκρά κατά κάποιο τρόπο. Αυτό περιορίζει κατά πολύ τις δυνατότητες εισόδου/εξόδου. Για παράδειγμα δεν μπορείς από ένα αρχείο διανυσματικών γραφικών να του ζητήσεις να μετατραπεί σε άλλη ανάλυση (χρήσιμο για επεξεργασία σε \term{bitmap}) ή σε άλλο σύστημα αξόνων (+ψ επάνω ή κάτω), πρέπει να το κάνεις στο πρόγραμμά σου. Αυτό είναι μια τυπική διεργασία - ρουτίνα που φαντάζομαι πολλοί από εμάς την κάνουν \dq{βόλτα} από πρόγραμμα σε πρόγραμμα, αν και λογικό είναι να γίνετε σε ένα μέρος, επειδή η δομή των στοιχείων διαφέρει αναγκαζόμαστε να αντιγράφουμε και να διορθώνουμε αυτή την ρουτίνα. Δεν θα γινόταν όμως αυτό αν μπορούσαμε από την \dq{είσοδο} να ζητήσουμε το πως θέλουμε τα στοιχεία.

\subsection{Συμπεράσματα}

Αυτά ακριβώς περιορίζουν στο ελάχιστο την δοκιμή (και χρήση) ενδιαφέρον έργων με αποτέλεσμα τον περιορισμό της τοπικής και συνολικής ανάπτυξης του λογισμικού σε παγκόσμιο επίπεδο. Δηλαδή μας δυσκολεύει να δοκιμάσουμε και να χρησιμοποιήσουμε έτοιμες λύσεις, και αν αυτά τα προβλήματα  διορθωθούν είμαι σίγουρος θα έχουμε εκτίναξη της ανάπτυξης λογισμικού, εμπορικού και μη, σε παγκόσμιο επίπεδο.

Θα δούμε όλα αυτά πως λύνονται και πως προωθούνται σε μια τελείως διαφορετική λογική χρήσης και ανάπτυξης. Θα ασχοληθούμε όμως σχεδόν αποκλειστικά με το λεγόμενο \term{VFS}, δηλαδή το \dq{εικονικό σύστημα αρχείων}, διότι είναι το πιο σημαντικό αλλά και το πιο απλό τμήμα του \PM{}.

\section{Ένα ενιαίο \term{interface}}

Τα προβλήματα αυτά τα έχω \dq{νιώσει στο πετσί μου} από την εποχή προ του \term{DOS}. Όσο όμως πέρναγε ο καιρός, και όσο μεγάλωνε η αθλίοτητα του \term{Windows API}\cite{wapi} με ανάγκασε πολλές φορές να φτιάχνω \term{C modules} που ουσιαστικά δεν έκαναν τίποτα άλλο από το να προσφέρουν ένα ενιαίο \term{interface} ανάμεσα ίδιου θέματος βιβλιοθήκες ή τμήματα του \term{API}!

Στο \term{arm0nia project} βρέθηκα να είμαι σε θέση που έπρεπε να συνδέσω εκατοντάδες βιβλιοθήκες γνωστές και μη, τμήματα κώδικα γνωστά και μη καθώς και την διασύνδεση όλων αυτών μεταξύ τους. Αυτό πίστευα, και επιμένω ότι πρέπει να γίνει και σε πολύ μεγάλο βαθμό το \PM{} τα κατάφερε. Δεν με ενδιέφερε και τόσο το \term{arm0nia} αυτό διότι είχα και έχω περιορισμένο χρόνο κυρίως λόγο της εργασίας μου και της \term{SB}. Αλλά το είδος του προβλήματος ήταν που μου κέντρισε το ενδιαφέρον.

\begin{center}
\includegraphics[width=10cm]{io}
\label{fig:io}
\end{center}

Η όλη κατάσταση έμοιαζε με το παραπάνω σχήμα. Τα προγράμματα ήταν φτιαγμένα όπως το \lat{application} της εικόνας, δηλαδή είχαν φτιαχτεί για μιας συγκεκριμένης μορφής είσοδο ή για συγκεκριμένων μορφών σύνδεσης με βιβλιοθήκες\footnote{Στο σχεδιάγραμμα δείχνουμε μόνο την \dq{είσοδο} και \dq{έξοδο} αλλά το ίδιο συμβαίνει και με τις διάφορες βιβλιοθήκες.}. 

Αυτό λοιπόν που χρειαζόταν ήταν τα πάντα να ομιλούν την ίδια γλώσσα, να έχουν δηλαδή την ίδια υποδοχή σύμφωνα με το σχεδιάγραμμα.

\result{Το ενιαίο \term{interface} για τα πάντα είναι η βασική αρχή του \PM{}. Είναι η αρχή όπου ξεδιπλώνεται γύρω της το υπόλοιπο σύστημα.}

Ως δια μαγείας, λοιπόν, όλα τα προβλήματα θα λυνόντουσαν αν υπήρχε κοινή υποδοχή καθώς επίσης και η \dq{έξοδος} ήταν όπως η \dq{είσοδος}. Και αν για κάποιο λόγο δεν μπορούσαμε να είχαμε κοινή είσοδο ένα τέτοιο πρόγραμμα που θα αναλάμβανε να έχει μια γνωστή \dq{έξοδο} θα κάλυπτε αυτό το κενό ώστε να έχουμε το ενιαίο τρόπο επικοινωνίας.

Ως δια μαγείας, λοιπόν, όλα όσα δεν λυνόντουσαν με αυτό θα μπορούσαν να λυθούν με επιπλέον κώδικα. Στο \PM{} η \dq{είσοδος} και η \dq{έξοδος} είναι σχεδόν πάντα κώδικας, δηλαδή \dq{ζωντανό}, ευμετάβλητο πράγμα. Και αν κατά περίπτωση δεν τύχει, μπορεί να γίνει.

\section{Εν' αρχή ήταν η \term{SB}}

Ανάμεσα στα άλλα, έχω φτιάξει και μια \term{BASIC}, την \term{SmallBASIC} (για συντομία \term{SB}). Η \term{SB} έχει μεγάλη σημασία για το \PM{}, διότι είναι ο \dq{σχεδιαστικά} πρόγονός του. 

Η \term{SB} είναι ένα ιδιόμορφο έργο\ano{} πρέπει να παρέχει την μέγιστη ευκολία στον χρήστη μιας και απευθύνεται -- εκτός των άλλων -- σε παιδιά, πρέπει επίσης να λειτουργεί κάτω από διαφορετικά λειτουργικά συστήματα όπως \term{PalmOS}, \term{Linux}, \term{Windows} κ.λπ. Όλα αυτά σημαίνουν ότι έπρεπε η \term{SB} να προσφέρει ένα ενιαίο περιβάλλον για μεγάλο αριθμό διαφορετικών πραγμάτων αλλά και ταχύτατη λειτουργία διότι ειδικά στα \term{Palms} η ταχύτητα καθώς και οι δυνατότητές τους είναι ενοχλητικά περιορισμένες.

Για να καταφέρω αυτά, πήγα πίσω στις πρώτες εκδόσεις του \term{Unix} αλλά και στο \term{DOS} (και \term{CP/M}) και αναρωτήθηκα γιατί δεν επιβλήθηκε μια όμορφη σχεδιαστική δυνατότητα. Και στα δύο αυτά Λ.Σ. η σειριακή πόρτα λειτουργεί όμοια με την κονσόλα και τα δύο λειτουργούν με εντολές \term{file I/O}. Ναι, έχουν ένα ενιαίο \term{interface}, έστω και πρόχειρα φτιαγμένο.

\latintext
\begin{example}
fp_console = fopen("CON:",  "wt");	// Anoigma device consolas
fp_serial  = fopen("COM1:", "wt");	// Anoigma serial port 1

fprintf(fp_console, "Hello, world!");	// typwma sto monitor
fprintf(fp_serial,  "Hello, world!");	// apostolh mesw serial
\end{example}
\greektext

Πιστεύοντας ότι σχεδόν όλα τα δεδομένα μπορούν να οργανωθούν έτσι ώστε να διαχειρίζονται με \term{file I/O} εντολές, αλλά και επειδή είχα ήδη αποκτήσει αναγκαστικά εμπειρία σε τέτοια θέματα, αντί να προσθέτω εντολές στην \term{SB} για κάθε \term{driver}, άλλαξα τον κάθε \term{driver} να συμπεριφέρεται σαν \term{filesystem}.

Έτσι σήμερα στην \term{SB}, με τις τέσσερις εντολές \term{OPEN}, \term{INPUT\#}, \term{PRINT\#} και \term{CLOSE} που χρησιμοποιούνται για το κλασσικό \term{file I/O}, μπορούν οι χρήστες να κάνουν τα εξής

\begin{enumerate}
\item Να χειρίζονται τα αρχεία του δίσκου τους.
\item Να στέλνουν και να παίρνουν δεδομένα μέσω σειριακής.
\item Να γράφουν και να διαβάζουν \term{PDOC} αρχεία (\term{PalmOS database compressed documents}).
\item Να γράφουν και να διαβάζουν \term{memos} από το \term{memo database}.
\item Να γράφουν και να διαβάζουν μέσω \term{telnet protocol}, δηλαδή να επικοινωνούν με τις περισσότερες υπηρεσίες του \term{internet} (\term{POP3}, \term{SMTP}, \term{HTTP} κ.α.)
\end{enumerate}

Η \term{SB} συνέβαλλε βέβαια παραπάνω στο \PM{}, διότι ο κώδικας για τα πρώτα δυναμικά \term{modules} καθώς και άλλα, είναι αντιγραφή του αντίστοιχου κώδικα της \term{SB}.

\subsection{Το ιεραρχικό σύστημα των αρχείων}

Το ιεραρχικό σύστημα των αρχείων είναι μια κλασσική και πάμπολλα διαδεδομένη δομή που μπορεί να εκφράσει σύνθετες δομές δεδομένων. Δεν νομίζω ότι υπάρχει κάποιος που δεν μπορεί να περιγράψει την δομή των δεδομένων όπως ακριβώς σε ένα \term{RDBMS}. Οι σχέσεις των στοιχείων καθώς και τα ευρετήρια, μπορούν να εκφραστούν με πιο σύνθετους τρόπους αλλά πάντα στα πλαίσια του \dq{συστήματος αρχείων} καθώς επίσης και οι λειτουργίες μέσω κώδικα. Για παράδειγμα τα συνδεδεμένα προγράμματα (το \sq{\lat{\#!}} στο \term{Unix} και η \dq{επέκταση} στα \term{Windows}) και οι συνδέσεις (\term{links} στο \term{Unix}).

Πέρα από αυτά, οι διαδικασίες που χρειάζονται για να γίνει η \dq{ανάγνωση} ή \dq{εγγραφή} των στοιχείων, είτε έχουμε αρχείο, είτε \term{socket}, είτε \term{database}, είτε δυναμική λίστα, κ.λπ. είναι πάντα η ίδια. Αλλάζουν μόνο οι εντολές ανάγνωσης και εγγραφής.

Τυπικός ψευδοκώδικας που εκφράζει μια τυπική διεργασία με \dq{ανάγνωση} και \dq{εγγραφή}.
\begin{example}
Πήγαινε στην αρχή των στοιχείων
Εφόσον δεν τελείωσαν τα στοιχεία
	ανάγνωση στοιχείων
	επεξεργασία
	εγγραφή στοιχείων στην έξοδο
	πήγαινε στο επόμενο στοιχείο
\end{example}

Είτε είναι δυναμική λίστα, είτε \term{database}, είτε αρχείο κειμένου, πολλές φορές και \term{socket} κ.λπ. αυτός ο ψευδοκώδικας εκφράζει κάτι που έχουμε βαρεθεί να το επαναλαμβάνουμε. Η \term{SB} (και το \PM{} κατ' επέκταση) δεν υπόσχεται ότι δεν θα το γράψουμε, υπόσχεται όμως ότι έτσι θα γίνετε και με τις ίδιες εντολές για οποιοδήποτε θέμα. \term{INPUT\#} για την ανάγνωση, \term{PRINT\#} για την εγγραφή.

\proof{Οι χρήστες της \term{SB} είναι ευχαριστημένοι με την χρήση αυτών αντί να μαθαίνουν τις \gterm{ιδιότητες} και τις \gterm{μεθόδους} του εκάστοτε \term{class}.}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Πως έγινε όμως αυτό?}

Έχω το ελάττωμα να λατρεύω τα \term{function-pointers}, στην \term{SB} όμως τέτοια υλοποίηση ήταν δύσκολο λόγω των πολλαπλών \term{code segments} που απαιτούσε το \term{PalmOS}. Έτσι αυτό υλοποιήθηκε με τον πλέον απλό τρόπο, τον οποίο και θα δούμε αν θέλουμε να καταλάβουμε αργότερα το ιδιαίτερα σύνθετο \PM{}.

Η εντολή \term{OPEN} παίρνει παράμετρο το όνομα του αρχείου για άνοιγμα. Στην \term{BASIC}, αντίθετα από την \term{C}, αυτή η εντολή παίρνει ως παράμετρο και το \term{file-handle}. Όταν ο χρήστης, πέραν του συνηθισμένου \gterm{συστήματος αρχείων}, θέλει να χρησιμοποιήσει κάποιον από τους προκαθορισμένους οδηγούς που προσφέρονται με την \term{SB}, χρειάζεται αυτό να το δηλώσει στο \gterm{όνομα αρχείου}. Έτσι χρησιμοποιώντας το σύμβολο \sq{:} διαχωρίζει το όνομα του οδηγού και τις παραμέτρους του. Για παράδειγμα το \gterm{όνομα αρχείου} \dq{\lat{myfile.txt}} σημαίνει ένα απλό αρχείο, το \gterm{όνομα αρχείου} \dq{\lat{COM1:9600}} σημαίνει ότι η \term{SB} να χρησιμοποιήσει τον οδηγό της σειριακής πόρτας 1 (\term{COM1}) αντί για το κλασσικό \gterm{σύστημα αρχείων}, στην ταχύτητα των 9600 \term{BAUDs}.

\latintext
\begin{example}[label=\textit{SB source},frame=single]
handle = 1
OPEN "COM1:9600" AS #handle
\end{example}
\greektext

Έτσι το παραπάνω παράδειγμα μεταφράζεται από την \term{SB} στο παρακάτω κώδικα.

\latintext
\begin{example}[label=\textit{\gr{Αντικατάσταση της} OPEN},frame=single]
fileName     = "COM1:9600";
driverName   = fileName.leftOf (':');		// driverName   <- "COM1"
driverParams = fileName.rightOf(':');		// driverParams <- "9600"
if ( driverName == "COM1" ) {
	fileTable[handle].driverID = SERIAL;	// use serial I/O library
	fileTable[handle].serialHandle = serial_open(driverParams);
	}
else {
	fileTable[handle].driverID = DISK;		// use file I/O library
	fileTable[handle].fp = fopen(driverName + driverParams);
	}
\end{example}
\greektext

Το \var{fileTable} φυλάσσει τα στοιχεία του κάθε \term{file-handle}, και ένα από τα στοιχεία αυτά είναι ποια βιβλιοθήκη θα χρησιμοποιήσει (στο παράδειγμά μας, για \term{serial port} ή τυπικό \term{file-system}). Αυτή η πληροφορία καταχωρείτε στο πεδίο \var{driverID} όπως είδαμε.

Η συνάρτηση \code{serial\_open} μαζί με την \code{serial\_write\_string} που θα δούμε παρακάτω, είναι μέρος του \term{driver} της \term{SB}, για την διαχείριση της σειριακής πόρτας. Δηλαδή αυτός ο \term{driver} δεν είναι τίποτα άλλο από μια τυπική βιβλιοθήκη (ή απλό \term{C module}) που περιέχει τουλάχιστον αυτές τις δυο συναρτήσεις.

\latintext
\begin{example}[label=\textit{SB source},frame=single]
PRINT #handle; "Hello, world!"
\end{example}
\greektext

Αντίστοιχα και η αποστολή στοιχείων (\term{PRINT}) γίνετε με το ίδιο τρόπο.

\latintext
\begin{example}[label=\textit{\gr{Αντικατάσταση της} PRINT},frame=single]
params = "Hello, world!";
if ( fileTable[handle].driverID == SERIAL ) 
	serial_write_string(fileTable[handle].serialHandle, params);
else
	fprintf(fileTable[handle].fp, "%s", params);
\end{example}
\greektext

Όπως αντιλαμβανόμαστε η διαδικασία είναι πολύ απλή. Ένα \term{switch} ή διαδοχικά \term{if} υλοποιούν αυτό το υποσύστημα.

\section{Η ιδέα}

Όπως είδαμε ο χρήστης της \term{SB} έχει ένα ενιαίο \term{interface} για μια πληθώρα δυνατοτήτων. Τι θα γινόταν άραγε αν προσαρμόζονταν τα πάντα γύρω από δύο - τρία τέτοια \term{interfaces}? και τι αν η εφαρμογή έπαιρνε παραμετρικά το αντίστοιχο \term{driver} αφού ο κώδικας της θα ήταν ο ίδιος ενώ μόνο η παράμετρος της εντολής \dq{\term{open}()} θα άλλαζε? και τι αν ο ένας \term{driver} φόρτωνε τον άλλο? Και τι αν ο χρήστης (ή πρόγραμμα - γονιός) επέλεγε ποιος είναι ο \term{default driver} για κάθε λειτουργία?

Απάντηση... τρελά πράγματα, χωρίς να αλλάξει ούτε μια γραμμή κώδικα, τόσο τρελά που ούτε η φαντασία μας δεν μπορούσε να συλλάβει. Αυτό που ονειρευτήκαμε την ενοποίηση τεράστιου όγκου κώδικα. 

\result{Στο \PM{} δεν υπάρχει πια η έννοια του αρχείου, της εικόνας, \term{database}, \term{TCP/IP} κ.λπ. υπάρχει μόνο αυτόνομος κώδικας που συμπεριφέρεται με προκαθορισμένο τρόπο.}

Η εφαρμογή ανοίγει ένα αρχείο όπως κάνει πάντα, με τις ίδιες εντολές πάντα, και φυσικά τον ίδιο τρόπο χειρισμού. Το τι κάνει όμως αυτό το αρχείο δεν το ξέρει διότι δεν έχουμε να κάνουμε με αρχείο αλλά κώδικα που συμπεριφέρεται σαν αρχείο.

\result{Αντίστοιχα με τα εικονικά αρχεία η εφαρμογή χειρίζεται και άλλα πραγματικά ή εικονικά συστήματα εισόδου / εξόδου ή επεξεργασίας τα οποία παραμένουν άγνωστα στην εφαρμογή αλλά με γνωστό τρόπο διαχείρισης αυτών.}

Μερικά τρελά παραδείγματα
\begin{itemize}
\item Ένα \term{filemanager} που να στέλνει \term{email} χωρίς να έχει κώδικα για αυτό, δεν τον χρειάζεται, δεν χρειάζεται καν να ξέρει τι είναι \term{socket}!

\item Ένα \term{filesystem} που να προσθέτει \term{unix attributes} σε \term{FAT}!

\item Μια εικόνα που να αποθηκεύεται σαν ήχος και το αντίστροφο! Έχετε ποτέ τραβήξει γραμμές σε ήχο?

\item Ένα γραφικό περιβάλλον που να λειτουργεί το ίδιο καλά σε \term{graphics terminals} όσο και σε \term{ASCII terminals}.

\item Μια εφαρμογή που να εμφανίζεται κατά επιλογή σε \term{PDF} αρχείο αντί για οθόνη, είτε επειδή ορίστηκε έτσι στην εφαρμογή, είτε επειδή ο χρήστης διάλεξε για \term{driver} οθόνης το \term{PDF driver}!
\end{itemize}

Ο Δημήτρης, είχε πει ότι το \PM{} είναι η αποθέωση του \dq{εικονικού}, το \term{virtual} του \term{virtual}. Και είχε δίκιο, διότι το σύστημα αυτό προσφέρει ένα εικονικό περιβάλλον, με εικονικά ή μη δεδομένα, από εικονικές ή μη συσκευές όπου το ένα μπορεί να βασίζεται στο άλλο.

Για παράδειγμα, είναι δυνατό να φτιαχτεί ένα ολόκληρο \term{GUI} περιβάλλον του οποίου η είσοδος και έξοδος καθορίζεται δυναμικά από τον χρήστη, δηλαδή να εκτελείται στην μνήμη, και αν και όταν συνδέσουμε ένα \term{module} \dq{εξόδου} όπως η κάρτα γραφικών, ο εκτυπωτής, τερματικό, βιβλιοθήκη \term{avi} ή \term{pdf} να παίρνουμε τα αποτελέσματα στην οθόνη, εκτυπωτή, σε οθόνη άλλου τερματικού ή αρχείο. Αντίστοιχα ως \dq{είσοδο} αυτού του συστήματος θα μπορούσαμε να έχουμε ένα άλλο πρόγραμμα ή το πληκτρολόγιο ή το ποντίκι, ή συνδυασμό αυτών.

\result{Δεν πρόκειται για κάτι πολύπλοκο, επαναλαμβάνω ότι έχουμε να κάνουμε με πολύ απλό σύστημα, με απλές τεχνικές, που είναι έτσι σχεδιασμένο ώστε να ενοποιεί με ικανοποιητικό τρόπο άσχετα μεταξύ τους κομμάτια λογισμικού αλλά και να αποτρέπει τους περιορισμούς της ίδιας της φύσης του κάθε κώδικα. Το αποτέλεσμα αυτού είναι όλες αυτές οι δυνατότητες.}

Εφόσον το ποντίκι (\term{pointing device interface}) μπορεί να αντικατασταθεί από κώδικα, η οθόνη (\term{graphics device interface}) από κώδικα και το ταχυδρομείο από κώδικα που συμπεριφέρεται σαν σύστημα αρχείων (\term{virtual file system interface}). Εφόσον όλα αυτά μπορούν να γίνουν χωρίς να αλλάξει ούτε μια γραμμή κώδικα, τότε δεν θα έπρεπε να σας παραξενεύουν τα αποτελέσματα αλλά αντίθετα να μας κριτικάρετε για έλλειψη φαντασίας.

\subsection{Τα \term{modules} ανεξάρτητα από το \PM{}}

Το \term{arm0nia project} όμως είναι, τουλάχιστον προς το παρών, ευάλωτο. Σήμερα υπάρχει, αύριο μπορεί και όχι. Το έργο όμως πάνω στις αρχές του \PM{} έπρεπε και πρέπει να επιζήσει.

Ο λόγος είναι απλός. Εμείς θα κάναμε και κάνουμε ήδη μια εργασία. Αυτή η εργασία προσφέρει ένα τυποποιημένο μοντέλο λειτουργίας για διάφορα πράγματα η οποία μπορεί να χρησιμοποιηθεί και από τρίτους, και θα πρέπει να γίνει αυτό ή έστω να απαιτηθεί να γίνει αυτό.

Το \PM{} λοιπόν προσφέρει εκτός του συνολικού συστήματος και ένα τρόπο \textbf{έτσι ώστε ανεξάρτητες εφαρμογές με το \PM{} να είναι ικανές να προσθέσουν τα \term{modules} του \PM{} στον κώδικά τους χωρίς να χρειάζονται το ίδιο το \PM{} ή την βιβλιοθήκη αυτού}. Η ανεξαρτητοποίηση των \term{modules} αυτών είναι για 'μένα σημαντικό θέμα.

Το πως γίνετε -- πράγμα απλό και εύχρηστο -- αυτό δεν θα το αναλύσουμε εδώ, αλλά το βρίσκω απόλυτα απαραίτητο να ειπωθεί.

\section{Τεχνικές ανάπτυξης του \PM{}}
Θα εξηγήσουμε παρακάτω -- με τον πλέον τυπικό τρόπο -- τις τεχνικές που χρησιμοποιήθηκαν για να επιτευχθεί η ανάπτυξη του \PM{}. Όλα αυτά είναι ενσωματωμένα στο υποσύστημα και είναι αόρατα στον τελικό χρήστη - προγραμματιστή.

\subsection{Σύνδεση αρχείου και κώδικα}

Όπως είδαμε στην \term{SB}, η επιλογή των ρουτινών για το άνοιγμα ή την ανάγνωση ή την αποστολή στοιχείων γινόταν με διαδοχικά \term{if}. Αυτή η διαδικασία στο \PM{} έπρεπε να γίνετε αυτόματα και το πως αυτό είναι δυνατό θα το αναλύσουμε τώρα.

Αν αντί για μια σειρά από \defn{if}, συνδέσαμε το εικονικό αρχείο με την βιβλιοθήκη που είναι  ικανή να το διαχειρίζεται...

\latintext
\begin{example}[label=\textit{\gr{Αντικατάσταση της} OPEN},frame=single]
fileName     = "COM1:9600";
driverName   = fileName.leftOf (':');		// driverName   <- "COM1"
driverParams = fileName.rightOf(':');		// driverParams <- "9600"
if ( driverName == "COM1" ) {
	fileTable[handle].openFuncPtr = serial_io_open;
	fileTable[handle].writeFuncPtr = serial_io_write;
	}
else {
	fileTable[handle].openFuncPtr = file_io_open;
	fileTable[handle].writeFuncPtr = file_io_write;
	driverParams = driverName + driverParams;
	}

// open 'file'
fileTable[handle].systemHandle =
	fileTable[handle].openFuncPtr(driverParams);
\end{example}
\greektext

Δηλαδή ο πίνακας \var{fileTable}, στο νέο αυτό σχήμα, φυλάσσει τις διευθύνσεις των ρουτινών αντί για το ποια βιβλιοθήκη να χρησιμοποιήσει, ενώ οι συναρτήσεις για το \term{serial I/O} και για το \term{file I/O} έχουν προσαρμοστεί έτσι ώστε να έχουν την ίδια σύνταξη.

Αυτό έχει φιλοσοφικές προεκτάσεις διότι προσθέτει μια τελείως διαφορετική λογική και δυνατότητες στην αντιμετώπιση του θέματος. Ενώ πριν είχαμε ένα πίνακα από στοιχεία για κάθε αρχείο, τώρα στο αρχείο αυτό το συνδέουμε με τον αντίστοιχο κώδικα για τον χειρισμό του (\term{function pointers}). Αυτός ο \dq{αντίστοιχος κώδικας} μπορεί πράγματι να αναφέρεται στην χρήση ενός αρχείου αλλά μπορεί και σε οτιδήποτε άλλο (π.χ. σειριακή πόρτα, \term{sockets}, ή κάποια επεξεργασία κ.λπ.).

\result{Με αυτή την τεχνική ο υπόλοιπος κώδικας δεν χρειάζεται να ξέρει τι είναι το αρχείο για να το χρησιμοποιήσει. Απλά καλεί τις προκαθορισμένες συναρτήσεις, με προκαθορισμένη σύνταξη, συναρτήσεις που είναι ορισμένες μέσα στο \var{fileTable[handle]}.}

Στην ακόλουθη αντικατάσταση της \code{PRINT} βλέπουμε καθαρά ότι το πρόγραμμα δεν χρειάζεται πια να ξέρει ότι το υποτιθέμενο \dq{αρχείο} είναι σειριακή πόρτα ή κανονικό αρχείο.
\latintext
\begin{example}[label=\textit{\gr{Αντικατάσταση της} PRINT},frame=single]
params = "Hello, world!";
fileTable[handle].writeFuncPtr(fileTable[handle].systemHandle, params);
\end{example}
\greektext

\subsection{Εξέλιξη σε \term{module}}

Στην προηγούμενη διαδικασία η \term{open} γέμιζε το \term{fileTable} με τις διευθύνσεις των ρουτινών για τις μεθόδους \term{open}, \term{close} και \term{read}, \term{write}. Είδαμε επίσης ότι για να γίνει αυτό χρειαζόταν κάθε βιβλιοθήκη να συμπεριφέρεται με τον ίδιο τρόπο, δηλαδή να έχει μια προκαθορισμένη σύνταξη για τις προαναφερθέντες εντολές.

Όμως μέχρι τώρα όλα αυτά γινόντουσαν στο ίδιο το πρόγραμμα - εφαρμογή. Αυτό που μας ενδιαφέρει είναι οι βιβλιοθήκες αυτές να φορτώνονται κατά επιλογή από την εφαρμογή. Αυτό είναι δυνατό να γίνει αν χρησιμοποιήσουμε τον μηχανισμό δυναμικής διασύνδεσης βιβλιοθηκών που παρέχεται στα σημερινά Λ.Σ.

Για να γίνει αυτό, αντί να έχουμε μια μεταβλητή τύπου \term{fileTable}, φτιάχνουμε εμείς ένα \term{structure} στο οποίο αποθηκεύουμε τις διευθύνσεις των ρουτινών. 

\latintext
\begin{example}[label=\textit{\gr{Αντικατάσταση του} fileTable},frame=single]
struct module {
	void	*dlHandle; // handle of dynamic linked library
	int		(*open) (const char *fileName, const char *mode);
	void	   (*close)(int handle);
	int		(*write)(int handle, char *buffer, int size);
	int		(*read) (int handle, char *buffer, int size);
	};
\end{example}
\greektext

Έτσι, λοιπόν, καθορίζουμε το ενιαίο \term{interface} όλων των βιβλιοθηκών, που από τώρα ονομάζονται \term{modules}, όπου συμπεριφέρονται σαν αρχεία. Δηλαδή, χειρίζονται με τις κλασσικές εντολές του \term{file I/O}\footnote{\lat{open(), read(), write(), close(), eof(), seek(), fgets(), etc}}.

\latintext
\begin{example}[label=\textit{\gr{Δυναμικό φόρτωμα }module},frame=single]
module	serial_io_lib;
module	file_io_lib;

serial_io_lib.dlHandle = dlopen("my_serial_io_lib.so", RTLD_LAZY);
serial_io_lib.open     = dlsym(serial_io_lib.dlHandle, "open");
...
file_io_lib.dlHandle = dlopen("my_file_io_lib.so", RTLD_LAZY);
file_io_lib.open     = dlsym(file_io_lib.dlHandle, "open");
\end{example}
\greektext

Περισσότερα για τις δυναμικής -- σύνδεσης βιβλιοθήκες στο \cite{plhow}. Με αυτό τον τρόπο είναι δυνατό να φορτώνουμε πολλά τέτοια \term{modules} και κρατώντας τον ίδιο κώδικα - εφαρμογής να εναλλάσσουμε την έξοδο/είσοδο απλά αλλάζοντας τον \gterm{δείκτη} του \term{module} όπως ακριβώς βλέπουμε στο παρακάτω παράδειγμα.

\latintext
\begin{example}[label=\textit{\gr{Παράδειγμα με δύο} modules},frame=single]
module	*current_module;

//current_module = &serial_io_lib;
current_module = &file_io_lib;
int handle = current_module->open("myfile", "w");
current_module->read(handle, buffer, 1024);
current_module->close(handle);
\end{example}
\greektext

Όπως βλέπουμε, αν απενεργοποιήσουμε την γραμμή 4 και ενεργοποιήσουμε την 3, τότε ο κώδικας αυτός αντί να διαβάζει από ένα αρχείο θα παίρνει στοιχεία από την σειριακή πόρτα.

\proof{Σ' αυτό το σημείο θα πρέπει να αντιλαμβάνεστε πόσο εύκολο θα ήταν, αλλάζοντας μια μόνο γραμμή κώδικα στην εφαρμογή, αυτή να χρησιμοποιεί συμπιεσμένα ή όχι αρχεία με την χρήση της \term{zlib}.}

\subsection{\term{VFS}}

Το \term{VFS} σημαίνει \term{Virtual File System} δηλαδή εικονικό σύστημα αρχείων. Το ονομάσαμε έτσι διότι η εφαρμογή νομίζει ότι διαχειρίζεται ένα σύστημα αρχείων, αλλά αυτό το σύστημα μπορεί να εκφράζει τελείως διαφορετικά πράγματα. Κλασσικά δείγματα, είναι τα \term{zip} αρχεία όπου περιέχουν καταλόγους και αρχεία σε συμπιεσμένη μορφή, το \term{registry} των \term{Windows}, κ.α.

Το \term{VFS} υποσύστημα του \PM{}, εκφράζει δύο καταστάσεις. 

\begin{enumerate}
\item Επίπεδο αρχείου. Δηλαδή όταν έχουμε να κάνουμε με εικονικά αρχεία όπως η σειριακή πόρτα.
\item Επίπεδο καταλόγων. Δηλαδή όταν έχουμε να κάνουμε με ολοκληρωμένο περιβάλλον, με καταλόγους, αρχεία και \term{file-attributes}.
\end{enumerate}

Υποθέτω ότι η λέξη \term{file} ακόμα σας περιορίζει την φαντασία στα κλασσικά αρχεία. Αυτό είναι σημαντικό λάθος, δεν πρόκειται για αρχεία αλλά για κώδικα! Η λέξη \term{file} εκφράζει τον τρόπο επικοινωνίας με το \term{module} και όχι τι κάνει το \term{module}. Το αρχείο στο \term{VFS} θα μπορούσε κάλλιστα να είναι μια ρουτίνα που στέλνει πίσω στην εφαρμογή τα αποτελέσματα μιας επεξεργασίας ή οποία έγινε την ώρα ακριβώς που η εφαρμογή ζήτησε να \dq{ανοίξει} το αρχείο.

Ας δούμε ένα απλό παράδειγμα.

Υποθέτουμε ότι έχουμε ένα μετρητή θερμοκρασίας στο \term{PC} μας ο οποίος επιστρέφει την θερμοκρασία σε βαθμούς \term{Kelvin}. Αυτή την συσκευή την διαχειριζόμαστε από την βιβλιοθήκη που μας παρέχει ο κατασκευαστής, η οποία βιβλιοθήκη έχει μια και μόνη συνάρτηση, την \code{curTherm()}.

Ένα τυπικό πρόγραμμα θα έκανε τα παρακάτω για να μας εμφανίσει την θερμοκρασία σε βαθμούς \term{Kelvin} και \term{Celsius}.
\latintext
\begin{example}[label=\textit{thermometer},frame=single]
main()
{
	double	t = curTherm();
	
	printf("%f Kelvin\n",  t);
	printf("%f Celsius\n", t - 273);
}
\end{example}
\greektext

Επειδή όμως εμείς θέλουμε να βλέπουμε αυτές τις μετρήσεις σε ένα \term{file-manager} έτσι ώστε όταν κάνουμε κλικ σε ένα αρχείο που ονομάζεται \file{/thermometer/Kelvin} και ένα που ονομάζεται
\\\file{/thermometer/Celsius} να βλέπουμε την τρέχουσα μέτρηση στην αντίστοιχη κλίμακα\ano{} φτιάχνουμε ένα αντίστοιχο \term{VFS module}.

\latintext
\begin{example}[label=\textit{thermometer vfs module},frame=single]
char	strKelvin[32];
char	strCelsius[32];

int		therm_open(const char *fileName)
{
	if	( strcmp(fileName, "Celsius") == 0 )	{
		sprintf(strCelsius, "%f", curTherm() - 273);
		return 1;
		}
	else if	( strcmp(fileName, "Kelvin") == 0 )	{
		sprintf(strKelvin,  "%f",  curTherm());
		return 2;
		}		
	return -1; // error
}

int		therm_read(int handle, char *buf, int size)
{
	int		len = 0;

	switch ( handle )	{
	case	1:	// Celsius-file data
		len = strlen(strCelsius);
		strncpy(buf, strCelsius, len);
		break;	
	case	2:	// Kelvin-file data
		len = strlen(strKelvin);
		strncpy(buf, strKelvin, len);
		}
	return len;
}

void	module_init(module *mod)
{
	mod->open = therm_open;
	mod->read = therm_read;
}
\end{example}
\greektext

Αυτό το \term{module} είναι ένα εικονικό σύστημα αρχείων. Βέβαια το έχουμε απλοποιήσει εδώ αλλά δεν έχει και μεγάλη διαφορά από την πραγματικότητα. Στο \code{module\_init} όπως βλέπουμε καθορίζουμε ποια συνάρτηση αναλαμβάνει να κάνει το \term{open} και ποια το \term{read}.

Ας δούμε τι και πως ακριβώς θα συμβεί
\begin{enumerate}
\item Η εφαρμογή -- \term{file-manager} ζητά από τον \PM{} να φορτώσει το \term{module}.
\item Το \PM{} εκτελεί την \code{module\_init} ώστε να ξέρει ποιες συναρτήσεις
	είναι υλοποιημένες στο \term{module} και ποια αναλαμβάνει να κάνει τι.
\item Η εφαρμογή ζητά από το \PM{} να ανοίξει το εικονικό αρχείο \file{Celsius}.
\item Το \PM{} εκτελεί την \code{therm\_open("Celsious")} και επιστρέφει τον 
	εικονικό \term{handle} (επιστρέφεται από την \code{therm\_open()}) πίσω στην εφαρμογή.
\item Η εφαρμογή ζητά από το \PM{} να πάρει τα περιεχόμενα του αρχείου με μια τυπική κλήση 
	στην \code{fgets()} (\code{module->fgets(...)}).
\item Το \PM{}, μέσω της δικής του \code{fgets()} καλεί την \code{therm\_read()} για να πάρει
	τα στοιχεία και τα επιστρέφει στην εφαρμογή.
\end{enumerate}

\subsection{Εκτός του \term{VFS}}

...

...κλειδιά...

\subsection{\term{PMFS}}

Ωραία όλα αυτά αλλά θα έπρεπε η εφαρμογή να μπορεί να ξέρει τι \term{modules} υπάρχουν στο σύστημα για ποιο \term{interface}. Έτσι το \term{deamon} του \PM{}, ανέλαβε να παρέχει αυτές τις πληροφορίες μέσω ενός εικονικού συστήματος αρχείων, το ονομαζόμενο \term{pmfs}.

\latintext
\begin{example}[label=\textit{\gr{Λίστα όλων των} vfs modules},frame=single]
main()
{
	pm_vfs_module_t	*pmfs;
	strlist_t		*list;
	int				i;

	pm_init();	// initialize PM

	// load PM virtual-file-system module
	if	( (pmfs = pm_vfs_load("vfs/pmfs")) == NULL )
		panic("pm_vfs_load(): failed");

	printf("The following VFS modules found:\n\n");
	list = pmfs->list(pmfs->mid, "/vfs/*");
	for ( i = 0; i < list->count; i ++ )	
		printf("%d: %s\n", i+1, list->str[i]);

	strlist_destroy(list);
	pm_vfs_release(pmfs);
}
\end{example}
\greektext

Η \dq{μέθοδος} \term{list} είναι μια πιο προχωρημένη έκδοση των \term{opendir()/closedir()}, και επιστρέφει μια λίστας με τα ονόματα των αρχείων. Δηλαδή το αντίστοιχο των εντολών \code{ls} ή/και \code{dir} που γνωρίζουμε από την κονσόλα.

\subsection{Ένα έτοιμο εικονικό σύστημα αρχείων}

Ας υποθέσουμε ότι έχουμε ένα \term{file-manager} ο οποίος λειτουργεί με \term{modules} αντίστοιχα με αυτά που περιγράψαμε παραπάνω, αλλά προσθέστε και λοιπές κοινότυπες εργασίες όπως \term{opendir()/closedir()} και \term{chdir()/rmdir()/mkdir()}. 

\proof{Έχουμε ήδη φτιάξει τέτοιο πρόγραμμα - εφαρμογή που λειτουργεί άψογα, το \term{vfssh}, το οποίο είναι ένα \term{shell} σαν τα \term{bash} και \term{tcsh} μόνο που αντί να λειτουργεί με το σύστημα αρχείων του Λ.Σ., αυτό λειτουργεί αποκλειστικά με \term{modules} του \PM{}.}

Σκεφτείτε όμως τώρα, πως θα φτιάξουμε ένα \term{vfs module} για την παρουσίαση των στοιχείων του κάθε χρήστη έτσι όπως αυτά αναφέρονται στο \file{/etc/passwd}. 

\proof{Το συγκεκριμένο \term{module}, αν και όχι ακριβώς το ίδιο, υπάρχει στα παραδείγματα και μπορείτε να το δείτε να λειτουργεί μέσω του \term{vfssh}.}

Έχουμε τα παρακάτω στοιχεία από τα κλασσικά αρχεία του \term{Unix}

(\lat{todo: passwd structure, groups})

Τώρα πρέπει να φανταστούμε πως θα θέλαμε να υπάρχουν σε μορφή αρχείων. Λογικά θα θέλαμε ένα κατάλογο για τους χρήστες και ένα για τις ομάδες. Κάθε αρχείο στον κατάλογο του χρηστών, θα πρέπει να περιέχει τα στοιχεία του χρήστη και φυσικά το όνομά του να είναι το αντίστοιχο \term{username}.

\latintext
\begin{Verbatim}[label=\textit{\gr{Ιεραρχία εικονικού συστήματος}},frame=lines]
/users/
    |--- root
    |--- nikos
    |--- dimitris
    +--- yannis
/groups/
    |--- root
    +--- users
\end{Verbatim}
\greektext

Και να πως θα έπρεπε να εμφανίζεται ένα τυπικό εικονικό αρχείο.

\latintext
\begin{Verbatim}[label=\textit{\gr{Περιεχόμενα αρχείου }\file{/users/nikos}},frame=lines]
Nicholas Christopoulos
User-ID       : 501
Group-ID      : 100
Home directory: /home/nikos
Shell         : /bin/tcsh
\end{Verbatim}
\greektext

\proof{Μπορείτε να τα δείτε αυτά μέσω του \term{vfssh} εκτελώντας τις εντολές \code{ls} και \code{cat} όπως ακριβώς θα κάνατε αν ήταν πραγματικά αρχεία.}

Προσθέσαμε λοιπόν στο \PM{} μια βιβλιοθήκη η οποία χτίζει ένα εικονικό σύστημα αρχείων στην μνήμη. Το μόνο που χρειάζεται, λοιπόν, να κάνει το \term{module} μας είναι να επεξεργαστεί τα στοιχεία των \file{/etc/passwd} και \file{/etc/groups}, και να τα γράψει στο εικονικό σύστημα αρχείων, πράγμα που επιτυγχάνετε με τις τυπικές, \term{file I/O}, εντολές, όπως θα κάναμε αν τα γράφαμε στο δίσκο. Από εκεί και πέρα το \term{vfslib}, η βιβλιοθήκη αναφέραμε, αναλαμβάνει την διαχείριση του \term{module} κατά επιλογή βέβαια του προγραμματιστή.

%%%%%%%%%%%%%%%%%%
\section{Αρχές του \PM{}}

\subsection{Λογική σχεδίαση}
Η λογική στο \PM{} έχει μεγαλύτερη σημασία από την δυνατότητα, διότι ο προγραμματιστής και ο κάθε άνθρωπος βολεύεται με τυποποιημένες λογικές λύσεις και όχι με \dq{ακροβατικές} δυνατότητες - προχειρότητες. Όταν ένα πράγμα είναι φτιαγμένο για να κάνει μια συγκεκριμένη λειτουργία, έτσι πρέπει να παραμείνει και όχι να προσφέρεται μέσω αυτής της λειτουργίας άσχετες δυνατότητες. 

Κατά την γνώμη μου, ο σωστός σχεδιασμός έχει να κάνει με αυτό, δηλαδή ο προγραμματιστής να μην χρειάζεται να ανοίξει το βιβλίο για να βρει πως θα κάνει τι, αλλά αυτό να είναι αυτονόητο. Αν χρειαστούν ποτέ εξτρά δυνατότητες αυτές μπορούν να γίνουν με μια παραπάνω συνάρτηση \ano{} κατά κανόνα, αυτά τα εξτρά δεν χρειάζονται παρά μόνο σε εξαιρέσεις.

Το ακριβώς αντίθετο του \dq{σωστού σχεδιασμού} μπορείτε να το μελετήσετε στο \term{Windows API}, ή απλά να διαβάσετε τον πολύ καλό σχολιασμό του Σπινέλλη\cite{wapi}.

\subsection{Ενιαίο \term{interface}}

Όταν γράφουμε κώδικα για μια εικόνα τύπου \term{bmp}, είναι αυτονόητο να απαιτούμε ο ίδιος κώδικας να λειτουργεί και για εικόνες τύπου \term{jpeg}. Όταν έχουμε μια βιβλιοθήκη γραφικών που γράφει/διαβάζει την \term{Video RAM}, είναι αυτονόητο να απαιτούμε να διαχειρίζεται και \term{memory bitmaps}. Όταν γράφουμε και διαβάζουμε στο \term{default file-system} είναι αυτονόητο να απαιτούμε με τον ίδιο τρόπο να διαχειριζόμαστε και \term{memory sticks}.

Αυτά είναι από τα πλέον τυπικά παραδείγματα που αναλαμβάνει το \PM{} να λύσει. Όμως δεν σταματά εδώ, αλλά επεκτείνετε στο ότι εφόσον κάτι μπορεί να δομηθεί με την κλασσική ιεραρχική δομή των συστημάτων αρχείων τότε είναι αυτονόητο ότι πρέπει να λειτουργεί και έτσι με τις ίδιες εντολές όπως το κλασσικό σύστημα. Όταν έχουμε μια εικόνα είναι αυτονόητο ότι η εικόνα αυτή μπορεί να επεξεργαστεί με την βιβλιοθήκη γραφικών που προσφέρει το ίδιο το \PM{}, και δεν χωρά αντιθέσεις σ' αυτό, εφόσον είναι εικόνα θα πρέπει να αποθηκεύεται / διαβάζεται σε / από όλες τις μορφές με τον ίδιο τρόπο, εφόσον εμφανίζεται στην οθόνη μπορεί και να εκτυπωθεί και να καταγραφεί σε αρχείο.

\subsubsection{Ομαδοποίηση στο \PM{}}

Ποια όμως τμήματα του λογισμικού ταιριάζουν σε τι είδους \term{interface}? 
Το \term{file I/O} βλέπετε, μπορεί να ενσωματώσει σχεδόν τα πάντα, αλλά δεν μπορεί να ικανοποιήσει όλες τις απαιτήσεις ούτε να κάνει το σύστημα τόσο ευέλικτο. Για παράδειγμα πως θα σχεδιάζουμε γραμμές με εντολές \term{read/write}? Σίγουρα μπορούμε, και μπορούμε να έχουμε ένα παραπάνω επίπεδο, που έτσι και αλλιώς ήδη υπάρχει στο \term{pml}, για να χρησιμοποιούμε \term{\lat{line}} αντί για \term{\lat{write}} αλλά δεν θα μπορούσαμε να εκμεταλλευτούμε τον επιταχυντή της κάρτας γραφικών.

\begin{enumerate}
\item \lat{VFS (virtual file system interface)}.
	Το αντίστοιχο \term{module} θα έπρεπε να υποστηρίζει τις \term{file I/O} εντολές.
	Το \term{interface} αυτό έχει δύο επίπεδα, α) σαν αρχείο, β) σαν \term{file system}.
\item \lat{GFX (bitmap and vector graphics interface)}.
	Το αντίστοιχο \term{module} θα έπρεπε να υποστηρίζει εγγραφή
	και ανάγνωση \term{pixels}.
\item \lat{SND (sound interface)}.
	Το αντίστοιχο \term{module} θα έπρεπε να υποστηρίζει εγγραφή
	και ανάγνωση \term{wave}.
\item \lat{PTD (pointing devices interface)}.
	Το αντίστοιχο \term{module} θα έπρεπε να υποστηρίζει θέση και κατάσταση πλήκτρων.
\item \lat{KBD (keyboard interface)}.
	Το αντίστοιχο \term{module} θα έπρεπε να υποστηρίζει πλήκτρα-χαρακτήρες
	και συνδυασμούς αυτών.
\end{enumerate}

\subsection{Ενιαίο τρόπος μεταφοράς δεδομένων}

Το ενιαίο \term{interface} δεν λύνει όμως όλα τα προβλήματα. Αν υποθέσουμε ότι έχουμε μια εικόνα σε μορφή \term{png} και θέλουμε να την μετατρέψουμε σε μορφή \term{jpeg}, θα πρέπει αυτά τα δύο να συνεργάζονται, πράγμα που σημαίνει ότι χρειαζόμαστε και ενιαία μορφή δεδομένων. 

Για παράδειγμα όλες οι εικόνες που επιστρέφονται ή στέλνονται στα \term{modules} είναι απαραίτητο να έχουν συγκεκριμένη μορφή, και αυτή καθορίστηκε να είναι όπως στην \term{Video RAM} αλλά με προκαθορισμένο \term{header} που αναφέρει την ανάλυση και το βάθος χρώματος. Έτσι όλα τα σχετικά με γραφικά \term{modules} ή βιβλιοθήκες ξέρουν επακριβώς με τι και πως να εργαστούν. Αντίστοιχα και για τα διανυσματικά γραφικά (ξέρουμε πολύ καλά ότι κάθε βιβλιοθήκη έχει δικό της ορισμό για το διάνυσμα). Αντίστοιχα και για τον ήχο.


\subsection{Διαχείριση \term{modules}}

Κατ' αρχήν έπρεπε να φτιαχτεί ένα σύστημα που να φορτώνει και να ξεφορτώνει τους \term{drivers} με όσο τον δυνατό ταχύτερο τρόπο και αυτό έγινε με την χρήση ενός \term{daemon} (\defn{pmd}) και μιας βιβλιοθήκης (\defn{pml}) που συνδέεται με την εφαρμογή. Οι \term{drivers} από την άλλη μετατράπηκαν σε \term{shared libraries} (\term{dynamic linked libraries}) γι' αυτό και αποκαλούνται \term{modules}.

Για όλα τα \term{modules} θα έπρεπε να ισχύουν και συγκεκριμένοι κανόνες, όπως

\begin{enumerate}
\item Οι \term{drivers} να φορτώνονται και να ξεφορτώνονται δυναμικά ανάλογα 
	με τα κέφια της εφαρμογής.

\item Οι \term{drivers} να μπορούν να ορίζονται και εξωτερικά, από τον χρήστη.
	Δηλαδή αν ο χρήστης θα ήθελε η έξοδος μιας εφαρμογής αντί για την οθόνη
	να είναι το \term{jpeg driver} αυτό να είναι δυνατό να γίνει.

\item Όλες οι εικόνες που στέλνονται ή επιστρέφουν από ένα \term{driver} να είναι
	πάντα με συγκεκριμένη μορφή και μάλιστα με την πλέον απλή. Αυτό επιτρέπει την
	μετακίνηση και επεξεργασία των δεδομένων από κοινό κώδικα.	
	
\item Όλα τα δεδομένα ήχου που στέλνονται ή επιστρέφουν από ένα \term{driver} να είναι
	πάντα με συγκεκριμένη μορφή και μάλιστα με την πλέον απλή.
	
\end{enumerate}

Το \PM{} έχει και άλλα πράγματα καθώς και υποστηρίζει λειτουργία ανά έκδοση του κάθε \term{interface} (όπου το \term{module} αναφέρει ποια έκδοση και τι \term{interface} υποστηρίζει) καθώς και δικτυακή επικοινωνία κ.α. Δεν θα επεκταθούμε όμως σε αυτά, θέλουμε εδώ να δώσουμε την \dq{φιλοσοφία} του έργου και όχι τον αναλυτικό σχεδιασμό του.

\subsection{Αυτόματη συμπλήρωση συναρτήσεων των \term{modules}}

Πολλά πράγματα που πρέπει να απαιτούνται από το \term{interface} μπορούν να αντικατασταθούν από κοινότυπο κώδικα. Για παράδειγμα η γραμμή στα γραφικά. Δεν χρειάζεται κάθε \term{GFX module} να περιέχει τον αλγόριθμο αυτό, παρά μόνο αν υποστηρίζει κάποιον επιταχυντή. ’λλο ένα παράδειγμα είναι το \term{fgets()} στο \term{VFS}, το οποίο υλοποιήται με κλήσεις στην αντίστοιχη \term{read()}, είναι όμως απαραίτητο να υποστηρίζεται από το \term{VFS interface}.

Σ' αυτές τις περιπτώσεις το \PM{} αναλαμβάνει να συμπληρώσει αυτές τις συναρτήσεις αν αυτές δεν έχουν οριστεί μέσα στο \term{module}. 

Λογικό είναι να περιμένουμε ειδικά από τα γραφικά σε κάποιες περιπτώσεις το \term{module} να περιέχει μόνο τις \term{getpixel} / \term{putpixel} ενώ σε άλλες να θέλει να αντικαταστήσει το μεγαλύτερο μέρος της βιβλιοθήκης γραφικών.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\section{Έτοιμα παραδείγματα}

\subsection{\term{vfstest}}

Το ακόλουθο πρόγραμμα είναι μια τυπική εφαρμογή που χειρίζεται \term{VFS modules}.
Δεν κάνει τίποτα παραπάνω από το να φορτώνει το αντίστοιχο \term{module} που παίρνει σαν παράμετρο και να τυπώνει τα περιεχόμενα ενός από τα εικονικά αρχεία.

Το \term{module-key} και το όνομα του αρχείου δίδονται από τον χρήστη σαν παράμετρο από την κονσόλα.

\latintext
\begin{example}
// vfstest.c
#include <pm_app.h>

int	main(int argc, char *argv[])
{
	int		handle;
	pm_vfs_module	*m;
	
	pm_init();		// initialize PM
	
	if	( argc != 3 )	// arguments
		panic("usage: vfstest module-key open-file");
		
	// load the module
	if	( (m = pm_vfs_load(argv[1])) == NULL )
		panic("Can't load the %s module", argv[1]);
	
	// open the "file"
	if	( (handle = m->open(m->mid, argv[2], 0)) == -1 )
		panic("Can't open the %s file", argv[2]);
	
	// display theirs contents
	while ( m->gets(m->mid, handle, buf, 256) )
		printf("%s", buf);
		
	m->close(m->mid, handle);	// close "file"
	pm_vfs_release(m);			// unload the module
	return 0;
}
\end{example}
\greektext

Μπορούμε τώρα να δούμε εύκολα μερικές από τις δυνατότητες του \PM{}. Θα προτιμούσαμε να είσαστε συνδεδεμένος σαν διαχειριστής (\term{root}) διότι ορισμένα \term{modules}-παραδείγματα έχουν φτιαχτεί για να λειτουργούν με πλήρη δικαιώματα στο σύστημα.

\begin{description}
\item[Παράδειγμα 1]\ \\
	Χρησιμοποιήστε το \term{vfstest} για να δείτε την ώρα από ένα τοπικό 
	ή εξωτερικό (\term{internet}) διακομιστή.

	\latintext	
	\begin{Verbatim}
	# vfstest vfs/telnet localhost:13
	\end{Verbatim}
	\greektext

	Αν η σύνδεση αποτύχει, αυτό σημαίνει ότι δεν έχετε ενεργοποιήσει το 
	\term{timegen service} στο σύστημά σας. Φορτώστε με ένα 
	\term{editor} το αρχείο \file{/etc/inetd.conf} και βγάλτε το \sq{\lat{\#}} 
	από την γραμμή του \term{timegen}. Ξαναφορτώστε το \term{inetd} και προσπαθήστε ξανά.
	
\item[Παράδειγμα 2]\ \\
	Χρησιμοποιήστε το \term{vfstest} για να συνδεθήτε μέσω σειριακής πόρτας
	με ένα άλλο μηχάνημα.
	
	\latintext	
	\begin{Verbatim}
	# vfstest vfs/serial /dev/ttyS1:57600
	\end{Verbatim}
	\greektext
	
	Στο \term{Palm} μου, το δοκίμασα τρέχοντας το πρόγραμμα \file{sertest.bas} που είναι
	παράδειγμα της \term{SB} και ... έστειλα χαρακτήρες στο \term{PC}. Αν το δοκιμάσετε
	θυμηθήτε ότι το \term{vfstest} μόνο διαβάζει δεδομένα άρα το πρόγραμμα που θα συνδεθεί
	(π.χ. \term{Minicom}, \term{Telix}, \term{Procomm}, \term{Hyperterminal}) θα πρέπει
	να αποστέλλει δεδομένα (πλήκτρα που πατάτε).
	
\item[Παράδειγμα 3]\ \\
	Χρησιμοποιήστε το \term{vfstest} για να πάρετε τα στοιχεία ενός χρήστη.

	\latintext	
	\begin{Verbatim}
	# vfstest vfs/users users/root
	\end{Verbatim}
	\greektext
	
	Πληροφορίες, όπως το \term{home directory} και το επιλεγμένο
	\term{shell} του χρήστη \term{root} θα πρέπει να εμφανιστούν στην κονσόλα σας.
\end{description}

\subsection{Συνοδευτικά παραδείγματα -- εφαρμογές}

Από το \term{CVS} μπορείτε να κατεβάσετε περισσότερα παραδείγματα. Τα παραδείγματα αυτά βρίσκονται στον κατάλογο \term{apps}.

...(λίστα και μια περιγραφή)...

\subsection{Συνοδευτικά παραδείγματα -- \term{modules}}

...(λίστα και μια περιγραφή)...

%%%%%%%%%
\section{Θεωρητικά παραδείγματα}

Προσωρινά τα ονομάζουμε \dq{θεωρητικά} διότι απλούστατα δεν έχουμε κάτσει ακόμα να τα φτιάξουμε. Δηλαδή δεν έχουμε αμφιβολία ότι μπορούμε, απλά δεν το έχουμε κάνει ακόμα.

\subsection{Ένας \term{e-mail client} που λειτουργεί σαν σύστημα αρχείων}

...

\subsection{Ένα παντοδύναμο εργαλείο με λίγο κώδικα}

...

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{thebibliography}{}

\bibitem[\lat{Bazaar}]{bazaar}
	\biblatf
	{The Cathedral and the Bazaar}
	{Eric S. Raymond}
	{1998/08/11 20:27:29}

\bibitem[\lat{CrqAPI}]{wapi}
	\biblatf
	{A Critique of the Windows Application Programming Interface}
	{Diomidis Spinellis}
	{University of the Aegean, Dec. 1997}

\bibitem[ΕΔΕΤ-Γ4]{edetg4}
	\bibgrf
	{Ελεύθερο Λογισμικό / Λογισμικό Ανοικτού Κώδικα (ΕΛ/ΛΑΚ) στην Εκπαίδευση,
	τη Δημόσια Διοίκηση και στις Επιχειρήσεις Μικρού / Μεσαίου Μεγέθους.}
	{Ομάδα Εργασίας OE Γ4}
	{Εθνικό Δίκτυο Έρευνας \& Τεχνολογίας, Αθήνα, Ιαν. 2003}
	
%\bibitem[\lat{W95S}]{w95s}
%	\biblatf
%	{Windows 95 System Programming Secrets}
%	{Matt Pietrek}
%	{IDG Books, Nov. 1995}

\bibitem[\lat{LPLib}]{plhow}
	\biblatf
	{Program Library HOWTO}
	{David A. Wheeler}
	{LDP, ver 1.07, 30 December 2002}

\end{thebibliography}

\section*{Ευχαριστίες}
\begin{description}
\item[Δημήτριο Κουκοράβα και Γιάννη Βλαχογιάννη]\ \\
Το πείσμα του Δημήτρη πάνω στο \PM{} -- είχα και έχω σκοπό να μην ασχολούμαι με το \term{arm0nia project} -- αλλά και η εκνευριστική επιμονή του, είναι ο λόγος ύπαρξης αυτού του εγγράφου. Για τα κρασιά που κεράσανε, και για τις ιδέες που αναπτύξαμε και οι τρεις από κοινού κάτω από αρκετές ώρες αμπελοφιλοσοφίας (το αγαπημένο μου σπορ).
\end{description}

\label{EOF}
\end{document}
