Un approccio pratico a Unix

Transcript

Un approccio pratico a Unix
sersh
Un approccio pratico a Unix
Sereno Ternullo
30 Maggio 2005
1
Copyright (c) 2005 Sereno Ternullo. Permission is granted to copy, distribute
and/or modify this document under the terms of the GNU Free Documentation
License, Version 1.2 or any later version published by the Free Software Foundation; with the Invariant Sections being Prefazione, no Front-Cover Texts, and
no Back-Cover Texts. A copy of the license is included in the section entitled
GNU Free Documentation License.
If you would like to get the latex sources of this document, you can write to my
email address asking for them: [email protected].
2
Indice
1 Prefazione
4
2 Cosa è una Shell
2.1
2.2
Interazione col SO . . . . . . . . .
Amministrazione di sistema . . . .
2.2.1 /bin/init . . . . . . . . . . .
2.2.2 Script di avvio in System V
2.2.3 Script di avvio in BSD . . .
2.2.4 Eseguibili Unix . . . . . . .
3 Funzionalità di una Shell Posix
3.1
3.2
3.3
3.4
Variabili di ambiente . . . . . .
alias . . . . . . . . . . . . . . .
Redirezione . . . . . . . . . . .
3.3.1 pipelining . . . . . . . .
Strutture di controllo . . . . . .
3.4.1 if ... then ... else ... .
3.4.2 case $var in ... esac . . .
3.4.3 for var in ... do ... done
3.4.4 while ... do ... done . .
5.2
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Genesi dei processi . . . . . . . . . . . . . .
5.1.1 fork . . . . . . . . . . . . . . . . . .
5.1.2 waitpid . . . . . . . . . . . . . . . .
5.1.3 exec . . . . . . . . . . . . . . . . . .
Segnali . . . . . . . . . . . . . . . . . . . . .
5.2.1 sigaction . . . . . . . . . . . . . . . .
5.2.2 Dierenze fra SIGTERM e SIGKILL
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Astrazione delle risorse . . . . .
stdin, stdout, stderr . . . . . .
Architettura del File System . .
4.3.1 Directory standard . . .
4.3.2 Multiutenza e permessi
5 Implementazione
5.1
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4 Cenni sul File System Unix
4.1
4.2
4.3
.
.
.
.
.
.
6 GNU Free Documentation License
3
5
5
6
6
6
7
7
8
8
8
9
9
10
10
11
11
12
13
13
14
14
14
15
16
16
16
17
18
21
21
23
26
1
Prefazione
I sistemi operativi e la programmazione C rappresentano indubbiamente due
tra le mie maggiori passioni; decisi quindi tempo fa di intraprendere uno studio
privato di tale disciplina, motivato esclusivamente dalla mia passione. Oltre
alla conoscenza che ho potuto attingere dalla sterminata documentazione fornita dalla comunità GNU/Linux, mi sono stati di grandissimo aiuto due opere
in particolare, ovvero Sistemi Operativi, disegno e implementazione di Andy
Tenenbaum e GaPiL di Simone Piccardi; consiglio a chiunque voglia cimentarsi nella programmazione di sistema di leggere questi mostri sacri della
letteratura informatica.
sersh
è una semplicissima shell che nasce dalla mia volontà di voler vedere
applicati nella pratica ed in un lavoro da me svolto alcuni di quei concetti che
sono basilari nella programmazione di sistema Unix: gestione dei le, genesi dei
processi, interazione col sistema operativo. Per comprendere un sistema Unix
bisogna inanzitutto capire cosa è un le, perché sotto Unix tutto è un le, e per
tale motivo risulta di vitale importanza la comprensione delle chiamate che il
SO ore sui le, e come il lesystem organizzi le risorse del sistema.
Inizialmente questa guida nasceva con lo scopo di documentare le principali
chiamate di sistema utilizzate all'interno di sersh; in corso d'opera ho trovato
utile arricchire tale lavoro con alcuni concetti chiave basilari nella comprensione
e nell'uso di un sistema Unix. Per questa ragione ritengo che quanto io abbia
scritto possa essere un buon punto di inizio anche per coloro che si avvicinano
a Unix per la prima volta.
sersh è una sorta di mia personale esercitazione che io rilascio con licenza
GNU GPL con lo scopo di poter essere utile a quanti si trovano adesso nel-
lo studio dei Sistemi Operativi. Non ho quindi l'intenzione di implementare
un'autentica Shell Posix, - sarebbe fuori dal mio scopo -, ma soltanto quello
di fornire un punto di partenza per quanti abbiano voglia di capire come certe
cose funzionano.
Sarò felice di ricevere commenti,
suggerimenti o miglioramenti di quanto io ho già svolto.
Sereno Ternullo,
Catania 14 Maggio 2005
[email protected]
4
2
Cosa è una Shell
2.1
Interazione col SO
Shell signica conchiglia, e la conchiglia è ciò che avvolge la perla.
Così come
per il mollusco, idealmente la Shell è in un sistema Unix quel programma utente
che avvolge il kernel, facendo in modo che le richieste dell'utente possano essere
soddisfatte dal sistema sottostante. Non bisogna infatti sottovalutare il fatto
che un ipotetico SO che fosse composto esclusivamente dal proprio kernel non
servirebbe proprio a niente, perché l'utente non avrebbe alcun modo di interfacciarsi con esso. La shell è un normalissimo processo utente con lo scopo di
fornire un invito 1 , aspettare che l'utente digiti qualcosa, ed eseguire quanto
questi desidera. Potrebbe sembrare alquanto banale, ma cosa si potrebbe fare
di un sistema in cui non si potesse visualizzare il contenuto del proprio disco
mediante un banalissimo ls 2 ?
Possiamo quindi immagginare una shell davvero elementare come un ciclo innito in cui ad una richiesta di input avviene l'esecuzione di una fork, quindi
l'esecuzione del comando richiesto mediante exec, e il successivo ritorno al processo padre una volta che il glio è terminato mediante waitpid.
while(true) {
prendo_una_riga();
pid = fork();
/* Creo un processo identico */
switch(pid) {
/* Chi sono ? */
case 0:
exec();
break;
/* Sono il processo figlio,
*/
/* eseguo il codice del programma passato */
default:
waitpid();
break;
/* Sono il processo padre, */
/* quindi mi blocco finché il figlio non termina */
}
}
•
sersh si comporta essenzialmente in questo modo.
1 user@home:$
2 ls è un programma
che si occupa di mostrare il contenuto di una directory
5
2.2
Amministrazione di sistema
Una Shell Posix implementa tutta una seria di funzionalità e strutture di
controllo che la rendono un utilissimo strumento indispensabile nell'amministrazione di sistema. E' possibile infatti denire degli script di cui la Shell sia
l'interprete.
Ciascuno degli Unix Shell Script inizia sempre con la seguente intestazione:
#! /bin/sh
Il primo rigo di ciascuno script serve al kernel del SO per avere indicazione su
quale interprete avviare per eseguire lo script.
Solitamente su un sistema GNU/Linux , /bin/sh è un link simbolico a /bin/bash,
la Bourne Again Shell. Tuttavia, secondo il nome eettivamente specicato
per l'interprete si avranno dei comportamenti leggermenti diversi. Se bash verrà avviato per mezzo del nome sh essa seguirà un comportamento rigidamente
dettato dalle speciche Posix 3 , altrimenti abiliterà l'uso delle estensioni GNU.
Il primo processo utente mandato in esecuzione sul sistema a cui spetta il
compito di congurare la macchina non appena questa viene avviata è
2.2.1 /bin/init
Una volta avviato init esamina il contenuto di /etc/inittab, le di congurazione
in cui sono indicati i comandi da eseguire anché la macchina si porti ad un
determinato runlevel. Un runlevel è semplicemente uno stato di esecuzione della
macchina che identica le modalità di funzionamento del sistema e i servizi
disponibili; in genere esiste sempre uno specicato runlevel che congura la
macchina come postazione monoutente 4 , e vi è sempre un certo runlevel che
congura la macchina come postazione multiutente inizializzando le interfacce
di rete.
• Gli eseguibili che si occupano di portare la macchina da un runlevel ad
un'altro sono Script Shell.
Nel mondo Unix esistono due scuole di pensiero sul modo in cui organizzare gli
script di avvio; tradizionalmente si fa riferimento al modo in cui questo è stato
fatto nei due grandi Unix storici: Unix System V della AT&T, e il Berkley
Software Distribution Unix, detto più brevemente BSD Unix.
2.2.2 Script di avvio in System V
Nei sistemi operativi aderenti allo stile System V per ciascun runlevel, init cerca nella directory /etc una sotto directory rcX.d, dove X è il numero che indica il runlevel desiderato. Se la directory cercata esiste, allora init eseguirà
automaticamente tutti gli script shell in essa contenuti.
3 Questo
viene fatto dal main di bash controllando argv[0], ovvero il nome stesso con cui il
programma è stato mandato in esecuzione
4 questo può rendersi utile all'amministratore di sistema in caso di ripristini dovuti a
situazioni critiche
6
runlevel=3
# Indica il runlevel su cui vogliamo portarci
if [ -d rc${runlevel}.d ]; then
for file in rc${runlevel}.d/*
do
. $file
done
fi
# Esiste una directory chiamata rc3.d ?
# ok, allora esegui tutti
# gli script in essa contenuti
2.2.3 Script di avvio in BSD
Nei sistemi operativi attinenti allo stile BSD l'esecuzione degli script avviene in
maniera leggermente meno intuitiva. Tutti gli script di avvio sono contenuti all'interno della directory /etc/rc.d . Per ciascun runlevel init manda in esecuzione
un le specico, ad esempio rc.M: esso congura il sistema come postazione multiutente. A sua volta questo script si occuperà di mandare in esecuzione degli
ulteriori script, vericandone prima il ag di eseguibilità.
if [ -x rc.pcmcia ] ; then
. rc.pcmcia start
fi
# rc.pcmcia è eseguibile ?
# Ok, lo mando in esecuzione
2.2.4 Eseguibili Unix
Bisogna avere chiaro che sotto Unix un le è considerato eseguibile se la sua
maschera dei permessi presenta attivo il ag di eseguibilità; al contrario di
quanto avviene in windows, dove ciascun eseguibile deve essere necessariamente
un le binario con estensione .exe, sotto Unix i le eseguibili non hanno alcuna estensione che li qualichi come tali. Come per gli Shell Script, sotto Unix
anche un le ASCII può essere considerato eseguibile.
Per vedere la maschera dei permessi
è possibile eseguire il comando ls -l :
5
di un le
user@home $ ls -l /etc/rc.d/rc.M
-rwxr-xr-x 1 root root 7906 2004-06-20 03:42 /etc/rc.d/rc.M
• il primo simbolo
- ci indica che è un le normale.
• Il le appartiene all'utente root ed al gruppo root.
root può leggere, scrivere, ed eseguire il le.
rwx corrisponde al valore ottale 7.
• gli appartenenti al gruppo root possono leggere ed eseguire il le.
r-x corrisponde al valore ottale 5.
• il resto del mondo può leggere ed eseguire il le.
r-x corrisponde al valore ottale 5.
5 della
maschera dei permessi si parlerà in modo più approfondito nel capitolo successivo
7
3
Funzionalità di una Shell Posix
3.1
Variabili di ambiente
All'interno di una Shell Posix è possibile denire variabili non tipizzate dette
variabili di ambiente. La dichiarazione di una variabile avviene mediante il
costrutto:
user@home $ variabile=valore
E' possibile accedere al contenuto di una variabile anteponendo ad essa il simbolo
$. Per fare in modo che una variabile di ambiente dichiarata all'interno di una
sessione Shell possa essere visibile anche ai successivi programmi lanciati da rigo
di comando, è neccessario esportarla per mezzo del comando export.
user@home $ export variabile
E' possibile dichiarare ed esportare simultaneamente una variabile per mezzo
della sintassi:
user@home $ export variabile=valore
• in sersh è possibile usare soltanto questo ultimo costrutto.
E' possibile visualizzare la lista di tutte le variabile di ambiente per mezzo del
comando env
Alcune tra le variabili sempre presenti in una sessione Shell sono:
! - PID dell'ultimo processo mandato in esecuzione in background ;
? - Raccoglie il codice di uscita dell'ultimo comando mandato in esecuzione;
PWD - Directory di lavoro;
OLDPWD - Directory di lavoro precedente;
PID - PID della Shell corrente;
PPID - PID del processo che ha generato la shell corrente ( il padre );
USER - Nome dell'utente corrente;
HOME - Home directory per l'utente corrente;
SHELL - Shell di default per l'utente corrente;
PATH - Insieme delle directory in cui cercare gli eseguibili;
PS1 - Specica per la formattazione dell'invito primario;
PS2 - Specica per la formattazione dell'invito secondario.
E' possibile denire delle scorciatoie ai comandi più utilizzati per mezzo degli
3.2
alias
La dichiarazione di un alias avviene per mezzo del costrutto:
user@home $ alias comando_nuovo="comando [arg1] [arg2] ... [argN]"
• Gli alias non sono attualmente supportati da sersh
Per esempio potrò denire:
user@home $ alias ls="ls -l -k"
in modo da non dover scrivere ogni volta i ag frequentemente usati per il
comando ls.
8
3.3
Redirezione
Una Shell Posix permette la redirezione dei le standard di input, output ed
error associati ai processi. Tramite un'opportuna sintassi è possibile sostituire i
le standard di default specicandone di nuovi.
comando < file
comando <0 file
Indica a comando di usare le come nuovo le di input.
comando > file
comando 1> file
Indica a comando di usare le come nuovo le di output.
comando 2> file
Indica a comando di usare le come nuovo le di error.
• La redirezione dei singoli comandi è supportata da sersh.
In una Shell Posix più comandi possono essere assemblati fra loro per mezzo del
3.3.1 pipelining
• Il pipelining non è al momento supportato da sersh.
L'uso del pipelining permette che lo stdout di un comando sia rediretto verso lo
stdin del comando successivo; è possibile fare questo mediante il simbolo |, pipe.
Esempio
Stampo a video il contenuto della directory corrente.
E' possibile scorrere la pagina.
user@home $ ls
| less
less si occupa di formattare a video quanto letto dal proprio stdin.
ls stampa sul proprio stdout il contenuto della directory corrente.
| fa in modo che lo stdout di ls sia concatenato allo stdin di less.
Esempio
Visualizzo il rigo esatto in cui inizia il main di sersh.c
user@home $ cat sersh.c -n | grep main
70 int main(int argc, char *argv[]) {
cat sersh.c -n stampa sul proprio stdout l'intero le sersh.c aggiungendo i numeri
di riga. grep main legge stdin cercando le righe che abbiano corrispondenza con
la parola main. Se queste righe vengono trovate, vengono allora stampate su
stdout.
9
3.4
Strutture di controllo
Una Shell Posix mette a disposizione le principali strutture di controllo presenti
nella maggior parte dei linguaggi strutturati in modo da permettere la creazione
di Shell Script .
• Le strutture di controlo non sono attualmente supportate da sersh
• Al contrario di quanto accade in C, al valore 0 viene dato valore di verità,
mentre a qualsiasi valore diverso da 0 viene dato valore di falsità.
3.4.1 if ... then ... else ... Equivale al costrutto C if.
Esempio
i=10
if [ $i = 10 ] ; then
echo "i vale 10"
else
echo "i non vale 10"
fi
E' possibile denire if annidati per mezzo della parola chiave elif, contrazione
di else if.
i=14
if [ $i = 1 ]
then
echo "i vale 1";
elif [ $i = 2 ]
then
echo "i vale 2"
else
echo "i non vale ne' 1 ne' 2"
fi
E' possibile denire un costrutto if sull'esito di un comando.
Esempio
Controlla se nel sistema esiste l'utente letto da tastiera
#! /bin/sh
echo "Inserisci il nome dell'utente da cercare"
read utente
if grep $utente /etc/passwd 1> /dev/null 2> /dev/null
echo "L'utente $utente esiste nel sistema"
exit 0
10
; then
else
fi
echo "L'utente $utente non esiste nel sistema"
exit 1
3.4.2 case $var in ... esac
Equivale al costrutto C switch.
Esempio
Confronta un numero inserito da tastiera con 1 e 10
#! /bin/sh
echo "Inserisci un numero"
read num
case $num in
1)
echo "hai inserito 1"
;;
10)
echo "hai inserito 10"
;;
esac
*)
echo "Non hai inserito ne' 1 ne' 10"
;;
3.4.3 for var in ... do ... done
Eettua dei cicli all'interno del codice delimitato da do .. done facendo in modo
che var assuma di volta in volta tutti i valori successivi a in.
Non ha un esatto corrispondete C.
Esempio
#! /bin/sh
for citta in Catania Firenze Napoli Milano Genova Messina
do
echo "$citta e' una citta' italiana"
done
11
3.4.4 while ... do ... done
Cicla all'interno del codice delimitato da do ... done no a quando l'espressione
denita nel while è vera.
Equivale al costrutto
C while.
Esempio
#! /bin/sh
ciclo=0
while [ $ciclo ]
do
echo "Vuoi continuare a ciclare ?"
read risposta
done
if [ $risposta = "si" ] ; then
ciclo=0
else
ciclo=1
fi
12
4
Cenni sul File System Unix
4.1
Astrazione delle risorse
File System signica sistema di archiviazione, ed è compito di ciascun sistema
operativo astrarre le risorse di un computer in modo da renderle idealmente
indipendenti dai propri supporti sici; Unix assolve a questa funzione mediante
l'utilizzo di un'univoca gerarchia di directory, seguendo il paradigma secondo
cui ogni cosa è un le : su Linux il primo disco rigido IDE è indicato dal le
di dispositivo /dev/hda, la prima linea seriale è indicata dal le /dev/ttyS0, il
terminale corrente è sempre indicato da /dev/tty etc.
Questa astrazione nasce da una semplice constatazione: il funzionamento della
stragrande maggioranza dei dispositivi di cui si compone un computer (stampanti, schede audio, schede video, linee seriali ) si basa su due delle più elementari
funzioni di I/O : lettura e scrittura.
Dal momento che le chiamate di read e write per scrivere e leggere da un le
esistono n dalla notte dei tempi, è parso naturale ai padri di Unix associare
a ciascun driver di dispositivo dei le speciali, collocati tradizionalmente nella
directory /dev ; in modo si ore agli sviluppatori una semplice interfaccia per
leggere e scrivere su un dispositivo, prescindendo da qualunque cosa via sotto.
Se per esempio vorrò fare un programma che stampi sulla mia stampante parallela 6 ( /dev/lp0 ) ciascuna riga che andrò inserendo da terminale, basterà
compilare il seguente programma:
#include <stdio.h>
int main(int argc, char *argv[]) {
FILE * printer;
/* Lo userò per la stampante */
char
buffer[200]; /* buffer per la lettura
*/
printer = fopen("/dev/lp0", "r");
/* Apro in lettura la stampante */
while(1) {
}
fprintf(stdout, "\nInserisci una riga");
fgets(buffer, 200, stdin );
/*
fprintf( printer, "%s", buffer );
/*
fflush(printer);
/*
/*
Prendo una riga da terminale */
Stampo sulla stampante */
scarico il buffer relativo */
allo stream printer */
}
Come è possibile vedere dal codice, è stato possibile accedere alla stampante
attraverso un paio di semplicissime istruzioni: le stesse che si usano per i le
ordinari.
6 L'esempio
può essere applicato anche ad una stampante USB, /dev/usblp0
13
Fra tutti i le presenti su un sistema Unix un ruolo di particolare importanza
spetta ai le standard associati a ciascun processo, ovvero
4.2
stdin, stdout, stderr
standard input, output, error
Ciascun processo eseguito su una macchina Unix usa i le stdin, stdout e stderr
rispettivamente per le operazioni di input (normalmente la tastiera), output
(normalmente il monitor di terminale) e noticazioni di errore (anche in questo
caso il monitor di terminale).
Il più grande pregio oerto dai le standard è la possibilità di essere rediretti su altri le : molto spesso problemi apparentemente complessi possono essere
risolti eettuando una semplice redirezione dei ussi standard.
• Come si può vedere dalle prime righe di sersh.c , la redirezione è parecchio
sfruttata da sersh
Per questa ragione scrivere scanf(%s, string ) è del tutto equivalente allo scrivere fscanf(stdin , %s, string ), perché per default stdin è lo stream associato al
le di input. Lo stesso vale per stdout e stderr. Tutto è un le.
Una Shell Posix sfrutta pesantemente questa possibilità facendo in modo che
più programmi possano essere assemblati per creare un comando che di per sè
non esisterebbe.
4.3
Architettura del File System
4.3.1 Directory standard
Tutto quanto ha origine dalla radice, indicata dal simbolo / e chiamata root.
Nella maggior parte dei casi la root risiede sul File System della partizione su
cui si è installato il sistema operativo. 7 All'interno della radice trovano posto
diverse directory di primaria importanza, tra cui:
/mnt
/lib
/boot
/tmp
/dev
/etc
/bin
/sbin
/home
/root
/proc
7a
#
#
#
#
#
#
#
#
#
#
#
Directory per il mounting dei dispositivi removibili
Librerie condivise
kernel e file di boot sotto Linux
File temporanei
File di dispositivo
File di configurazione del sistema
Programmi di uso generale per tutti gli utenti
Programmi riservati all'utente root
Directory per la home degli utenti sotto Linux
Directory home per l'utente root sotto Linux
File System virtuale, interfaccia col kernel sotto Linux
meno che non sia stato eseguito un chroot
14
4.3.2 Multiutenza e permessi
Il requisito che da sempre appartiene a Unix è quello della multiutenza 8 : a più
persone deve essere concesso di lavorare su un singolo computer senza interferire
con il lavoro degli altri.
L'adozione di questo requisito necessita l'implementazione all'interno del SO
di una politica che permetta di determinare chi possa accedere o meno a ciascun le, in modo da garantire che nessun utente, maliziosamente o meno, possa
interferire sul lavoro degli altri.
In Unix ciascun le viene dotato di una maschera ottale in cui si specicano
i diritti in lettura, scrittura ed esecuzione per il possessore del le (owner), il
gruppo di lavoro a cui appartiene il le ed il resto del mondo.
La maschera ottale dei permessi di un le può essere ricavata facilmente per
mezzo del seguente schema:
Possessore
_____________
4
2
1
|
|
|
r
w
x
|
Cifra
Gruppo
_____________
4
2
1
|
|
|
r
w
x
|
Cifra
Resto del mondo
_____________
4
2
1
|
|
|
r
w
x
|
Cifra
Ciascuna delle 3 cifre è uguale alla somma dei valori corrispondenti a
r, w , x.
Avremo quindi:
r--w--x
=
=
=
4 + 0 + 0 =
0 + 2 + 0 =
0 + 0 + 1 =
4
2
1
rwr-x
=
=
4 + 2 + 0 =
4 + 0 + 1 =
6
5
rwx
=
4 + 2 + 1 =
7
E quindi:
-rwxr-xr-x
-r-xr-xr-x
-rw-r--r--rw-------rw-r-----
corrisponde
corrisponde
corrisponde
corrisponde
corrisponde
a
a
a
a
a
755
555
644
600
640
e così via.
8 in
PDP
eetti questo non era vero per i primi Unix implementati sui mitici computer della serie
15
5
Implementazione
5.1
Genesi dei processi
Le principale chiamate di sistema Unix
che competono alla genesi e gestione dei processi sono:
fork
exec
5.1.1 fork
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
si occupa di creare un processo glio che dierisce dal padre solo nel suo Proe PPID.
Il processo glio continua l'esecuzione del codice dall'istruzione successiva alla
fork, ed evolve quindi in modo del tutto indipendente dal padre che lo ha generato. fork ritorna due valori dierenti: nel glio ritorna sempre il valore 0; nel
padre ritorna sempre il pid del processo glio 9 . Esaminare i valori di ritorno
risulta utile subito dopo l'esecuzione di una fork per determinare l'identità del
processo corrente.
cess IDentier e Parent Process IDentier, rispettivamente PID
pid = fork();
/* Mi sono sdoppiato, ma adesso chi sono ? */
if (pid == 0) {
/* Sono il processo figlio */
esegui_codice_processo_figlio();
exit(0);
}
else {
/* Sono il processo padre */
esegui_codice_processo_padre();
exit(0);
}
fork è l'unica chiamata di sistema Unix che permette la creazione di un nuovo processo !
9e
quindi un valore sempre diverso da zero
16
Un caso in cui risulta indispensabile l'uso della chiamata fork è per esempio
quello di un generico Web Server. Un Web Server è un processo daemon in
perenne ascolto sulla porta TCP 80 il cui compito è quello di rispondere alle
interrogazioni HTTP ricevute fornendo ai client remoti10 le dovute risposte11 .
Un Web Server quindi inizia la propria esecuzione ponendosi in ascolto e bloccandosi sulla porta 80 in attesa di connessioni. Non appena viene eseguita una
nuova connessione, il processo si clona mediante una chiamata a fork: in questo
modo il processo glio si occuperà di servire il client remoto inviandogli quanto
richiesto, mentre il processo padre si rimetterà subito in ascolto sulla porta 80
in attesa di servire nuove connessioni.
while(true) {
ascolto_sulla_porta_e_mi_blocco();
pid = fork();
}
/* Ho ricevuto una connessione, quindi mi clono */
if (!pid) {
/* Se sono il figlio servo il client e termino */
servi_il_client_remoto();
exit(0);
}
else continue;
/* Se sono il padre */
/* mi rimetto subito in attesa di altre connessioni */
Ciascun processo al termine della propria esecuzione torna al padre un numero
intero detto codice di uscita, a cui si attribuisce l'esito dell'esecuzione e i motivi
per cui è potuto terminare. 0 indica successo nell'esecuzione, un qualsiasi valore
diverso da zero indica un fallimento. Nel momento in cui un processo termina, il
kernel manda al relativo processo padre un segnale di SIGCHLD per noticare
l'avvenuta morta del glio. Se un processo termina la propria esecuzione senza
che il genitore abbia raccolto il suo codice di uscita, si dice che esso rimane un
processo zombie. Un processo zombie è un processo terminato di cui però il
kernel non rilascia le risorse ( address space, le descriptors ... ) in attesa che
il padre ne raccolga il codice di uscita. La chiamata di sistema che il processo
padre deve invocare alla morte del glio per fare in modo che le risorse del glio
terminato siano disallocate è
5.1.2 waitpid
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);
Raccoglie in *status il codice di uscita del processo glio specicato da pid. Se
pid viene posto uguale a WAIT_ANY, la funzione avrà eetto su qualsiasi
dei processi gli.
10 Browser Internet
11 Pagine HTML, immagini
JPEG, audio MP3 ...
17
options può assumere uno dei seguenti valori:
• 0 waitpid si blocca in attesa della terminazione di un processo glio
•
WNHOHANG waitpid non si blocca se nessun glio è terminato
La chiamata a waitpid con options posto uguale a 0 può essere usata in una
rudimentale forma di sincronizzazione fra processi diversi: padre > glio >
padre.
• Questo è il modo in cui si comporta sersh per i processi mandati in
esecuzioni in foreground
Se altrimenti si vorrà che padre e glio evolvano parallelamente, 12 sarà necessario che il padre si prenda carico di richiamare eplicitamente waitpid installando
un gestore per il segnale SIGCHLD, evitando così la creazione di processi zombie.
E se il padre termina prima del glio ?
In tal caso il processo rimasto orfano verrà adottato da init, e sarà successivamente lo stesso init a prendersi carico di richiamare waitpid alla ricezione di
SIGCHLD.
Un nuovo processo generato per mezzo della funzione fork può eseguire il codice
di un'altro programma rimpiazzando il proprio codice residente in memoria per
mezzo della chiamata 13
5.1.3 exec
Posix mette a disposizione delle funzioni di libreria che rendono più semplice e
essibile l'uso della chiamata exec ed i cui prototipi sono:
#include <unistd.h>
extern char **environ;
int
int
int
int
int
execl(const char *path, const char *arg, ...);
execlp(const char *file, const char *arg, ...);
execle(const char *path, const char *arg , ..., char * const envp[]);
execv(const char *path, char *const argv[]);
execvp(const char *file, char *const argv[]);
Il nuovo programma da mandare in esecuzione di norma deve essere fornito con
il suo percorso assoluto ( /bin/ls per esempio ) nelle stringhe puntate da path
o le. Fanno eccezione execlp e execvp : se il programma non viene indicato nel
suo percorso assoluto, allora sarà automaticamente cercato mediante l'ausilio
della variabile di ambiente PATH specicata, se esiste, all'interno di environ.
12 si ricorda che si tratta di un parallelismo simulato, e non reale
13 In verità sotto Linux la chiamata di sistema si chiama execve, ma per inveterata tradizione
Unix continuerò anche qui a chiamarla exec
18
Gli argomenti da passare al nuovo programma possono essere specicati generalmente in due modi: ponendo in successione i puntatori a ciascuna stringa
interessata ( execl, execlp ) , oppure confezionando ciascun argomento in un
array di stringhe argv terminato dal puntatore NULL. execle si comporta sostianzialemente come execl, ma richiede che l'ultimo argomento sia un vettore di
stringhe da passare al programma come nuovo ambiente.
Bisogna prestare attenzione al primo argomento passato a qualsiasi delle
funzioni exec: argv[0] rappresenta sempre il nome stesso del programma da eseguire, quindi qualsiasi programma si mandi in esecuzione ci si deve curare che
almeno il primo argomento esista e che abbia lo stesso nome del programma
specicato in path o le !
• La funzione utilizzata da sersh è
execvp.
Esempio sull'uso di execvp.
Manda in esecuzione il comando /bin/ls ed esce.
#include <stdio.h>
#include <unistd.h>
main(int argc, char *argv[]) {
char
char
*ls = "/bin/ls";
*arg[] = { ls , (char *) NULL
execvp(ls, arg );
}
19
};
Esempio sull'uso di fork, exec, waitpid.
Aspetta che l'utente inserisca un comando14 e lo manda in esecuzione.
Questa è già una rudimentalissima Shell !
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#define BUFFER_SIZE 50
extern char ** environ;
main(int argc, char *argv[]) {
char buffer[BUFFER_SIZE];
char *arg[] = { buffer, (char *) NULL };
pid_t pid;
while(1) {
printf("\n$ ");
fscanf(stdin, "%s", buffer );
pid = fork();
if (!pid) {
int status;
execvp(buffer, arg);
}
}
}
14 senza
}
fprintf(stderr, "\nComando non valido !");
exit(1);
else {
int exitStatus;
waitpid(pid,&exitStatus,0);
fprintf(stdout, "\nIl processo precedente ") ;
fprintf(stdout, "è terminato con codice %d", exitStatus );
alcun argomento !
20
5.2
Segnali
Come precedentemente accennato, se non si vuole che il padre si sincronizzi sulla
morte del glio, sarà necessario che questi richiami esplicitamente waitpid per
mezzo di un'apposità routine alla ricezione del segnale SIGCHLD . Questo è
possibile per mezzo della chiamata
5.2.1 sigaction
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
sigaction nstalla l'azione specicata dalla struct sigaction act alla ricezione
del segnale specicato da signum. Se oldact non è NULL vi restituisce il
comportamento adottato n'ora.
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int
sa_flags;
void (*sa_restorer) (void);
}
Tralasciando gli aspetti più complessi sull'uso di sigaction e della relativa struttura dati, è necessario sapere che:
• sa_handler è il puntatore ad una funzione void la cui esecuzione avviene
sincronicamente alla ricezione del segnale specicato.
• sa_mask è la maschera dei segnali che devono essere bloccati durante la
ricezione del segnale specicato.
• sa_ags specica particolari comportamenti da adottare alla ricezione del
segnale specicato.
21
Esempio sull'uso di sigaction.
Il programma installa l'azione per la ricezione di SIGTERM e si blocca per
sempre in attesa di ricevere segnali. Ogni volta che riceve un segnale di SIGTERM
stampa un messaggio a video.
#include
#include
#include
#include
<stdio.h>
<sys/types.h>
<unistd.h>
<signal.h>
void handler(int a) {
printf("\nHo ricevuto un SIGTERM!\n");
}
int main(int argc, char *argv[]) {
struct sigaction action;
action.sa_handler = handler;
sigemptyset(&action.sa_mask); /* Non blocco alcun segnale oltre signum */
action.sa_flags = 0;
/* Non specifico alcuna azione particolare */
sigaction(SIGTERM, &action, NULL ); /* Installo l'azione */
while(1) pause();
/* Mi blocco e aspetto per sempre l'arrivo di SIGTERM */
}
Dopo aver compilato il programma per mezzo di un semplicissimo gcc esempio_signal.c -o sig mandate in esecuzione il programma in background :
user@home $ ./sig &
[1] 3862
3862 è il PID del processo appena mandato in esecuzione.
La shell mantiene il PID dell'ultimo processo mandato in esecuzione in background all'interno della variabile di ambiente !
Adesso possiamo inviare SIGTERM al processo per mezzo del comando
user@home $ kill $!
che equivale esattamente allo scrivere
user@home $ kill -SIGTERM 3862
ottenendo
Ho ricevuto un SIGTERM!
Se non specicato diversamente, il comando kill manda il segnale SIGTERM !
Per terminare il processo sarà necessario inviargli un SIGKILL per mezzo di
user@home $ kill -SIGKILL $!
che equivale esattamente allo scrivere,
22
user@home $ kill -SIGKILL 3862
che equivale ancora allo scrivere
user@home $ kill -9 3862
In questo ultimo caso ho specicato SIGKILL per mezzo del suo valore numerico
Per avere la lista delle associazioni segnale-valore date il comando:
user@home $ kill -l
5.2.2 Dierenze fra SIGTERM e SIGKILL
Come si è potuto vedere dall'esempio precedente, ci è stato possibile intercettare
SIGTERM per mezzo di sigaction e farne ciò che ne volevamo, ovvero mostrare
una semplicissima frase sullo schermo ogni qual volta fosse arrivato. Questo ci
è servito come piccolo esempio, ma in verità sotto Unix la ricezione di ciascun
segnale è associata ad un suo preciso signicato.
Normalmente SIGTERM viene inviato ad un processo quando si vuole che
questo termini immediatamente ma in modo pulito. Mettiamo il caso di avere
un programma che tenga aperti contemporaneamente una decina di le; supponiamo quindi di aver appena avviato la procedura di spegnimento per mezzo
di
root@home $ shutdown -h now
Sarà compito di init noticare a tutti i processi in esecuzione sulla macchina il
prossimo spegnimento; questo verrà fatto invitando tutti i processi a terminare
il proprio lavoro nel modo più opportuno mediante l'invio di SIGTERM. Quindi è lecito pensare che il processo con i dieci le aperti avrà una routine per
la ricezione di SIGTERM tale da chiudere tutti i le precedentemente aperti e
richiamare automaticamente exit per terminare.
Sottolineo che SIGTERM può essere intercettato, bloccato o completamente ignorato, quindi non è detto che ciascun processo che lo abbia ricevuto sia automaticamente terminato. init è consapevole di questa possibilità, e quindi,
passato un certo tempo dall'invio di SIGTERM, provvederà a mandare a tutti
i processi rimasti ancora attivi il segnale SIGKILL. SIGKILL a dierenza del
precedente non può essere intercettato, né bloccato, né ignorato, causando per
default la terminazione brutale di chi lo riceve.
Dopo l'invio di SIGKILL init potrà avere la certezza che nessun altro processo
utente sia rimasto attivo sulla macchina, quindi potrà ricorrere all'invocazione
di sync per scaricare i buer sui dischi e arrestare denitivamente la macchina.
SIGTERM è un invito a nire ciò che si stava facendo.
SIGKILL è la terminazione senza appello di chi lo riceve.
23
#include
#include
#include
#include
#include
<stdio.h>
<sys/types.h>
<unistd.h>
<signal.h>
<sys/wait.h>
#define BUFFER_SIZE 50
extern char ** environ;
void catchChild(int a) { /* Funzione da eseguire alla ricezione SIGCHLD */
pid_t pid;
do {
int status;
pid = waitpid(WAIT_ANY, &status, WNOHANG );
if (pid > 0) {
fprintf(stderr, "\nE' terminato figlio %d ", (int) pid
fprintf(stderr, "con exit code %d", status );
}
} while (pid > 0);
);
}
main(int argc, char *argv[]) {
char buffer[BUFFER_SIZE];
char *arg[] = { buffer, (char *) NULL };
pid_t pid;
struct sigaction action;
action.sa_handler = catchChild; /* Inizzializzo struttura action */
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
sigaction(SIGCHLD, &action, NULL); /* Installo azione ricezione SIGCHLD */
while(1) {
printf("\n$ ");
fscanf(stdin, "%s", buffer );
pid = fork();
if (!pid) {
int status;
fprintf(stderr, "\nIl mio pid e' %d\n", getpid() );
execvp(buffer, arg);
24
}
}
}
fprintf(stderr, "\nComando non valido !");
exit(1);
Come si può vedere dal codice, all'interno della funzione catchChild la chiamata
a waitpid è eseguita in un ciclo while; è necessario adottare questo costrutto
per via del modo stesso in cui sono implementati i segnali. Sotto Unix infatti
i segnali non sono cumulabili ; se già un segnale risulta pendente 15 , l'invio di
un'ulteriore segnale della stessa natura passerà come inosservato ; esiste quindi
il rischio che l'invio repentino di numerosi segnali dello stesso tipo possa essere visto come l'invio di un unico segnale. Nel caso dell'esempio precedente
potrebbe quindi accadere che un ulteriore glio termini proprio mentre è in esecuzione catchChild ; l'ulteriore segnale SIGCHLD verrebbe bloccato e quindi,
nel caso in cui si vericasse la morte di un glio proprio mentre in esecuzione
catchChild, questo verrebbe completamente ignorato dal padre, condannando
arbitrariamente un glio a rimanere zombie.
La soluzione più semplice a tale problema è quella di richiamare waitpid all'interno di un ciclo while specicando l'opzione WNOHANG. In questo modo
waitpid verrà mandata in esecuzione senza bloccarsi nché vi sarà un qualsiasi
processo zombie da terminare. Non appena il pid restituito sarà minore di zero,
vorrà dire che non vi saranno ulteriori zombie e sarà quindi possibile uscire dal
ciclo.
15 il
segnale è stato inviato ma non ancora noticato al processo interessato
25
6
GNU Free Documentation License
Version 1.2, November 2002
c 2000,2001,2002 Free Software Foundation, Inc.
Copyright 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.
Preamble
The purpose of this License is to make a manual, textbook, or other functional and useful document free in the sense of freedom: to assure everyone
the eective 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 modications 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.
1. APPLICABILITY AND DEFINITIONS
This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under
the terms of this License. Such a notice grants a world-wide, royalty-free license,
unlimited in duration, to use that work under the conditions stated herein. The
Document, below, refers to any such manual or work. Any member of the
public is a licensee, and is addressed as you. You accept the license if you copy,
modify or distribute the work in a way requiring permission under copyright
law.
A Modied Version of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with modications
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.
(Thus, 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.
26
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. If a section does not t the above
denition of Secondary then it is not allowed to be designated as Invariant.
The Document may contain zero Invariant Sections. If the Document does not
identify any Invariant Sections then there are none.
The Cover Texts are certain short passages of text that are listed, as FrontCover Texts or Back-Cover Texts, in the notice that says that the Document is
released under this License. A Front-Cover Text may be at most 5 words, and
a Back-Cover Text may be at most 25 words.
A Transparent copy of the Document means a machine-readable copy, represented in a format whose specication is available to the general public, that is
suitable for revising the document 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 le format whose markup,
or absence of markup, has been arranged to thwart or discourage subsequent
modication by readers is not Transparent. An image format is not Transparent
if used for any substantial amount of text. 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, PostScript
or PDF designed for human modication. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include 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, PostScript or PDF 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.
A section Entitled XYZ means a named subunit of the Document whose
title either is precisely XYZ or contains XYZ in parentheses following text that
translates XYZ in another language. (Here XYZ stands for a specic section
name mentioned below, such as Acknowledgements, Dedications, Endorsements, or History.) To Preserve the Title of such a section when you modify
the Document means that it remains a section Entitled XYZ according to this
denition.
The Document may include Warranty Disclaimers next to the notice which
states that this License applies to the Document. These Warranty Disclaimers
are considered to be included by reference in this License, but only as regards
disclaiming warranties: any other implication that these Warranty Disclaimers
may have is void and has no eect on the meaning of this License.
2. VERBATIM COPYING
27
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.
3. COPYING IN QUANTITY
If you publish printed copies (or copies in media that commonly have printed
covers) 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 t legibly, you
should put the rst ones listed (as many as t 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 computernetwork location from which the general network-using public has access to
download using public-standard network protocols a complete Transparent copy
of the Document, free of added material. 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.
4. MODIFICATIONS
You may copy and distribute a Modied Version of the Document under the
conditions of sections 2 and 3 above, provided that you release the Modied
Version under precisely this License, with the Modied Version lling the role
of the Document, thus licensing distribution and modication of the Modied
Version to whoever possesses a copy of it. In addition, you must do these things
in the Modied Version:
A. 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
28
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.
B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modications in the Modied Version, together
with at least ve of the principal authors of the Document (all of its principal authors, if it has fewer than ve), unless they release you from this
requirement.
C. State on the Title page the name of the publisher of the Modied Version,
as the publisher.
D. Preserve all the copyright notices of the Document.
E. Add an appropriate copyright notice for your modications adjacent to
the other copyright notices.
F. Include, immediately after the copyright notices, a license notice giving
the public permission to use the Modied Version under the terms of this
License, in the form shown in the Addendum below.
G. Preserve in that license notice the full lists of Invariant Sections and
required Cover Texts given in the Document's license notice.
H. Include an unaltered copy of this License.
I. Preserve the section Entitled History, Preserve its Title, and add to it
an item stating at least the title, year, new authors, and publisher of the
Modied 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 Modied Version as stated in the previous sentence.
J. 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.
K. For any section Entitled Acknowledgements or Dedications, Preserve the
Title of the section, and preserve in the section all the substance and tone
of each of the contributor acknowledgements and/or dedications given
therein.
L. 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.
M. Delete any section Entitled Endorsements. Such a section may not be
included in the Modied Version.
29
N. Do not retitle any existing section to be Entitled Endorsements or to
conict in title with any Invariant Section.
O. Preserve any Warranty Disclaimers.
If the Modied 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
Modied 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 Modied Version by various partiesfor example,
statements of peer review or that the text has been approved by an organization
as the authoritative denition of a standard.
You may add a passage of up to ve 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 Modied 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 Modied Version.
5. COMBINING DOCUMENTS
You may combine the Document with other documents released under this
License, under the terms dened in section 4 above for modied versions, provided that you include in the combination all of the Invariant Sections of all of the
original documents, unmodied, and list them all as Invariant Sections of your
combined work in its license notice, and that you preserve all their Warranty
Disclaimers.
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 dierent 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.
6. 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
30
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.
7. 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, is called an aggregate if the copyright resulting from the compilation
is not used to limit the legal rights of the compilation's users beyond what
the individual works permit. When the Document is included in an aggregate,
this License does not apply to the other works in the aggregate which 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 half of the entire aggregate, the
Document's Cover Texts may be placed on covers that bracket the Document
within the aggregate, or the electronic equivalent of covers if the Document is
in electronic form. Otherwise they must appear on printed covers that bracket
the whole aggregate.
8. TRANSLATION
Translation is considered a kind of modication, 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, and all the license notices in the Document, and any Warranty
Disclaimers, provided that you also include the original English version of this
License and the original versions of those notices and disclaimers. In case of a
disagreement between the translation and the original version of this License or
a notice or disclaimer, the original version will prevail.
If a section in the Document is Entitled Acknowledgements, Dedications,
or History, the requirement (section 4) to Preserve its Title (section 1) will
typically require changing the actual title.
9. 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.
10. FUTURE REVISIONS OF THIS LICENSE
31
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 dier 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 species 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 specied 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.
ADDENDUM: How to use this License for your
documents
To use this License in a document you have written, include a copy of the
License in the document and put the following copyright and license notices just
after the title page:
c YEAR YOUR NAME. Permission is granted to copy,
Copyright distribute and/or modify this document under the terms of the GNU
Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections,
no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled GNU Free Documentation
License.
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
replace the with...Texts. line with this:
with the Invariant Sections being LIST THEIR TITLES, with the
Front-Cover Texts being LIST, and with the Back-Cover Texts being
LIST.
If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation.
If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software
license, such as the GNU General Public License, to permit their use in free
software.
32