From 3d44c36183fe67ed64bff95a36596ad87f620683 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Mon, 5 Mar 2001 22:20:07 +0000 Subject: [PATCH] Initial revision --- ChangeLog | 32 ++++ fdl.tex | 338 ++++++++++++++++++++++++++++++++++++++ files.tex | 394 +++++++++++++++++++++++++++++++++++++++++++++ intro.tex | 200 +++++++++++++++++++++++ ipc.tex | 32 ++++ macro.tex | 55 +++++++ main.tex | 92 +++++++++++ network.tex | 221 +++++++++++++++++++++++++ option.tex | 145 +++++++++++++++++ pref.tex | 54 +++++++ process.tex | 112 +++++++++++++ signal.tex | 238 +++++++++++++++++++++++++++ sources/wrappers.h | 233 +++++++++++++++++++++++++++ 13 files changed, 2146 insertions(+) create mode 100644 ChangeLog create mode 100644 fdl.tex create mode 100644 files.tex create mode 100644 intro.tex create mode 100644 ipc.tex create mode 100644 macro.tex create mode 100644 main.tex create mode 100644 network.tex create mode 100644 option.tex create mode 100644 pref.tex create mode 100644 process.tex create mode 100644 signal.tex create mode 100644 sources/wrappers.h 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); +} + -- 2.30.2