From: Simone Piccardi Date: Mon, 5 Mar 2001 22:20:07 +0000 (+0000) Subject: Initial revision X-Git-Tag: restart~2 X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=3d44c36183fe67ed64bff95a36596ad87f620683 Initial revision --- diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e343f4c --- /dev/null +++ b/ChangeLog @@ -0,0 +1,32 @@ +2001-02-27 Simone Piccardi + + * network.tex: completata (si fa per dire) la parte introduttiva. + + * files.tex: finita tutta l'introduzione, su come il kernel + maneggia i file, su quali sono i vari tipi di file e i vari + concetti associati. Adesso si può passare alle API. + + * process.tex: scritto una prima parte di introduzione, definiti + genitori e figli, e messo un po' di struttura. + + * intro.tex: sistemata: la base c'è, adesso può essere migliorata + ed espansa, ma per il momento la lascerò stare. + +2001-02-22 Simone Piccardi + + * intro.tex: tolta roba rete, quasi completata l'introduzione, + aggiunti utenti e gruppi + + * network.tex: messo qui la roba sulla rete + + * files.tex: quasi finita introduzione sul VFS + +2000-12-30 Simone Piccardi + + * pref.tex: Versione iniziale + + * main.tex: Versione iniziale (beh, diciamo la prima che mi sono + ricordato di commentare) + + * intro.tex: Versione iniziale + diff --git a/fdl.tex b/fdl.tex new file mode 100644 index 0000000..16231dc --- /dev/null +++ b/fdl.tex @@ -0,0 +1,338 @@ +% fdl.tex +% This file is a chapter. It must be included in a larger document to work +% properly. + +\chapter{GNU Free Documentation License} + +Version 1.1, March 2000\\ + + Copyright \copyright\ 2000 Free Software Foundation, Inc.\\ + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\\ + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +\section*{Preamble} + +The purpose of this License is to make a manual, textbook, or other +written document ``free'' in the sense of freedom: to assure everyone +the effective freedom to copy and redistribute it, with or without +modifying it, either commercially or noncommercially. Secondarily, +this License preserves for the author and publisher a way to get +credit for their work, while not being considered responsible for +modifications made by others. + +This License is a kind of ``copyleft'', which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + +\section{Applicability and Definitions} + +This License applies to any manual or other work that contains a +notice placed by the copyright holder saying it can be distributed +under the terms of this License. The ``Document'', below, refers to any +such manual or work. Any member of the public is a licensee, and is +addressed as ``you''. + +A ``Modified Version'' of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A ``Secondary Section'' is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (For example, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The ``Invariant Sections'' are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. + +The ``Cover Texts'' are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. + +A ``Transparent'' copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, whose contents can be viewed and edited directly and +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup has been designed to thwart or discourage +subsequent modification by readers is not Transparent. A copy that is +not ``Transparent'' is called ``Opaque''. + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, \LaTeX~input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML designed for human modification. Opaque formats include +PostScript, PDF, proprietary formats that can be read and edited only +by proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML produced by some word processors for output +purposes only. + +The ``Title Page'' means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, ``Title Page'' means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + + +\section{Verbatim Copying} + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +\section{Copying in Quantity} + +If you publish printed copies of the Document numbering more than 100, +and the Document's license notice requires Cover Texts, you must enclose +the copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a publicly-accessible computer-network location containing a complete +Transparent copy of the Document, free of added material, which the +general network-using public has access to download anonymously at no +charge using public-standard network protocols. If you use the latter +option, you must take reasonably prudent steps, when you begin +distribution of Opaque copies in quantity, to ensure that this +Transparent copy will remain thus accessible at the stated location +until at least one year after the last time you distribute an Opaque +copy (directly or through your agents or retailers) of that edition to +the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + + +\section{Modifications} + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +\begin{itemize} + +\item Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +\item List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has less than five). +\item State on the Title page the name of the publisher of the + Modified Version, as the publisher. +\item Preserve all the copyright notices of the Document. +\item Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +\item Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +\item Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +\item Include an unaltered copy of this License. +\item Preserve the section entitled ``History'', and its title, and add to + it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section entitled ``History'' in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +\item Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the ``History'' section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +\item In any section entitled ``Acknowledgements'' or ``Dedications'', + preserve the section's title, and preserve in the section all the + substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +\item Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +\item Delete any section entitled ``Endorsements''. Such a section + may not be included in the Modified Version. +\item Do not retitle any existing section as ``Endorsements'' + or to conflict in title with any Invariant Section. + +\end{itemize} + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section entitled ``Endorsements'', provided it contains +nothing but endorsements of your Modified Version by various +parties -- for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +\section{Combining Documents} + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections entitled ``History'' +in the various original documents, forming one section entitled +``History''; likewise combine any sections entitled ``Acknowledgements'', +and any sections entitled ``Dedications''. You must delete all sections +entitled ``Endorsements.'' + + +\section{Collections of Documents} + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + + + +\section{Aggregation With Independent Works} + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, does not as a whole count as a Modified Version +of the Document, provided no compilation copyright is claimed for the +compilation. Such a compilation is called an ``aggregate'', and this +License does not apply to the other self-contained works thus compiled +with the Document, on account of their being thus compiled, if they +are not themselves derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one quarter +of the entire aggregate, the Document's Cover Texts may be placed on +covers that surround only the Document within the aggregate. +Otherwise they must appear on covers around the whole aggregate. + + +\section{Translation} + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License provided that you also include the +original English version of this License. In case of a disagreement +between the translation and the original English version of this +License, the original English version will prevail. + + +\section{Termination} + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document is void, and will +automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such +parties remain in full compliance. + + +\section{Future Revisions of This License} + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. + diff --git a/files.tex b/files.tex new file mode 100644 index 0000000..17878c5 --- /dev/null +++ b/files.tex @@ -0,0 +1,394 @@ +\chapter{I files} +\label{cha:files} + +Uno dei concetti fondamentali del design di unix è il cosiddetto +\textit{everything is a file}, cioè il fatto che l'accesso alle periferiche +viene gestito attraverso un'interfaccia astratta che tratta nello stesso modo +sia i normali file di dati che le periferiche. Si può accedere cioè a queste +ultime (con l'eccezione delle interfacce di rete) attraverso i cosiddetti file +di dispositivo (i \textit{device files}) che permettono ai programmi di +interfacciarsi alle varie periferiche come la seriale, la parallela, la +console, e gli stessi dischi. + +\section{Concetti generali sui files} +\label{sec:file_gen} + +Per poter accedere ai singoli file su disco è necessario l'uso di un +\textit{filesystem}, cioè di un'interfaccia del kernel che permetta di +strutturare l'informazione tenuta sullo spazio grezzo disponibile sui dischi +in files e directory. Sarà quest'ultimo a gestire l'accesso ai dati +memorizzati all'interno del disco stesso, e l'uso delle normali directory e +files. + +%In generale un filesystem piazzerà opportunamente sul disco dei blocchi di +%informazioni riservate che tengono conto degli inodes allocati, di quelli +%liberi, e delle posizioni fisiche su disco dei dati contenuti nei files, per + +Per poter accedere ai file contenuti in un disco occorrerà poi attivare il +filesystem \textit{montando} il disco (o la partizione del disco). + +In unix, a differenza di quanto avviene in altri sistemi operativi, tutti i +file vengono tenuti all'interno di un unico albero la cui radice (la directory +di \textit{root}) viene montata all'avvio. Pertanto un file viene identificato +dall'utente usando il suo \textit{pathname}, cioè il percorso completo che si +deve fare a partire dalla radice, per accedere al file. + +Dopo la fase di inizializzazione il kernel riceve dal boot loader +l'indicazione di quale dispositivo contiene il filesystem da usare come punto +di partenza e questo viene montato come radice dell'albero (cioè nella +directory \texttt{/}); tutti gli ulteriori dischi devono poi essere inseriti +nell'albero utilizzando opportune sottodirectory (in genere sotto +\texttt{/mnt}) . + +Alcuni filesystem speciali (come \texttt{/proc} che contiene un'interfaccia ad +alcune strutture interne del kernel) sono generati automaticamente dal kernel +stesso, ma anche essi devono essere montati all'interno dell'albero. + +All'interno dello stesso albero si potranno poi inserire anche gli altri +oggetti visti attraverso l'interfaccia che manipola i files come le FIFO, i +link, i socket e gli stessi i file di dipositivo (questi ultimi, per +convenzione, sono inseriti nella directory \texttt{/dev}). + +\subsection{Il \textit{virtual filesystem} di linux} +\label{sec:file_vfs} + +Esamineremo adesso come viene implementato l'accesso ai files in linux. Questa +sezione riporta informazioni sui dettagli di come il kernel gestisce i files, +ed è basata sul documento di Richard Goochs distribuito coi sorgenti del +kernel (\texttt{linux/Documentation/vfs.txt}). + +L'argomento è abbastanza ``esoterico'' e questa sezione può essere saltata ad +una prima lettura; è bene però tenere presente che vengono intodotti qui +alcuni termini che potranno comparire in seguito, come \textit{imode}, +\textit{dentry}, \textit{dcache}. + +In linux il concetto di \textit{everything is a file} è stato implementato +attraverso il \textit{virtual filesystem} (da qui in avanti VFS) che è +l'interfaccia astratta che il kernel rende disponibile ai programmi in user +space attraverso la quale vengono manipolati i files, esso provvede anche +un'astrazione delle operazioni di manipolazione sui files che permette la +coesistenza di diversi filesystem all'interno dello stesso kernel. + +La funzione più importante implementata dal VFS è la system call \texttt{open} +che permette di aprire un file. Dato un pathname viene eseguita una ricerca +dentro la \textit{directory entry cache} (la \textit{dcache}) una tabella di +hash che contiene tutte le \textit{directory entry} (in breve \textit{dentry}) +che permette di associare in maniera rapida ed efficiente il pathname a una +specifica dentry. + +Una singola dentry contiene in genere il puntatore ad un \textit{inode}; +quest'ultimo è la struttura base che sta sul disco e che identifica un singolo +oggetto del VFS che può essere un file, una directory, una FIFO, un file di +dispositivo, o una qualsiasi altra cosa che possa essere rappresentata dal +VFS (sui tipi di files possibili torneremo in seguito). + +Le dentries ``vivono'' in memoria e non vengono mai salvate su disco, vengono +usate per motivi di velocità, gli inodes invece vivono su disco e vengono +copiati in memoria quando serve, ed ogni cambiamento viene copiato +all'indietro sul disco, gli inodes che stanno in memoria sono inodes del VFS +ed è ad essi che puntano le singole dentry. + +La dcache costituisce perciò una sorta di vista completa di tutto l'albero dei +files, ovviamente per non riempire tutta la memoria questa vista è parziale +(la dcache cioè contiene solo le dentry per i file per i quali è stato +richiesto l'accesso), quando si vuole risolvere un nuovo pathname il VFS deve +creare una nuova dentry e caricare l'inode corrispondente in memoria. + +Questo procedimento viene eseguito dalla metodo \texttt{lookup()} dell'inode +della directory che contiene il file; esso viene installato dallo specifico +filesystem su cui l'inode va a vivere. + +Una volta che il VFS ha a disposizione la dentry (ed il relativo inode) +diventa possibile accedere a operazioni sul file come la \texttt{open} per +aprire il file o la \texttt{stat} per leggere i dati dell'inode e passarli in +user space. + +L'apertura di un file richiede comunque un'altra operazione, l'allocazione di +una struttura di tipo \texttt{file} in cui viene inserito un puntatore alla +dentry e una struttura \verb|f_ops| che contiene i puntatotori ai metodi che +implementano le operazioni disponibili sul file. In questo modo i processi in +use space possono accedere alle operazioni attraverso detti metodi, che +saranno diversi a seconda del tipo di file (o dispositivo) aperto. Un elenco +delle operazioni disponibili è riportato in \ntab. + +% La struttura file viene poi inserita nella tavola dei file +% , non +% tutte le operazioni possibili sono definite per tutti i dispositivi; un elenco +% delle operazioni definite in linux è riportato in \ntab. + +\begin{table}[htb] + \centering + \begin{tabular}[c]{c l} + \textbf{funzione} & \textbf{operazione} \\ + \hline + open & apre il file \\ + read & legge dal file \\ + write & scrive sul file \\ + llseek & sposta la posizione corrente sul file \\ + ioctl & accede alle operazioni di controllo (tramite la \texttt{ioctl})\\ + readdir & per leggere il contenuto di una directory \\ + poll & \\ + mmap & chiamata dalla system call \texttt{mmap} \\ + release & chiamata quando l'ultima referenza a un file aperto è chiusa\\ + fsync & chiamata dalla system call \texttt{fsync} \\ + fasync & chiamate da \texttt{fcntl} quando è abilitato il modo asincrono + per l'I/O su file. \\ + \hline + \end{tabular} + \caption{Operazioni sui file definite nel VFS.} + \label{tab:file_operations} +\end{table} + +In questo modo per ciascun file diventano utilizzabili una serie di operazioni +(non è dette che tutte siano disponibili), che costituiscono l'interfaccia +astratta del VFS, e qualora se ne voglia eseguire una il kernel andrà ad +utilizzare la opportuna routine dichiarata in \verb|f_ops| appropriata al tipo +di file in questione. + +Così sarà possibile scrivere sulla porta seriale come su un file di dati +normale; ovviamente certe operazioni (nel caso la \textit{seek}) non saranno +disponibili, però con questo sistema l'utilizzo di diversi filesystem è +immediato e (relativamente) trasparente per l'utente ed il programmatore. + +\subsection{Proprietari e permessi} +\label{sec:file_perms} + +In unix è implementata da qualunque filesystem standard una forma elementare +(ma adatta alla maggior parte delle esigenze) di controllo di accesso ai +files. Torneremo sull'argomento in dettaglo più avanti, qui ci limitiamo ad +una introduzione dei concetti essenziali. + +Si tenga conto poi che quanto diremo è vero solo per filesystem di tipo unix, +e non è detto che sia applicabile (ed infatti non è vero per il filesystem di +windows) a un filesystem qualunque. Esistono inoltre estensioni che permettono +di implementare le ACL (\textit{Access Control List}) che sono un meccanismo +di controllo di accesso molto più sofisticato. + +Ad ogni file unix associa sempre l'utente che ne è proprietario (il cosiddetto +\textit{owner}) e il gruppo di appartenenza, secondo il meccanismo degli uid e +gid spiegato in \ref{sec:intro_usergroup}, e un insieme di permessi che sono +divisi in tre classi, e cioè attribuiti rispettivamente al proprietario, a +qualunque utente faccia parte del gruppo cui appartiene il file, e a tutti gli +altri utenti. + +I permessi sono espressi da un insieme di 12 bit, di questi i nove meno +significativi sono usati a gruppi di tre per indicare i permessi base di +lettura, scrittura ed esecuzione (indicati rispettivamente con le lettere +\textit{w}, \textit{r} \textit{x}) applicabili rispettivamente al +proprietario, al gruppo, a tutti. I restanti tre bit sono usati per indicare +alcune caratteristiche più complesse (\textit{suid}, \textit{sgid}, e +\textit{sticky}) su cui torneremo in seguito. + +Tutte queste informazioni sono tenute per ciascun file nell'inode. Quando un +processo cerca l'accesso al file esso controlla i propri uid e gid +confrontandoli con quelli del file e se l'operazione richiesta è compatibile +con i permessi associati al file essa viene eseguita, altrimenti viene +bloccata ed è restituito un errore di \texttt{EPERM}. Questo procedimento non +viene eseguito per l'amministratore di sistema (il cui uid è zero) il quale ha +pertanto accesso senza restrizione a qualunque file del sistema. + +In realtà il procedimento è più complesso di quanto descritto in maniera +elementare qui, in quanto ad un processo sono associati diversi +identificatori, torneremo su questo in maggiori dettagli in seguito in +\ref{sec:proc_perms}. + +\subsection{I tipi di files} +\label{sec:file_types} + +Come detto in precedenza esistono vari tipi di oggetti implementati del VFS +per i quali è disponibile l'interfaccia astratta da esso provveduta. Un elenco +dei vari tipi di file è il seguente: + +\begin{table}[htb] + \begin{center} + \begin{tabular}[c]{l l l} + \textit{regular file} & \textsl{file normale} & + un file che contiene dei dati (l'accezione normale di file) \\ + \textit{directory} & \textsl{cartella o direttorio} & + un file che contiene una lista di nomi associati a degli inodes \\ + \textit{symbolic link} & \textsl{collegamento simbolico} & + un file che contiene un riferimento ad un altro file/directory \\ + \textit{char device} & \textsl{dispositivo a caratteri} & + un file che identifica una periferica ad accesso sequenziale \\ + \textit{block device} & \textsl{dispositivo a blocchi} & + un file che identifica una periferica ad accesso diretto \\ + \textit{fifo} & \textsl{tubo} & + un file speciale che identifica una linea di comunicazione software + (unidirezionale) \\ + \textit{socket} & \textsl{presa} + un file speciale che identifica una linea di comunicazione software + (bidirezionale) \\ + \end{tabular} + \caption{Tipologia dei file definiti nel VFS} + \label{tab:file_types} + \end{center} +\end{table} + +Tutto ciò non ha ovviamente nulla a che fare con la classificazione sui tipi +di file (in questo caso file di dati) in base al loro contenuto, o tipo di +accesso. Una delle differenze principali con altri sistemi operativi (come il +VMS o windows) è che per unix tutti i file di dati sono identici e contengono +un flusso continuo di bytes; non esiste cioè differenza per come vengono visti +dal sistema file di diverso contenuto o formato (come nel caso di quella fra +file di testo e binari che c'è in windows) né c'è una strutturazione a record +per il cosiddetto ``accesso diretto'' come nel caso del VMS. + +Una seconda differenza è nel formato dei file ascii; in unix la fine riga è +codificata in maniera diversa da windows o macintosh, in particolare il fine +riga è il carattere \texttt{LF} al posto del \texttt{CR} del mac e del +\texttt{CR LF} di windows. Questo può causare alcuni problemi qualora si +facciano assunzioni sul terminatore della riga. + + +\section{Una panoramica sull'I/O sui file} +\label{sec:file_io_base} + +Per poter accedere al contenuto dei file occorre anzitutto aprirlo. Questo +crea un canale di comunicazione che permette di eseguire una serie di +operazioni. Una volta terminate le operazioni, il file dovrà essere chiuso, e +questo chiuderà il canale di comuniczione impedendo ogni ulteriore operazione. + + +\subsection{Le due interfacce ai file} +\label{sec:file_base_api} + +In unix le modalità di accesso ai file e le relative insterfacce di +programmazione sono due, basate su due diversi meccanismi di connessione. + +La prima è quella dei cosiddetti \textit{file descriptor} (descrittore di +file), che è specifica di unix e che provvede un accesso diretto a basso +livello non bufferizzato, con un'interfaccia primitiva ed essenziale; i file +descriptors sono rappresetati da numeri interi (cioè semplici variabili di +tipo \texttt{int}). L'interfaccia è definita nell'header \texttt{unistd.h}. + +La seconda è quella degli \textit{stream}, che provvede un'interfaccia più +complessa e un'accesso bufferizzato, questa è anche l'intefaccia standard +usata dal linguaggio C e che perciò si trova anche su tutti i sistemi non +unix. Gli stream sono più complessi e sono rappresentati da puntatori ad un +opportuno oggetto, cioè del tipo \texttt{FILE *}. L'interfaccia è definita +nell'header \texttt{stdio.h}. + +Entrambe le interfacce possono essere usate per l'accesso ai file come agli +altri oggetti del VFS (pipes, socket, device), ma per poter accedere alle +operazioni di controllo sul particolare tipo di oggetto del VFS scelto occorre +usare l'interfaccia a basso livello dei file descriptor. Allo stesso modo +devono essere usati i file descriptor se si vuole ricorrere a modalità +speciali di I/O come il polling o il non-bloccante (vedi \ref{sec:file_bohhhhh}). + +Gli stream però forniscono un'interfaccia di alto livello costruita sopra +quella dei file descriptor, e tratta tutti i file nello stesso modo, con +l'eccezione di poter scegliere tre diversi stili di bufferizzazione. Il +maggior vantaggio degli stream è che l'interfaccia per le operazioni di +input/output è enormemente più ricca di quella dei file descriptor, che +provvedono solo funzioni elementari per la lettura/scrittura diretta di +blocchi di bytes. In particolare dispongono di tutte le funzioni di +formattazione per l'input e l'output adatte per manipolare anche i dati in +forma di linee o singoli caratteri. + +In ogni caso, dato che gli stream sono implementati sopra l'interfaccia a +basso livello dei file decriptor, è sempre possibile extrarre il file +descriptor da uno stream ed eseguirvi operazioni di basso livello, o associare +in un secondo tempo uno stream ad un file descriptor. + +In generale, se non necessitano specificamente le funzionalità di basso +livello, è opportuno usare sempre gli stream per la loro maggiore portabilità +essendo questi ultimi definito nello stadard ISO C; l'interfaccia con i file +descriptor invece segue solo lo standard POSIX.1 dei sistemi unix ed è +pertanto di portabilità più limitata. + +\subsection{Caratteristiche specifiche dei file in unix} +\label{sec:files_spec_unix} + +Essendo un sistema multitasking e multiutente esistono alcune caratteristiche +specifiche di unix che devono essere tenute in conto nell'acceso ai file. È +infatti normale che più processi o programmi possano accedere +contemporaneamente allo stesso file e devono poter eseguire le loro operazioni +indipendentemente da quello che fanno gli altri processi. + +Per questo motivo le strutture usate per all'accesso ai file sono relative al +processo che effettua l'accesso. All'apertura di ogni file infatti viene +creata all'interno del processo una apposita struttura in cui sono memorizzati +tutti gli attributi del medesimo, che viene utilizzata per tutte le +operazioni. Questa è una struttura che resta locale al processo stesso; in +questo modo processi diversi possono usare le proprie strutture locali per +accedere ai file (che può essere sempre lo stesso) in maniera assolutamente +indipendente. + +Questo ha delle conseguenze di cui è bene tenere conto; ad esempio in tutti i +sistemi POSIX uno degli attibuti di un file aperto è la posizione corrente nel +file, cioè il punto nel file in cui verrebbe letto o scritto alla operazione +successiva. Essa è rappresentata da un numero intero che indica il numero di +bytes dall'inizio del file, che viene (a meno che non si apra il file in +append) inizializzato a zero all'apertura del medesimo. + + +Questo è uno dei dati che viene mantento nella suddetta struttura, per cui +ogni processo avrà la sua posizione corrente nel file, che non sarà +influenzata da quello che altri processi possono fare. Anzi, aprire un file +significa appuntio creare ed inizializzare una tale struttura, per cui se si +apre due volte lo stesso file all'interno dello stesso processo, si otterrano +due file descriptor o due stream che avreanno ancora un posizione corrente nel +file assolutamente independente. + +Si tenga conto inoltre che un'altro dei dati contenuti nella struttura di +accesso è un riferimento all'inode del file, pertanto anche se il file viene +cancellato da un altro processo, sarà sempre possibile mantenere l'accesso, +e lo spazio su disco non verrà rilasciato fintanto che il file non sarà chiuso +e l'ultimo riferimento cancellato. È pertanto possibile (e pratica comune) +aprire un file provvisorio per cancellarlo immediatamente dopo; in questo modo +all'uscita del programma il file scomparità definitivamente dal disco, ma il +file ed il suo contenuto saranno disponibili per tutto il tempo in cui il +processo è attivo. + + +\subsection{L'accesso ai files: nomi e direcory} +\label{sec:file_names} + +L'organizzazione dei nomi dei file deriva direttamente dall'organizzazione dei +medesimi nella gerarchia di directory descritta in \ref{sec:file_base}; una +directory comunque, come già specificato in \ref{sec:file_vfs}, è solo un +particolare tipo di file che il sistema riconosce come tale, che contiene le +informazioni che associano un inode ad un nome. Per questo, anche se è usuale +parlare di ``file in una directory'' in realtà una directory contiene solo dei +riferimenti ai file, non i file stessi. + +I nomi contenuti nelle directory sono chiamati componenti (\textit{file name + components}), un file può essere indicato rispetto alla directory corrente +semplicemente specificando il nome da essa contenuto. Una directory contiene +semplicemente un elenco di questi componenti, che possono corrispondere a un +qualunque oggetto del filesystem, compresa un'altra directory. + +Un nome di file è composto da una serie di componenti separati da una +\texttt{/} (in linux più \texttt{/} consecutive sono considerate equivalenti +ad una sola). Il nome completo di un file viene usualmente chiamato +\textit{pathname}, anche se questo può generare confusione, dato che con +\textit{path} si indica anche un insieme di directory su cui effettuare una +ricerca (ad esempio quello in cui si cercano i comandi). + +Il processo con cui si associa ad un pathname uno specifico file (cioè si +identifica l'inode a cui fare riferimento) è chiamato risoluzione del nome +(\textit{file name resoluzion} o \textit{pathname resolution}). +La risoluzione viene fatta esaminando il pathname da destra a sinistra e +localizzando ogni componente nella directory indicata dal componente +precedente: ovviamente perchè il procedimento funzioni occorre che i +componenti indicati come directory esistano e siano effettivamente directory, +inoltre i permessi devono consenite l'accesso. + + +Se il pathname comincia per \texttt{/} la ricerca parte dalla directory radice +del processo che (a meno di un \textit{chroot} su cui torneremo in seguito) è +la stessa per tutti i processi ed equivale alla radice dell'albero +(\ref{sec:file_gen}): in questo caso si parla di un pathname +\textsl{assoluto}. Altrimenti la ricerca parte dalla directory di lavoro +corrente (\texit{current working directory}, su cui pure torneremo più avanti) +ed il pathname è detto \textsl{relativo}. + +I componenti \texttt{.} e \texttt{..} hanno un significato speciale e vengono +inseriti in ogni directory; + + +%La struttura fondamentale che contiene i dati essenziali relativi ai file è il +%cosiddetto \textit{inode}; questo conterrà informazioni come il +%tipo di file (file di dispositivo, directory, file di dati, per un elenco +%completo vedi \ntab), i permessi (vedi \ref{sec:file_perms}), le date (vedi +%\ref{sec:file_times}). diff --git a/intro.tex b/intro.tex new file mode 100644 index 0000000..3908ff1 --- /dev/null +++ b/intro.tex @@ -0,0 +1,200 @@ +\chapter{Introduzione} + +In questo primo capitolo sarà fatta un'introduzione ai contetti generali su +cui è basato un sistema di tipo unix, per fornire una base di comprensione +mirata a sottolinearne le peculiarità che saranno poi importanti per quello +che rigarda la programmazione; in particolare faremo una panoramica sulla +struttura di un sistema \textit{unix-like} come Linux. + +Chi avesse già una conoscenza di questa materia può tranquillamente saltare +il capitolo. + +\section{La struttura di un sistema Unix} +\label{sec:unix_struct} + +Il concetto base di unix é quello di un nucleo del sistema (il cosiddetto +\textit{kernel}) a cui si demanda la gestione delle risorse essenziali (la +CPU, la memoria, le periferiche); mentre tutto il resto, quindi anche la parte +che prevede l'interazione con l'utente, deve venire realizzato tramite +programmi eseguiti dal kernel e che accedano alle risorse hardware tramite +delle richieste a quest'ultimo. + +Fin dall'inizio unix si presenta come un sistema operativo +\textit{multitasking}, cioé in grado di eseguire contemporaneamente più +programmi, e multiutente, in cui é possibile che più utenti siano connessi ad +una macchina eseguendo più programmi ``in contemporanea'' (in realtà, almeno +per macchine a processore singolo, i programmi vengono eseguiti singolarmente +a rotazione). + +% Questa e' una distinzione essenziale da capire, +%specie nei confronti dei sistemi operativi successivi, nati per i personal +%computer (e quindi per un uso personale), sui quali l'hardware (allora +%limitato) non consentiva la realizzazione di un sistema evoluto come uno unix. + +Gli unix più recenti, come linux, sono stati realizzati usando alcune +caratteristiche dei processori moderni come la gestione hardware della memoria +e la modalità protetta. In sostanza con i processori moderni si può +disabilitare temporaneamente l'uso di certe istruzioni e l'accesso a certe +zone di memoria fisica. Quello che succede é che il kernel é il solo +programma ad essere eseguito in modalità privilegiata, con il completo accesso +all'hardware, mentre i programmi normali vengono eseguiti in modalità protetta +(e non possono accedere direttamente alle zone di memoria riservate, al kernel +o alle porte di input/output). + +Una parte del kernel, lo \textit{scheduler}, si occupa di stabilire, ad +intervalli fissi e sulla base di un opportuno calcolo delle priorità, quale +``processo'' (vedi \ref{cha:process}) deve essere posto in esecuzione (il +cosidetto \textit{prehemptive scheduling}, e questo verrà comunque eseguito in +modelità protetta; quando necessario il processo potrà accedere alle risorse +hardware soltanto attraverso delle opportune chiamate al sistema +(\textit{system call}) con un'interfaccia ben definita che restituiranno il +controllo al kernel. + +La memoria viene sempre gestita del kernel attraverso il meccanismo della +memoria virtuale, che consente di assegnare a ciascun processo uno spazio di +indirizzi ``virtuale'' che il kernel stesso, con l'ausilio della unità di +gestione della memoria, si incaricherà di rimappare automaticamente sulla +memoria disponibile, salvando su disco (nella cosiddetta \textit{swap}) quando +necessario le pagine di memoria in eccedenza. + +Le periferiche infine vengono viste in genere attraverso un'interfaccia +astratta che permette di trattarle come fossero file. secondo il concetto per +cui \textit{everything is a file}, vedi \ref{sec:file_gen}, (questo non è vero +per le interfacce di rete, ma resta valido il caoncetto generale che tutto il +lavoro di accesso e gestione a basso livello è effettuato dal kernel), mentre +ai programmi vengono fornite solo delle routine di interfacciamento; essendo +l'argomento principale di cui tratteremo, di esse parleremo in abbondanza nei +capitoli successivi. + + +\section{User space e kernel space} +\label{sec:intro_userkernel} + +Questa architettura fa sì che nei sistemi unix esista una distinzione +essenziale fra il cosiddetto \textit{user space}, che contraddistingue +l'ambiente in cui vengono eseguiti i programmi, e il \textit{kernel space} che +é l'ambiente in cui viene eseguito il kernel. Ogni programma gira come se +avesse la piena disponibilità della macchina e della memoria ed è, salvo i +meccanismi di comunicazione previsti dall'architettura (che esamineremo in +\ref{cha:IPC}) completamente ignaro del fatto che altri programmi possono +essere messi in esecuzione dal kernel. + +In questo non è possibile ad un singolo programma disturbare l'azione di un +altro programma o del sistema e questo è il principale motivo della stabilità +di un sistema unix nei confronti di altri sistemi in cui i processi non hanno +di questi limiti, o che vengono per vari motivi eseguiti al livello del +kernel. + +Pertanto deve essere chiaro a chi programma in unix che l'accesso diretto +all'hardware non può avvenire se non all'interno del kernel, al di fuori dal +kernel il programmatore deve usare le opportune interfacce che quest'ultimo +fornisce allo user space. + +In genere queste vanno sotto il nome di chiamate al sistema (le cosiddette +\textit{system call}), cioè un insieme di routine che un programma può +chiamare per le quali viene generata una interruzione del medesimo e il +controllo è passato dal programma al kernel, il quale (oltre a fare una serie +di altre cose come controllare a quale processo tocca essere messo in +esecuzione) eseguirà la funzione richiesta in kernel space passando indietro i +risultati. + +È da chiarire poi che di solito i programmi non chiamano direttamente le +singole system call, ma usano un insieme di funzioni standard (definite dallo +standard internazionale POSIX1003.a(?)) che sono comuni a tutti gli unix. + + +\section{Il kernel e il resto} +\label{sec:intro_kernandlib} + +Per capire meglio la distinzione fra kernel space e user space si può prendere +in esame la procedura di avvio di un sistema unix; all'avvio il bios (o in +generale il software di avvio posto nelle eprom) eseguirà il \textit{boot} +incarichandosi di caricare il kernel in memoria e di farne partire +l'esecuzione; quest'ultimo, dopo aver inizializzato le periferiche farà +partire il primo processo, \textit{init} che è quello che si incaricherà di +far partire tutti i processi successivi, come quello che si occupa di +dialogare con la tastiera e lo schermo della console, mettendo a disposizione +dell'utente che si vuole collegare un terminale e la stessa \textit{shell} da +cui inviare i comandi. + +E' da rimarcare come tutto ciò, che usualmente viene visto come parte del +sistema, non abbia in realtà niente a che fare con il kernel, ma sia +effettuato da opportuni programmi che vengono eseguiti, allo stesso modo di un +programma di scrittura o di disegno, in user space. + +Questo significa ad esempio che il sistema di per sé non dispone di primitive +per tutta una serie di operazioni (come la copia di un file) che altri sistemi +(come windows) hanno invece al loro interno. Per questo può capitare che +alcune operazioni, come quella in esempio, siano implementate come normali +programmi. + +%Una delle caratteristiche base di unix \`e perci\`o che \`e possibile +%realizzare un sistema di permessi e controlli che evitano che i programmi +%eseguano accessi non autorizzati. + +Per questo motivo è più corretto parlare di sistema GNU/Linux, in quanto da +solo il kernel è assolutamente inutile, quello che costruisce un sistema +operativo utilizzabile è la presenza di tutta una serie di librerie e +programmi di utilità che permettono di eseguire le normali operazioni che ci +si aspetta da un sistema operativo. + +Questo è importante anche dal punto di vista della programmazione, infatti +programmare in linux significa anzitutto essere in grado di usare la Libreria +Standard del C, in quanto né il kernel né il linguaggio C implementano +direttamente operazioni comuni come la gestione della memoria, l'input/output +o la manipolazione delle stringhe presenti in qualunque programma. + +Per questo in linux una parte essenziale del sistema (senza la quale nulla +funziona) è la realizzazione fatta dalla FSF della suddetta libreria (la +\textit{glibc}), in cui sono state implementate tutte le funzioni essenziali +definite negli standard POSIX e ANSI C, che viene utilizzata da qualunque +programma. + + +\section{Utenti e gruppi, permessi e protezioni} +\label{sec:intro_usergroup} + +Unix nasce fin dall'inizio come sistema multiutente, cioè in grado di fare +lavorare più persone in contemporanea. Per questo esistono una serie di +meccanismi base di sicurezza che non sono previsti in sistemi operativi +monoutente. + +Il concetto base è quello di utente (\textit{user}) del sistema, utente che ha +dei ben definiti limiti e capacità rispetto a quello che può fare. Sono così +previsti una serie di meccanismi per identificare i singoli utenti ed uan +serie di permessi e protezioni per impedire che utenti diversi possano +danneggiarsi a vicenda o danneggiare il sistema. + +Ad ogni utente è dato un nome \textit{username}, che è quello che viene +richiesto all'ingresso nel sistema dalla procedura di \textit{login}. Questa +procedura si incarica di verificare la identità dell'utente (in genere +attraverso la richiesta di una parola d'ordine, anche se sono possibili +meccanismi diversi). + +Eseguita la procedura di riconoscimento in genere il sistema manda in +esecuzione un programma di interfaccia (che può essere la \textit{shell} su +terminale o una interfaccia grafica) che mette a disposizione dell'utente un +meccanismo con cui questo può impartire comandi o eseguire altri programmi. + +Ogni utente appartiene anche ad almeno un gruppo (\textit{group}), ma può +essere associato a più gruppi, questo permette di gestire i permessi di +accesso ai file e quindi anche alle periferiche, in maniera più flessibile, +definendo gruppi di lavoro, di accesso a determinate risorse, etc. + +L'utente e il gruppo sono identificati da due numeri (la cui corrispondenza ad +un nome in espresso in caratteri \`e inserita nei due files +\texttt{/etc/passwd} e \texttt{/etc/groups}). Questi numeri sono +l'\textit{user identifier}, detto in breve \textit{uid} e il \textit{group + identifier}, detto in breve \textit{gid} che sono quelli che identificano +l'utente di fronte al sistema. + +In questo modo il sistema è in grado di tenere traccia per ogni processo +dell'utente a cui appartiene ed impedire ad altri utenti di interferire con +esso. Inoltre con questo sistema viene anche garantita una forma base di +sicurezza interna in quanto anche l'accesso ai file (vedi +\ref{sec:file_perms}) è regolato da questo meccanismo di identificazione. + +Un utente speciale del sistema è \textit{root}, il cui uid è zero. Esso +identifica l'amministratore del sistema, che deve essere in grado di fare +qualunque operazione; pertanto per l'utente root i meccanismi di controllo +descritti in precedenza sono disattivati. diff --git a/ipc.tex b/ipc.tex new file mode 100644 index 0000000..7ec9f2d --- /dev/null +++ b/ipc.tex @@ -0,0 +1,32 @@ +\chapter{La comunicazione fra porcessi} +\label{cha:IPC} + + +\section{Introduzione} +\label{sec:ipc_intro} + +Uno degli aspetti fondamentali della programmazione in unix è la comunicazione +fra processi. In questo testo affronteremo solo alcuni dei meccanismi +fondamentali che permettono di scrivere applicazioni, esistono pure sistemi +più complessi ed evoluti come le RPC (\textit{Remote Procedure Calls}) e +CORBA (\textit{Common Object Request Brocker Architecture}) non saranno +affrontati qui. + +\section{Le pipes standard} +\label{sec:ipc_pipes} + +\section{Le pipes con nome} +\label{sec:ipc_nampipe} + +\section{System V IPC} +\label{sec:ipc_sysv} + +\section{Code di messaggi} +\label{sec:ipc_messque} + +\section{Semafori} +\label{sec:ipc_semaph} + +\section{Memoria condivisa} +\label{sec:ipc_shar_mem} + diff --git a/macro.tex b/macro.tex new file mode 100644 index 0000000..7375beb --- /dev/null +++ b/macro.tex @@ -0,0 +1,55 @@ +% +% Defining some commands to manipulate counter to avoid ude of +% \label and \ref commands (and related problem to remeber the +% used labels +% +% +\newcounter{usercount} % define a new counter for internal use +% +% Figure commands +% +\newcommand{\curfig}{fig.~\thefigure} +\newcommand{\nfig}{% +\setcounter{usercount}{\value{figure}}% +\addtocounter{usercount}{1}% +fig.~\thechapter.\theusercount} +\newcommand{\pfig}{% +\setcounter{usercount}{\value{figure}}% +\addtocounter{usercount}{-1}% +fig.~\thechapter.\theusercount} +% +% Tables commands +% +\newcommand{\curtab}{tab.~\thetable} +\newcommand{\ntab}{% +\setcounter{usercount}{\value{table}}% +\addtocounter{usercount}{1}% +tab.~\thechapter.\theusercount} +\newcommand{\ptab}{% +\setcounter{usercount}{\value{table}}% +\addtocounter{usercount}{-1}% +tab.~\thechapter.\theusercount} +% +% equations commands +% +\newcommand{\cureq}{(\theequation)} +\newcommand{\nxeq}{% +\setcounter{usercount}{\value{equation}}% +\addtocounter{usercount}{1}% +(\thechapter.\theusercount)} +\newcommand{\preeq}{% +\setcounter{usercount}{\value{equation}}% +\addtocounter{usercount}{-1}% +(\thechapter.\theusercount)} + +% +% Macro to put picture (in format PICT) inside a figure +% +\newcommand{\pictfig}[3]{ + \begin{minipage}[t][#1][b]{#2} + \mbox{\special{pict=#3}} +% \vspace{3cm} + \end{minipage} +} +% +% diff --git a/main.tex b/main.tex new file mode 100644 index 0000000..3cd309e --- /dev/null +++ b/main.tex @@ -0,0 +1,92 @@ +% +% File principale: gli altri vanno inclusi da questo. +% +\documentclass[a4paper,11pt,twoside,italian]{book} +\usepackage[latin1]{inputenc} +\usepackage{graphicx} +\usepackage{babel} +\usepackage{cite} +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage[hang,bf,footnotesize,it]{caption2} +% +% Setting page layout +% + +\oddsidemargin=0.5cm +\evensidemargin=-0.5cm +\textwidth=16cm +\textheight=24.2cm +\topmargin=-1.cm +%\setcaptionmargin{2cm} + +%\renewcommand{\chaptername}{Capitolo} +%\renewcommand{\contentsname}{Indice} +%\renewcommand{\bibname}{Bibliografia} +\pagestyle{headings} + +%\includeonly{macro,pref,intro,fdl} + + +\title{Guida alla Programmazione in Linux.} + +\author{Simone Piccardi, + si spera anche qualcun'altro} + + +\begin{document} + + + +\pagenumbering{roman} + +\maketitle + +\newcommand{\clearemptydoublepage}{\newpage{\pagestyle{empty} +\cleardoublepage}} + +\begin{quote} + + Copyright \copyright\ 2000 Simone Piccardi. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.1 + or any later version published by the Free Software Foundation; + with the Invariant Sections being ``Prefazione'', with no + Front-Cover Texts, and with no Back-Cover Texts. + A copy of the license is included in the section entitled ``GNU + Free Documentation License''. + +\end{quote} +\clearemptydoublepage + +\tableofcontents +\clearemptydoublepage + + +\include{macro} +\setcounter{secnumdepth}{-2} +\include{pref} +\setcounter{secnumdepth}{2} +\clearemptydoublepage + +\pagenumbering{arabic} + +\include{intro} +\include{files} +\include{network} +\include{process} +\include{option} +\include{signal} +\include{ipc} +\include{fdl} + +% at the end put the bibliography + +%\bibliographystyle{phaip} +%\bibliography{biblio} + +\end{document} + + + + diff --git a/network.tex b/network.tex new file mode 100644 index 0000000..9206c50 --- /dev/null +++ b/network.tex @@ -0,0 +1,221 @@ +\chapter{Introduzione alla rete} + +In questo capitolo sarà fatta un'introduzione ai contetti generali che +servono come prerequisiti per capire ed +esamineremo a grandi linee i protocolli di rete e come questi sono organizzati +e interagiscono. + + +\section{I protocolli di rete} +\label{sec:layer} + +Parlando di reti di computer si parla in genere di un insieme molto vasto ed +eterogeneo di mezzi di comunicazione che vanno dal cavo telefonico, alla +fibra ottica, alle comunicazioni via satellite; per rendere possibile la +comunicazione attraverso un così variegato insieme di mezzi sono stati +adottati una serie di protocolli, il più famoso dei quali, quello alla base +del funzionamento di internet, é il cosiddetto TCP/IP. + +\subsection{Il modello ISO/OSI} +\label{sec:iso_osi} + +Una caratteristica comune dei protocolli di rete è il loro essere strutturati +in livelli sovrapposti; in questo modo un livello superiore esegue richieste +al livello sottostante e da questo riceve responsi, mentre livelli uguali su +macchine diverse conversano tramite lo stesso protocollo. Questo modello di +funzionamento è stato stato standardizzato dalla International Standards +Organization (ISO) che ha preparato fin dal 1984 il Modello di Riferimento +Open Systems Interconnection (OSI), strutturato in a sette livelli, secondo la +tabella in \ntab. + +\begin{table}[htb] + \centering + \begin{tabular}{l c c l} + \textbf{Livello} & \multicolumn{2}{c}{\textbf{Nome}} & \\ + \hline + Livello 7&\textit{Application} &\textsl{Applicazione}& \\ + Livello 6&\textit{Presentation} &\textsl{Presentazione}& \\ + Livello 5&\textit{Session} &\textsl{Sessione}& \\ + Livello 4&\textit{Transport} &\textsl{Trasporto}& \\ + Livello 3&\textit{Network} &\textsl{Rete}& \\ + Livello 2&\textit{DataLink} &\textsl{Collegamento Dati}& \\ + Livello 1&\textit{Connection} &\textsl{Connessione Fisica}& \\ + \hline +\end{tabular} +\caption{I sette livelli del protocollo ISO/OSI.} +\label{tab:osilayers} +\end{table} + +Il modello ISO/OSI è stato sviluppato corrispondentemente alla definizione +della serie di protocolli X.25 per la commutazione di pacchetto. Ma nonostante +il lavoro dettagliato di standardizzazione il modello si è rivelato +sostanzialmente troppo complesso e poco flessibile rispetto a quello, +precedente, su cui si basa TCP/IP che è diventato uno standard de facto; +quest'ultimo viene comunemente chiamato modello DoD (Department of Defense), +dato che fu sviluppato dall'agenzia ARPA per il Dipartimento della Difesa +Americano. + +\subsection{Il protocollo TCP/IP} +\label{sec:tcpip_overview} + +Così come ISO/OSI anche TCP/IP è stato strutturato in livelli (riassunti in +\ntab); un confronto fra i due è riportato in \nfig dove viene evidenziata +anche la corrispondenza fra i rispettivi livelli (che comunque è +approssimativa) e come essi vanno ad inserirsi all'interno del sistema +operativo, riguardo alla divisione fra user space e kernel space spiegata in +\ref{sec:unix_struct}. + +% L'attuale Internent Protocol (IPv4) viene standardizzato nel 1981 +% dall'RFC~719; esso nasce per disaccoppiare le applicazioni della struttura +% hardware delle reti di trasmissione, e creare una interfaccia di trasmissione +% dei dati indipendente dal sottostante substrato di rete, che può essere +% realizzato con le tecnologie più disparate (Ethernet, Token Ring, FDDI, +% etc.). + +% In realtà IP realizza solo una parte di tutto questo, e fa parte di un +% sistema che va sotto il nome di TCP/IP che è, +% uno di +% questi, quello responsabile del trasporto dei pacchetti fra le varie reti che +% compongono Internet, è appunto IP. + +\begin{table}[htb] + \centering + \begin{tabular}{l c c l} + \textbf{Livello} & \multicolumn{2}{c}{\textbf{Nome}} & \textbf{Esempi} \\ + \hline + Livello 1&\textit{Application} &\textsl{Applicazione}& + Telnet, FTP, etc. \\ + Livello 2&\textit{Transport} &\textsl{Trasporto}& TCP, UDP \\ + Livello 3&\textit{Network} &\textsl{Rete}& IP, (ICMP, IGMP) \\ + Livello 4&\textit{Link} &\textsl{Connessione}& + device driver \& scheda di interfaccia \\ + \hline +\end{tabular} +\caption{I quattro livelli del protocollo TPC/IP.} +\label{tab:layers} +\end{table} + + +Come si può notare TCP/IP è più semplice del modello ISO/OSI e strutturato in +soli quattro livelli. Il suo nome deriva dai due principali protocolli che lo +compongono, il TCP \textit{Trasmission Control Protocol} e l'IP +\textit{Internet Protocol}. Le funzioni dei vari livelli sono le seguenti: + +\begin{description} +\item \textbf{Applicazione} É relativo ai programmi di interfaccia utente, in + genere questi vengono realizzati secondo il modello Client-Server (vedi + \ref{sec:cliserv}. +\item \textbf{Trasporto} Fornisce la comunicazione tra le due stazioni + terminali su cui girano gli applicativi, regola il flusso delle + informazioni, e può fornire un trasporto affidabile, cioè con recupero + errori. Il protocollo principale di questo livello è il TCP. +\item \textbf{Rete} Si occupa dello smistamento dei singoli pacchetti su una + rete complessa e interconnessa, a questo stesso livello operano i protocolli + per il reperimento delle informazioni necessarie allo smistamento, per lo + scambio di messaggi di controllo e per il monitoraggio della rete. Il + protocollo su cui si basa questo livello è IP (sia nella attuale versione, + IPv4 che nella nuova IPv6). +\item \textbf{Connessione} È responsabile per l'interfacciamento al + dispositivo elettronico che effettua la comunicazione fisica, gestendo + l'invio e la ricezione dall'hardware dei pacchetti. +\end{description} + + +La comunicazione fra due stazioni avviene pertanto secondo le modalità +illustrate in \nfig. + +Le singole applicazioni si scambieranno i dati secondo un loro formato +specifico, implementando un protocollo di applicazione (esempi possono essere +HTTP, POP, telnet, SMTP, etc). + +Questi dati vengono inviati al livello di trasporto usando un'interfaccia +opportuna (i \textit{socket}, che esamineremo in dettaglio in seguito), i +quali li spezzerà in pacchetti di dimensione opportuna e li incapsulerà +all'interno del suo protocollo di trasporto aggiungendo ad ogni pacchetto le +informazioni necessarie alla gestione di quest'ultimo. Questo processo viene +svolto dirattamente nel kernel ad esempio dallo stack TCP nel caso il +protocollo di trasporto sia questo. + +Una volta composto il pacchetto nel formato adatto al protocollo di trasporto +usato questo sarà passato al successivo livello, quello del collegamento che +si occupa di inserire le opportune informazioni per poter effettuare +l'instradamento nella rete ed il recapito alla destinazione finale. In genere +questo è il livello di IP (Internet Protocol), a cui vengono inseriti i numeri +IP che identificano i computer su internet. + +L'ultimo passo è il trasferimento del pacchetto al driver della interfaccia di +trasmissione che si incarica di incapsularlo nel relativo protocollo di +trasmissione fisica usato dall'hardware usato per la comunicazione (ad esempio +ethernet per una scheda di rete). + + +\subsection{Criteri generali del design di TCP/IP} + + +La filosofia architetturale di TCP/IP è semplice: costruire una rete che +possa sopportare il carico in transito, ma permettere ai singoli nodi di +scartare pacchetti se il carico è temporaneamente eccessivo, o se risultano +errati o non recapitabili. + +L'incarico di rendere il recapito pacchetti affidabile non spetta allo livello +di collegamento, ma ai livelli superiori. Pertanto il protocollo IP è per sua +natura inaffidabile, in quanto non è assicurata né una percentuale di +successo né un limite sui tempi di consegna dei pacchetti. + +È il livello di trasporto che si deve occupare (qualora necessiti) del +controllo del flusso dei dati e del recupero degli errori; questo è realizzato +dal protocollo TCP. La sede principale di "intelligenza" della rete è pertanto +al livello di trasporto o superiore. + +Infine le singole stazioni collegate alla rete non fungono soltanto da punti +terminali di comunicazione, ma possono anche assumere il ruolo di router, per +l'interscambio di pacchetti da una rete ad un'altra. Questo rende possibile la +flessibilità della rete che è in grado di adattarsi ai mutamenti delle +interconnessioni. + +La caratteristica essenziale che rende tutto ciò possibile è la strutturazione +a livelli tramite l'incapsulamento. Ogni pacchetto di dati viene incapsulato +nel formato del livello successivo, fino al livello della connessione fisica. +In questo modo il pacchetto ricevuto ad un livello $n$ dalla stazione di +destinazione è esattamente lo stesso spedito dal livello $n$ dalla sorgente. +Questo rende facile il progettare il software facendo riferimento unicamente a +quanto necessario ad un singolo livello, con la confidenza che questo poi sarà +trattato uniformemente da tutti i nodi della rete. + + + +\section{Il modello client-server} +\label{sec:cliserv}. + +La differenza principale fra un'applicazione di rete e un programma normale +è che quest'ultima per definizione concerne la comunicazione fra +``processi'' diversi (che in generale non girano neanche sulla stessa +macchina). Questo già prefigura un cambiamento completo rispetto all'ottica +del ``programma'' monolitico all'interno del quale vengono eseguite tutte le +istruzioni, e presuppone un sistema operativo ``multitasking'' in grado di +eseguire processi diversi. + +Il concetto fondamentale si basa la programmazione di rete sotto Linux (e +sotto Unix in generale) è il modello \textit{client-server} in cui un +programma di servizio, il \textit{server} riceve un connessione e risponde a +un programma di utilizzo, il \textit{client}, provvedendo a quest'ultimo un +definito insieme di servizi. + +Esempi di questo modello sono il WEB, ftp, telnet, ssh e praticamente ogni +servizio che viene fornito tramite la rete, ma il modello è utilizzato in +generale anche per programmi di uso locale. + +Normalmente si dividono i server in due categorie principali, +\textit{concorrenti} e \textit{iterativi}, sulla base del loro comportamento. + +Un server iterativo risponde alla richiesta inviando i dati e resta occupato +(non rispondendo ad ulteriori richieste) fintanto che non ha concluso la +richiesta. Una volta completata la richiesta il server diventa di nuovo +disponibile. + +Un server concorrente al momento di trattare la richiesta crea un processo +figlio incaricato di fornire i servizi richiesti, per poi porsi in attesa di +ulteriori richieste. In questo modo più richieste possono essere soddisfatte +contemporaneamente, una volta che il processo figlio ha concluso il suo lavoro +viene terminato, mentre il server originale resta sempre attivo. + diff --git a/option.tex b/option.tex new file mode 100644 index 0000000..52dab01 --- /dev/null +++ b/option.tex @@ -0,0 +1,145 @@ +\chapter{Gestione di parametri e opzioni} + +Il passaggio dei parametri e delle variabili di ambiente dalla riga di comando +al singolo programma quando viene lanciato è effettuato attraverso le +variabili \texttt{argc}, \texttt{argv}, queste vengono passate al programma +come argomenti della funzione principale: + +\begin{verbatim} + main(int argc, char * argv[]) +\end{verbatim} + +\section{Il formato dei parametri} + +Il passaggio dei parametri al programma viene effettuato dalla shell, che si +incarica di leggere la linea di comando e di effettuarne la scansione (il +cosiddetto \textit{parsing}) per individuare le parole che la compongono, +ciascuna delle quali viene considerata un parametro; di default per +individuare le parole viene usato come separatore lo spazio (comportamento +modificabile attraverso il settaggio della variabile di ambiente IFS). + +Nella scansione viene costruito l'array di puntatori \texttt{argv} inserendo +in successione il puntatore alla stringa costituente l'$n$-simo parametro; la +variabile \texttt{argc} viene inizializzata al numero di parametri trovati, in +questo modo il primo parametro è sempre il nome del programma (vedi \nfig). + +\section{La gestione delle opzioni} + +In generale un programma unix riceve da linea di comando sia i parametri che +le opzioni, queste ultime sono standardizzate per essere riconosciute come +tali: un elemento di \texttt{argv} che inizia con \texttt{-} e che non sia un +singolo \texttt{-} o \texttt{--} viene considerato un'opzione. In in genere +le opzioni sono costituite da un lettera preceduta dal meno e possono avere o +no un parametro associato; un comando tipico può essere cioè qualcosa del +tipo: +\begin{verbatim} +touch -r riferimento.txt -m questofile.txt +\end{verbatim} +ed in questo caso le opzioni sono \texttt{m} ed \texttt{r}. + +Per gestire le opzioni all'interno dei parametri passati in \texttt{argv} le +librerie standard del C forniscono la funzione \texttt{getopt} (accessibile +includendo \texttt{unistd.h}), che ha il prototipo: +\begin{verbatim} +int getopt(int argc, char * const argv[], const char * optstring); +\end{verbatim} + +Questa funzione prende come argomenti le due variabili \texttt{argc} e +\texttt{argv} ed una stringa che indica quali sono le opzioni valide; la +funzione effettua la scansione della lista dei parametri ricercando ogni +stringa che comincia con \texttt{-} e ritorna ogni volta che trova una opzione +valida. + +La stringa \texttt{optstring} indica quali sono le opzioni riconosciute ed è +costituita da tutti i caratteri usati per identificare le singole opzioni, se +l'opzione ha un parametro al carattere deve essere fatto seguire un segno di +due punti \texttt{:} nel caso appena accennato ad esempio la stringa di +opzioni sarebbe \texttt{"r:m"}. + +La modalità di uso è pertanto quella di chiamare più volte la funzione +all'interno di un ciclo di while fintanto che essa non ritorna il valore +\texttt{-1} che indica che non ci sono più opzioni. Nel caso si incontri +un'opzione non dichiarata in \texttt{optstring} viene ritornato un \texttt{?} +mentre se l'opzione non è seguita da un parametro viene ritornato un +\texttt{:} infine se viene incontrato il valore \texttt{--} la scansione viene +considerata conclusa. + +Quando la funzione trova un'opzione essa ritorna il valore numerico del +carattere, in questo modo si possono prendere le azioni relative usando un +case; la funzione inizializza inoltre alcune varibili globali: +\begin{itemize} +\item \texttt{char * optarg} contiene il puntatore alla stringa argomento + dell'opzione. +\item \texttt{int optind} alla fine della scansione restituisce l'indice del + primo argomento che non è un'opzione. +\item \texttt{int opterr} previene, se posto a zero, la stampa di un messaggio + di errore in caso di riconoscimento di opzioni non definite. +\item \texttt{int optopt} contiene il carattere dell'opzione non riconosciuta. +\end{itemize} + +In \nfig è mostrato un programma di esempio, + +\begin{figure}[htbp] + \begin{center} + \begin{verbatim} + opterr = 0; /* don't want writing to stderr */ + while ( (i = getopt(argc, argv, "o:a:i:hve")) != -1) { + switch (i) { + case 'i': /* input file */ + in_file=open(optarg,O_RDONLY); + if (in_file<0) { + perror("Cannot open input file"); + exit(1); + } + break; + case 'o': /* output file (overwrite) */ + out_file=open(optarg,O_WRONLY|O_CREAT); + if (out_file<0) { + perror("Cannot open output file"); + exit(1); + } + break; + break; + case 'a': /* output file (append) */ + out_file=open(optarg,O_WRONLY|O_CREAT|O_APPEND); + break; + case 'h': /* print help usage */ + usage(); + break; + case 'v': /* set verbose mode */ + debug("Option -v active\n"); + verbose=1; + break; + case '?': /* unrecognized options */ + printf("Unrecognized options -%c\n",optopt); + usage(); + default: /* should not reached */ + debug("default option\n"); + usage(); + } + } + debug("Optind %d, argc %d\n",optind,argc); + \end{verbatim} + \caption{Esempio di codice per la gestione delle opzioni.} + \label{fig:options_code} + \end{center} +\end{figure} + +\subsection{Opzioni in formato esteso} + +Un'estensione di questo schema è costituito dalle cosiddette +\textit{long-options} espresse nella forma \texttt{--option=parameter}, anche +la gestione di queste ultime è stata standardizzata attraverso l'uso di una +versione estesa di \texttt{getopt}. + + +\section{Le variabili di ambiente} + +Questo va fatto. + + + + + + + diff --git a/pref.tex b/pref.tex new file mode 100644 index 0000000..98ef59f --- /dev/null +++ b/pref.tex @@ -0,0 +1,54 @@ +\chapter{Prefazione} + +Nelle motivazioni in cui si introduce la GNU Free Documentation License (FDL) +(reperibili su http://www.gnu.org/philosophy/free-doc.html) si dà +una grande rilevanza all'importanza di disporre di buoni manuali, in quanto un +buon software senza un buon manuale liberamente disponibile pure la +fruibilità del software libero viene diminuita. + +E come per il software libero è anche in questo caso è di fondamentale +importanza la libertà di accedere ai sorgenti (e non solo al risultato +finale, sia questo una stampa o un file formattato) e la libertà di +modificarli per apportarvi migliorie, aggiornamenti, etc. + +Per questo la Free Software Foundation ha approntato una licenza apposita per +la documentazione, che tiene conto delle differenze che restano fra un testo e +un programma. + +Esiste però un altro campo, diverso dalla documentazione e dai manuali, in +cui avere a disposizione testi liberi, aperti e modificabili è essenziale ed +estremamente utile, quello della didattica e dell'educazione. E benché questo +sia citato dalla FDL non è altrettanto comune trovarlo messo in pratica. + +In particolare sarebbe di grande interesse poter disporre di testi didattici +in grado di crescere, essere adattati alle diverse esigenze, modificati e +ampliati nello stesso modo in cui si fa per il software libero. + +Questo progetto mira alla stesura di un libro il più completo e chiaro +possible sulla programmazione in GNU/Linux (da qui in avanti Linux per +brevità). Ovviamente essendo i concetti in gran parte gli stessi, esso +dovrebbe restare valido anche per la programmazione in ambito Unix generico, +l'idea è comunque quella di approfondire anche la caratteristiche peculiari di +GNU/Linux. + +L'idea è quella di riuscire a ottenere alla fine un testo utilizzabile per +apprendere la programmazione di rete sotto GNU/Linux della stessa qualità (è +un progetto molto ambizioso ...) dei testi del compianto R. W. Stevens. + +Il progetto prevede il rilascio del testo sotto licenza FDL, ed una modalità +di realizzazione aperta che permetta di accogliere i contributi di chiunque sia +interessato. + +Dato che lo scopo del progetto è la produzione di un libro si è scelto di +usare latex come "ambiente di sviluppo" del medesimo, sia per l'impareggiabile +qualità tipografica ottenibile, che per la congruenza dello strumento sia sul +piano pratico che su quello filosofico. + +Il testo sarà, almeno inizialmente, in italiano. + + + + + + + diff --git a/process.tex b/process.tex new file mode 100644 index 0000000..fb1f1af --- /dev/null +++ b/process.tex @@ -0,0 +1,112 @@ +\chapter{I processi} +\label{cha:process} + +Come accennato nell'introduzione in un sistema unix ogni attività del sistema +viene svolta tramite i processi. Questo significa che quando un programma +viene posto in esecuzione, viene fatto partire un processo che si incarica di +eseguirne il codice. In sostanza i processi costituiscono l'unità base per +l'allocazione e l'uso delle risorse del sistema. + +Una delle caratteristiche essenziali di unix (che esamineremo in dettaglio più +avanti) è che ogni processo può a sua volta generare altri processi figli +(\textit{child}): questo è ad esempio quello che fa la shell quando mette in +esecuzione il programma che gli indichiamo nella linea di comando. + +Una seconda caratteristica è che ogni processo viene sempre generato in tale +modo da un processo genitore (\textit{parent}) attraverso una apposita system +call. Questo vale per tutti i processi, tranne per un processo speciale, che +normalmente è \texttt{/sbin/init}, che invece viene lanciato dal kernel finita +la fase di avvio e che quindi non è figlio di nessuno. + +Tutto ciò significa che, come per i file su disco, i processi sono organizzati +gerarchicamente dalla relazione fra genitori e figli; alla base dell'albero in +questo caso c'è init che è progenitore di ogni altro processo. + + +\section{Una panoramica sui concetti base} +\label{sec:proc_gen} + +Ogni processo viene identificato dal sistema da un numero identificativo +unico, il \textit{process id} o \textit{pid}. Questo viene assegnato in forma +progressiva ogni volta che un nuovo processo viene creato, fino ad un limite +massimo (in genere essendo detto numero memorizzato in un intero a 16 bit si +arriva a 32767) oltre il quale si riparte dal numero più basso disponibile +(FIXME: verificare, non sono sicuro). Per questo motivo processo il processo +di avvio (init) ha sempre il pid uguale a uno. + +Quando un processo ha concluso il suo compito o ha incontrato un errore non +risolvibile esso può essere terminato con la funzione \texttt{exit} (la +questione è più complessa ma ci torneremo più avanti). La vita del processo +però termina solo quando viene chiamata la quando la sua conclusione viene +ricevuta dal processo padre, a quel punto tutte le risorse allocate nel +sistema ad esso associate vengono rilasciate. + +I processi vengono creati dalla funzione \texttt{fork}; in genere questa è una +system call, Linux però usa un'altra nomenclatura, e la funzione fork è basata +a sua volta sulla system call \texttt{clone}, che viene usata anche per +generare i \textit{thread}. Il processo figlio creato dalla \textit{fork} è +una copia identica del processo processo padre, solo che ha un suo pid proprio. + +Dopo l'esecuzione di una fork sia il processo padre che il processo figlio +continuano ad essere eseguiti normalmente, ed il processo figlio esegue +esattamente lo stesso codice del padre. La sola differenza è che nel processo +padre il valore di ritorno della funzione fork è il pid del processo figlio, +mentre nel figlio è zero; in questo modo il programma può identificare se +viene eseguito dal padre o dal figlio. + +Se si vuole che il processo padre si fermi fino alla conclusione del processo +figlio questo deve essere specificato subito dopo la fork chiamando la +funzione \texttt{wait} o la funzione \texttt{waitpid}, che restituiscono anche +una informazione abbastanza limitata (il codice di uscita) sulle cause della +terminazione del processo. + +Avere due processi che eseguono esattamente lo stesso codice non è molto +utile, mormalmente si genera un secondo processo per affidagli l'esecuzione di +un compito specifico (ad esempio gestire una connessione dopo che questa è +stata stabilita), o fargli eseguire (come fa la shell) un altro programma. Per +questo si usa la seconda funzione fondamentale per programmazione coi processi +che è la \texttt{exec}. + +Il programma che un processo sta eseguendo si chiama immagine del processo +(\textit{process image}), le funzioni della famiglia \textit{exec} permette di +caricare un'altro programma da disco sostituendo quest'ultimo alla process +image corrente, questo fa si che la precedente immagine venga completamente +cancellata e quando il nuovo programma esce anche il processo termina, senza +ritornare alla precedente immagine. + +Per questo motivo la \texttt{fork} e la \texttt{exec} sono funzioni molto +particolari con caratteristiche uniche rispetto a tutte le altre, infatti la +prima ritorna due volte (nel processo padre e nel figlio) mentre la seconda +non ritorna mai (in quanto viene eseguito un altro programma). + + +\section{Identificazione} +\label{sec:proc_id} + +Come detto ogni processo è identificato univocamente dal sistema per il suo +pid; quest'ultimo è un apposito tipo di dato, il \texttt{pid\_t} che in +genere è un intero con segno (nel caso di Linux e delle glibc il tipo usato è +\texttt{int}. + +Tutti i processi inoltre portano traccia del pid del genitore, chiamato in +genere \textit{ppid} (da \textit{Parente Process Id}). Questi identificativi +possono essere ottenuti da un programma usando le funzioni: +\begin{itemize} + \item \texttt{pid\_t getpid(void)} restituisce il pid del processo corrente. + + \item \texttt{pid\_t getpid(void)} restituisce il pid del padre del processo + corrente. + +\end{itemize} +(per l'accesso a queste funzioni e ai relativi tipi di dati occorre includere +gli header files \texttt{unistd.h} e \texttt{sys/types.h}. + + +\section{Provilegi e permessi} +\label{sec:process_perms} + +Va messo qui tutta la storia su effective, real, saved uid, e pure le cose di +linux come il filesystem uid. + + + diff --git a/signal.tex b/signal.tex new file mode 100644 index 0000000..60a7b52 --- /dev/null +++ b/signal.tex @@ -0,0 +1,238 @@ +\chapter{I segnali} +\label{sec:signals} + +I segnali sono il primo e più semplice meccanismo di comunicazione nei +confronti dei processi. Non portano con se nessuna informazione che non sia il +loro tipo, si tratta in sostanza di un'interruzione software portata ad un +processo. + +In genere i segnali vengono usati dal kernel per riportare situazioni +eccezionali (come errori di accesso, eccezioni atritmetiche, etc.) ma possono +anche essere usati come forma elementare di comunicazione fra processi (ad +esempio vengono usati per il controllo di sessione), per notificare eventi +(come la terminazione di un processo figlio), etc. + +\section{I concetti base} +\label{sec:sig_base} + +Come il nome stesso indica i segnali sono usati per notificare ad un processo +l'occorrenza di un evento eccezionale. Gli eventi che possono generare un +segnale sono vari; un breve elenco di possibile cause è il seguente: + +\begin{itemize} +\item un errore del programma, come una divisione per zero o un tentativo di + accesso alla memoria fuori dai limiti validi. +\item la terminazione di un processo figlio. +\item la scadenza di un timer o di un allarme. +\item il tentativo di effettuare un'operazione di input/output che non può + essere eseguita. +\item una richiesta dell'utente di terminare o fermare il programma. In genere + si realizza attraverso un segnale mandato dalla shell in corrispondenza + della pressione di tasti come 'ctrl-c' o 'ctrl-z'. +\item l'esecuzione di una \texttt{kill} o di una \texttt{raise} da parte del + processo stesso o di un'altro (solo nel caso della \texttt{kill}). +\end{itemize} + +Ciascuno di questi eventi (tranne gli ultimi due che sono controllati +dall'utente) comporta da parte del kernel la generazione un particolare tipo +di segnale. + + +\subsection{Le modalità di funzionamento} +\label{sec:sig_semantics} + +Quando un processo riceve un segnale il kernel esegue una apposita routine di +gestione (il cosiddetto \textit{signal handler}) che può essere specificata +dall'utente. Negli anni il comportamento del sistema in risposta ai segnali è +stato modificato in vari modi nelle differenti implementazioni di unix. +Attualmente si possono individuare due tipologie fondamentali di comportamento +dei segnali (dette semantiche) che vengono chiamate rispettivamente +\textit{reliable} e \textit{unreliable}. + +Nella semantica \textit{unreliable} la routine di gestione del segnale +specificata dall'utente non resta installata una volta chiamata; è perciò a +carico dell'utente stesso ripetere l'installazione all'interno della routine +stessa in tutti i casi in cui si vuole che il signal handler esterno resti +attivo. + +Per questo motivo è possibile una race-condition in cui il segnale arriva +prima che il suo manipolatore sia installato, nel qual caso il segnale può +essere perso o causare il comportamento originale (in genere la terminazione +del processo). Questa è la ragione per cui detti segnali sono chiamati +\textit{inaffidabili}, in quanto la ricezione del segnale e la reinstallazione +del suo manipolatore non sono oiperazioni atomiche. + +In caso di implementazione inaffidabile le chiamate di sistema non sono fatte +ripartire automaticamente quando sono interrotte da un segnale, per questo il +programma deve controllare lo stato di uscita della chiamata al sistema e +riperterla nel caso l'errore riportato da \texttt{errno} sia \texttt{EINTR}. + +Inoltre in questo caso non esiste una modalità semplice per ottenere una +operazione di pausa atomica (cioè mandare in sleep un processo fino all'arrivo +di un segnale), dato che ci sono casi in cui un segnale può arrivare quando il +programma non è in grado di accorgersene. + +In caso di segnali \textit{reliable} invece il signal handler resta installato +quando viene chiamato e i problemi precedenti sono evitati. Inoltre alcune +chiamate di sisteme possono essere fatte ripartire automaticamente e si può +ottenere un'operazione di pausa atomica (usando la funzione POSIX +\texttt{sigsuspend}). + + +\subsubsection{Tipi di segnali} +\label{sec:sig_types} + + +In generale gli eventi che generano i segnali si possono diviedere in tre +categorie principali: errori, eventi e richieste esplicite. + +Un errore significa che un programma ha fatto qualcosa di sbagliato e non può +continuare ad essere eseguito. Non tutti gli errori causano dei segnali, in +genere la condizione di errore più comune comporta la restituzione di un +codice di errore da parte di una funzione di libreria, sono gli errori che +possono avvenire ovunque in un programma che causano l'emissione di un +segnale, come le divisioni per zero o l'uso di indirizzi di memoria non validi. + +Un evento esterno ha in genere a che fare con l'I/O o con altri processi; +esempi di segnali di questo tipo sono quelli legati all'arrivo di dati di +input, scadenze di un timer, terminazione di processi figli. + +Una richiesta esplicita significa l'uso di una chiamata di sistema (come +\texttt{kill} o \texttt{raise}) per la generazione di un segnale, cosa che +viene fatta usualmente dalla shell quando l'utente invoca la sequenza di tasti +di stop o di suspend, ma può essere pure inserita all'interno di un programma. + +Si dice poi che i segnali possono essere \textit{asincroni} o +\textit{sincroni}. Un segnale sincrono è legato ad una azione specifica di un +programma ed è inviato (a meno che non sia bloccato) durante tale azione; +molti errori generano segnali sincroni, così come la richiesta esplicita da +parte del processo tramite le chiamate al sistema. Alcuni errori come la +divisione per zero non sono completamente sincroni e possono arrivare dopo +qualche istruzione. + +I segnali asincroni sono generati da eventi fuori dal controllo del processo +che li riceve e arrivano in tempi impredicibili nel corso dell'esecuzione del +programma. Eventi esterni come la terminazione di un processo figlio generano +segnali asincroni, così come le richieste di generazione di un segnale +effettuate da altri processi. + +In generale un tipo di segnale o è sincrono o è asincrono, salvo il caso in +cui esso sia generato attraverso una richiesta esplicita tramite chiamata al +sistema, nel qual caso qualunque tipo di segnale (quello scelto nella +chiamata) può diventare sincrono o asincrono a seconda che sia generato +internamente o esternamente al processo. + +\section{La notifica dei segnali} +\label{sec:sig_notification} + +Quando un segnale viene generato il kernel prende nota del fatto; si dice così +che diventa \textit{pending} (sospeso), e rimarrà tale fino al momento in cui +verrà notificato al processo a cui deve essere inviato. + +Normalmente l'invio al processo che deve ricevere il segnale è immediato, a +meno che il segnale in questione non sia stato bloccato (\textit{blocked}) nel +qual caso l'invio non avviene ed il segnale resta sospeso indefinitamente. Una +volta però che esso venga sbloccato il segnale sarà subito notificato. + +Una volta che il segnale viene notificato (che questo avvenga subito o dopo +una attesa più o meno lunga) viene eseguita l'azione specificata per detto +segnale. Per alcuni segnali (\texttt{SIGKILL} e \texttt{SIGSTOP}) questa azione +è fissa e non può essere cambiata, ma per tutti gli altri il programma può +specificare una scelta fra le tre seguenti: + +\begin{itemize} +\item ignorare il segnale +\item utilizzare il manipolatore (\textit{signal handler}) specificato +\item accettare l'azione di default per quel segnale. +\end{itemize} + +Il programma può specificare queste scelte usano le due routine +\texttt{signal} e \texttt{sigaction}; se si è installato un manipalatore sarà +quest'ultimo a intercettare il segnale ed ad essere eseguito, e mentre viene +eseguito (onde evitare race conditions) il segnale viene bloccato. + +Se l'azione specificata per un certo tipo di segnale è quella di ignorarlo +questo sarà scartato immediatamente ogni volta che verrà generato, e questo +avverrà anche se in quel momento il segnale è bloccato. Per questo un segnale +ignorato non sarà mai notificato, anche se in seguito si sarà specificata una +diversa azione per lo stesso segnale. + +Se arriva un segnale per il quale non è stato specificata un'azione viene +utilizzata l'azione standard. Questa è diversa da segnale a segnale (come +vedremo in \ref{sec:sig_standard}) ma per la maggior parte essa comporta la +terminazione del processo, per alcuni che invece rappresentano eventi innoqui +l'azione standard è di non fare nulla. + +Quando un segnale termina un processo, il padre può determinare la causa della +terminazione esaminando il codice di stato riportato delle funzioni +\texttt{wait} e \texttt{waitpid} in cui è riportato anche se la causa è un +segnale e nel caso quale; questo è il modo in cui la shell determina i motivi +della terminazione di un programma e scrive un eventuale messaggio di errore. + +I segnali che rappresentano errori del programma (divisione per zero o +violazioni di accesso) hanno anche la caratteristica di scrivere un file +\textit{core dump} che registra lo stato del processo prima della terminazione +e può essere esaminato da un debugger per investigare sulla causa dell'errore. +Lo stesso avvine se i suddetti segnale vengono generati artificialmente con +una \texttt{kill}. + + + +\subsection{I segnali standard} +\label{sec:sig_standard} + +Esaminiamo ora i vari segnali disponibili e le loro caratteristiche. +Ciascun segnale è identificato rispetto al sistema da un numero, ma l'uso +diretto di questo numero da parte dei programmi è da evitare, in quanto esso +può variare a seconda dell'implementazione del sistema. + +Per questo ad ogni tipo di segnale viene associato un nome, che corrisponde +tramite una macro di preprocessore, al suddetto numero, e sono questi nomi, +che sono standardizzati e uniformi rispetto alle varie implementazioni, che si +devono usare nei programmi. Tutti i nomi e le funzioni che concernono i +segnali sono definiti nell'header di sistema \texttt{signal.h}. + +Il numero totale di segnali presenti è dato dalla macro \texttt{NSIG}, e dato +che i numeri dei segnali sono allocati progressivamente, essa corrisponde +anche al successivo del valore numerico assegnato al'ultimo segnale definito. + + +\subsubsection{Segnali di errore di programma} + +Questi segnali sono generati quando c'é un grave errore nel programma rilevato +dal sistema o dallo stesso hardware. In generale indicano che il programma ha +dei gravi problemi e l'esecuzione non può essere proseguita. + +Alcuni programmi usano questi segnali per riordinare le cose prima di uscire. +As esempio ripristinare i settaggi della console, o eliminare i file di lock. +In questo caso il manipolatore deve concludersi ripristinando l'azione di +default e rialzando il segnale, così che il programma possa concludersi come +se il manipolatore non ci fosse mai stato. + +L'azione di default per tutti questi segnali è causare la terminazione del +processo che li ha causati. In genere oltre a questo il segnale provoca pure +la registrazione su disco di un \textit{core dump file} che viene scritto in +un file \texttt{core} nella directory corrente del processo al momento +dell'errore. + +Questi segnali sono: + +\begin{itemize} +\item \texttt{SIGFPE} Riporta un errore aritmetico fatale. Benchè il nome + derivi da \textit{floating point exception} si applica a tutti gli errori + aritmetici comprea la divisione per zero e l'overflow. + +% Per questo segnale le cose sono complicate dal fatto che possono esserci +% molte diverse eccezioni che \texttt{SIGFPE} non distingue, mentre lo +% standard IEEE per le operazioni in virgola mobile definisce vaire eccezioni +% aritmetiche e richiede che esse siano notificate. +\item \texttt{SIGFPE} Il nome deriva da \textit{illegal instruction} +\item \texttt{SIGILL} +\item \texttt{SIGSEGV} +\item \texttt{SIGBUS} +\item \texttt{SIGABRT} +\item \texttt{SIGTRAP} +\item \texttt{SIGSYS} + +\end{itemize} + diff --git a/sources/wrappers.h b/sources/wrappers.h new file mode 100644 index 0000000..70eb402 --- /dev/null +++ b/sources/wrappers.h @@ -0,0 +1,233 @@ +/*************************************************************** + * + * File wrappers.h: define a set of macro and inlined + * functions for signal, shared memory and semaphore handling + * + * Author: S. Piccardi + * + * $Id: wrappers.h,v 1.1 2001/03/05 22:20:08 piccardi Exp $ + * + ***************************************************************/ +#include /* IPC semaphore declarations */ +#include /* IPC shared memory declarations */ +#include +#include +#include +#include /* signal handling declarations */ +/** + ** Semaphore definition; used to implement a MutexXXXX API + ** To create a Mutex use an underlaying semaphore and init it; + ** we put here all the needed data structires + **/ +/* put this definition, get from the man pages */ +#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) +/* union semun is defined by including */ +#else +/* according to X/OPEN we have to define it ourselves */ +union semun { + int val; /* value for SETVAL */ + struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ + unsigned short int *array; /* array for GETALL, SETALL */ + struct seminfo *__buf; /* buffer for IPC_INFO */ +}; +#endif +/* + * Define the sem_lock and sem_ulock sembuf structures to + * lock and unlock the semaphore (used to implement a mutex) + */ +struct sembuf sem_lock={ /* to lock semaphore */ + 0, /* semaphore number (only one so 0) */ + -1, /* semaphore operation (-1 to use resource) */ + 0}; /* semaphore flag (in this case 0) */ +struct sembuf sem_ulock={ /* to unlock semaphore */ + 0, /* semaphore number (only one so 0) */ + 1, /* semaphore operation (-1 to release resource) */ + 0}; /* semaphore flag (in this case 0) */ +/* + * Function MutexLock: + * to lock a mutex/semaphore + * + * Input: a semaphore id # + */ +inline void MutexLock(int sem_id) +{ + if (semop(sem_id,&sem_lock,1)) { + perror("Cannot lock the semaphore"); + exit(1); + } +} +/* + * Function MutexUnlock + * to unlock a mutex/semaphore + * + * Input: a semaphore id # + */ +inline void MutexUnlock(int sem_id) +{ + if (semop(sem_id,&sem_ulock,1)) { + perror("Cannot unlock the semaphore"); + exit(1); + } +} +/* + * Function MutexCreate: + * First call create a semaphore, using the given key. + * We want only one semaphore so we set second argument to 1; third + * parameter is the flag argument, and is set to create a semaphore + * with R/W privilege for the user. + * Second call initialize the semaphore to 1 (unlocked) + * + * Input: an IPC key value (to create an unique semaphore) + * Return: the semaphore id# + */ +const union semun semunion={1}; /* semaphore union structure */ +inline int MutexCreate(key_t ipc_key) +{ + int sem_id; + if( (sem_id=semget(ipc_key,1,IPC_CREAT|0666))<0 ){ /* get sem ID */ + perror("cannot create semaphore"); /* a sem_id <0 is an error */ + printf("semid=%d",sem_id); + exit(1); + } + if ( (semctl(sem_id,0,SETVAL,semunion)) < 0 ) { + perror("cannot init semaphore"); /* <0 is an error */ + printf("on semid=%d",sem_id); + exit(1); + } + return sem_id; +} +/* + * Find Mutex + * get the semaphore/mutex Id given the IPC key value + * + * Input: an IPC key value + */ +inline int MutexFind(key_t ipc_key) +{ + int sem_id; + if( (sem_id=semget(ipc_key,1,0))<0 ){ /* find sem .ID */ + perror("cannot find semaphore"); + exit(1); + } + return sem_id; +} +/* + * Function MutexRead: + * Read the current value of the mutex/semaphore + * + * Input: a semaphore id # + * Return: the semaphore value + */ +inline int MutexRead(int sem_id) +{ + int value; + if ( (value=semctl(sem_id,0,GETVAL,semunion)) < 0 ) { + perror("cannot read semaphore"); /* a <0 is an error */ + printf("on semid=%d\n",sem_id); + exit(1); + } + return value; +} +/* + * Function ShmCreate: + * Allocate a shared memory segment. + * First call get a shared memory segment with KEY key access and size SIZE, + * by creating it with R/W privilege for the user (this is the meaning of + * the ored flags). The function return an identifier shmid used for any + * further reference to the shared memory segment. + * Second call attach the shared memory segment to this process and return a + * pointer to it (of char * type). + * Then initialize shared memory: + * Set all to 0x55 (means 0101 un binary notation + * + * Input: an IPC key value + * the shared memory segment size + * Return: the address of the segment + */ +inline char * ShmCreate(key_t ipc_key, int shm_size) +{ + char * shptr; + int shmid; /* ID of the IPC shared memory segment */ + if ((shmid=shmget(ipc_key,shm_size,IPC_CREAT|0666))<0){ /* get shm ID */ + perror("cannot find shared memory"); + exit(1); + } + if ( (shptr=shmat(shmid,0,0)) < 0 ){ /* take the pointer to it */ + perror("cannot attach shared memory"); + exit(1); + } + memset((void *)shptr,0x55,shm_size); /* second couter starts from "0" */ + return shptr; +} +/* + * Function ShmFind: + * Find a shared memory segment + * Input: an IPC key value + * the shared memory segment size + * Return: the address of the segment + */ +inline char * ShmFind(key_t ipc_key, int shm_size) +{ + char * shptr; + int shmid; /* ID of the IPC shared memory segment */ + if ( (shmid=shmget(ipc_key,shm_size,0))<0 ){ /* find shared memory ID */ + perror("cannot find shared memory"); + exit(1); + } + if ( (shptr=shmat(shmid,0,0)) < 0 ){ /* take the pointer to it */ + perror("cannot attach shared memory"); + exit(1); + } + return shptr; +} +/* + * Function LockFile: + * Create a lockfile of the given pathname. + * Fail and exit in case of error or existence of the same lock + * file, using unlink do not need to remove the file, + */ +inline void LockFile(const char* path_name) +{ + if (open(path_name, O_EXCL|O_CREAT)<0) { + perror("Already active"); + exit(1); + } +} +inline void UnlockFile(const char* path_name) +{ + if (unlink(path_name)) { + perror("error, cannot unlink"); + exit(1); + } +} +/* + * Function Signal + * Initialize a signal handler. + * To enable the signal handling a process we need to tell it to + * kernel; this is done writing all needed info to a sigaction structure + * named sigact, and then callind sigaction() system call passing the + * information stored in the sigact structure variable. + * + * Input: the signal to handle + * the signal handler function + * Return: the previous sigaction structure + */ +typedef void SigFunc(int); +SigFunc * Signal(int signo, SigFunc *func) +{ + struct sigaction new_handl, old_handl; + new_handl.sa_handler=func; + /* clear signal mask: no signal blocked during execution of func */ + if (sigemptyset(&new_handl.sa_mask)!=0){ /* initialize signal set */ + perror("cannot initializes the signal set to empty"); /* see mess. */ + exit(1); + } + new_handl.sa_flags=0; /* init to 0 all flags */ + /* change action for signo signal */ + if (sigaction(signo,&new_handl,&old_handl)){ + perror("sigaction failed on signal action setting"); + exit(1); + } + return (old_handl.sa_handler); +} +