Il progetto

GaPiL nasce dalla mia convinzione profonda che la “filosofia” che ispira il software libero si applichi anche ad altri campi che non siano necessariamente quelli della scrittura di programmi per computer. In particolare ritengo che possa assumere una grande rilevanza in ambiti come quelli dell’educazione e della formazione.

Ma se trovare della buona documentazione libera, specie per quanto riguarda i programmi che girano sul sistema GNU/Linux, è ormai relativamente facile, la produzione di buoni testi didattici che insegnino a programmare in questo sistema è ancora molto limitata, soprattutto se li si cercano in lingua italiana.

GaPiL è un tentativo di scrivere un manuale di programmazione di sistema in ambiente di tipo Unix, con una particolare attenzione alle caratteristiche specifiche delle interfacce fornite dal kernel Linux. Per questo motivo si parla di Linux e non di GNU/Linux.

Nonostante questa specificità, essendo la gran parte delle funzioni di sistema standardizzate, la guida dovrebbe risultare utile anche facendo riferimenti ad altri sistemi di tipo Unix come i vari *BSD; in ogni caso si sono sottolineate esplicitamente le caratteristiche specifiche di Linux.

Benché buona parte della trattazione delle funzioni di libreria sia del tutto identica, facendo riferimento a standard generali come POSIX, si è comunque prestata particolare attenzione alle funzioni delle GNU libc, che sono la versione più usata delle librerie del C, senza dimenticare, ove note, di citare le differenze con possibili alternative come le libc5 o le uclibc.

L’obiettivo resta comunque quello di riuscire a produrre un testo, rilasciato sotto GNU FDL, che possa servire a chi si accosta per la prima volta alla programmazione avanzata e di sistema su un kernel Linux, con la speranza di poter un giorno raggiungere la qualità dei lavori del compianto R. W. Stevens.

Share

Revisione dell’introduzione a file e directory

Nella revisione del testo iniziata con le vacanze natalizie, e che procederà lentamente nei prossimi mesi, il precedente quarto capitolo, L’architettura dei file, è stato completamente eliminato.

Trattandosi di una introduzione all’architettura dei file una prima metà dei contenuti (quella di carattere più generale, con i tipi di file, l’albero unico e il significato dei pathname) stati riportati più correttamente all’inizio nel primo capitolo, in una nuova sezione aggiunta fra le due precedenti, volta ad illustrare a grandi linee l’architettura della gestione dei file in un sistema unix-like.

La parte finale del capitolo, dedicata al funzionamento del Virtual File System di Linux (dentry, inode, ecc.) e alla descrizione della strutturazione generica di un filesystem per Linux è invece stata inserita in una nuova sezione iniziale di quello che era il precedente capitolo 5, cui si è aggiunta, essendo strettamente correlata, la parte relativa alla system call mount che in precedenza era trattata molto più avanti, nella sezione sulla gestione del sistema.

Tutte queste parti, essendo alquanto datate, sono state riviste profondamente, se non addirittura, come fatto per la sezione dedicata al funzionamento del Virtual File System, riscritte da zero. Inoltre nella aggiunta della parte relativa alla system call mount si sono trattate in dettaglio alcune delle opzioni avanzate introdotte nei kernel più recenti, come il bind mount e gli shared subtree. In particolare si sono cercate di trattare queste ultime, che al momento non sono documentate neanche nelle pagine di manuale della system call.

PS
Per eseguire un test diretto dei vari flag si è scritto un semplice programma per l’invocazione diretta della della system call mount, che consente di indicare, senza nessun controllo sulla correttezza della stessa, una qualunque combinazione di flag di montaggio. Il programma passa direttamente anche gli altri argomenti della funzione (opzioni del filesystem, tipo del filesystem, sorgente e target)

Il codice del comando è disponibile nel file mymount.c, lanciato con l’opzione -h stampa una breve spiegazione, i vari mount flags si specificano con una lista di nomi seprati da virgole per l’opzione -f. I nomi sono quelli dei corrispondenti flag MS_* togliendo il suffisso MS_ e mettendoli in minuscolo. Il programma è stato anche un buon esercizio sulle funzioni di ricerca sulle stringhe della glibc.

Share

Revisione terzo capitolo

La revisione del terzo capitolo sulle funzioni di gestione dei processi è stata completata.

Si è aggiornata la parte sull’ordine di esecuzione dei processi dopo una fork, si sono aggiunti brevi cenni e i relativi rimandi al numero di argomenti che si possono passare con una exec, si è aggiornata la trattazione di nice con le differenza introdotte nelle ultime versioni dello scheduler, in particolare riguardo le time slice,e si sono trattate tutte le macro per la gestione dei CPU set.

La trattazione della system call clone e la parte finale del capitolo con le funzioni avanzate è ancora incompleta.

Share

Rivisti i capitoli 1 e 2

La revisione dei primi due capitoli della guida è stata completata. In particolare il secondo capitolo ha visto una serie di risistemazioni con l’accorpamento e la ristrutturazione di alcune sezioni. Si è spiegata con maggior dettaglio la differenza fra system call e chiamate a funzioni ed il ruolo del link-loader ed il significato di variabili automatiche, globali, statiche ecc.

Si è migliorata la sezione sulla allocazione della memoria con delle correzioni ad alcune imprecisioni ed una più chiara esposizione del layout della memoria di un processo, si sono aggiornate le sezioni sulle funzioni variadic e le variabili di ambiente. La sezione sulla localizzazione resta incompleta.

Share

Inizio revisione

Approfittando delle ferie natalizie ho iniziato la revisione della Guida per renderla stampabile in formato Crown Quarti (quello dei testi della OReilly, tanto per fare un esempio) e cercare di migliorare anche alcune formattazioni (in particolare quelle dei riquadri delle funzioni) e sistemare una serie di macro Latex.

Per questo motivo fin tanto che la revisione sarà in corso si potranno avere errori di compilazione e una formattazione incoerente dei contenuti utilizzando la versione scaricabile da SVN.

Share

Upload nuovo PDF

Dato che il PDF pubblicato (nella pagina dei download) era parecchio vecchio ho provveduto ad una sua ripubblicazione. Ho aggiornato anche la versione stampabile su Lulu.com, ed il relativo PDF. Questa sarà probabilmente l’ultima versione in volume unico essendo ormai raggiunto il limite delle 750 pagine oltre il quale non è possibile più stampare un testo.

Share

Completate le sezioni su “capabilities” e ”prctl”

La sezione sulle capabilities è stata completamente rivista, con tutti gli aggiornamenti alla situazione realizzata con l’introduzione del supporto completo delle stesse a partire dal kernel 2.6.26.

Al contempo è stata introdotta una nuova sezione sulla system call prtcl, e ristrutturata la parte finale del capitolo sui processi, introducendo una sezione, ancora completamente da scrivere, su clone.

Share

In memoria

Poco tempo fa è morta una delle persone più significative nella storia dell’informatica, un uomo che ha lasciato un segno indelebile nello sviluppo di questa disciplina.

No, non si tratta di Steve Jobs.

Dennis Ritchie non era un imprenditore di successo che riusciava a vendere a proseliti adoranti macchine chiuse e costose usabili solo come gadget tecnologici secondo quanto imposto dalla sua azienda.

Dennis Ritchie era un ricercatore, una persona che l’informatica l’ha creata, dando un contributo il cui rilievo non sta nella apparenza, ma nella sostanza.

Dennis Ritchie non era neanche un informatico, era un fisico che si appassionò alla nuova scienza ed andò a lavorare ai laboratori della AT&T.

Lì con Brian Kernigan dette vita al C, il linguaggio con cui sono scritti tutti i sistemi operativi (almeno tutti quelli di uso pratico).

Lì con Ken Thompson creò Unix, un sistema operativo la cui architettura, nonostante i decenni passati, resta totalmente attuale ed è alla base, oltre che di Linux, anche del sistema usato dal venditore di successo.

Uno solo di questi risultati sarebbe stato sufficiente ad entrare nella storia dell’informatica, una persona capace di essere alla base di due delle più grandi innovazioni di questa disciplina non può che meritare un tributo eccezionale.

Ma non aspettatevi di trovarlo nei dibattiti in televisione, al più finirà in qualche trafiletto secondario sui giornali. L’apparenza oggi purtroppo conta molto di della sostanza, ed il successo di misura in fatturato, non in invenzioni.

Se si deve ricordare una persona che ha davvero creato qualcosa di significativo e importante nell’informatica, difficilmente qualcuno potrà superarlo.

Riporto qui per quanto girato sulla rete in sua memoria:

Dennis Ritchies logged-off
His pointer has been cast to void *
His process has terminated with exit code 0
Share

Trattazione delle quote disco

Al capitolo sulla gestione di file e directory è stata aggiunta una nuova sezione dedicata alla trattazione delle funzioni (in realtà è una sola, quotactl) per la gestione delle quote disco. Oltre alle spiegazioni sono stati aggiunti alcuni esempi di un modulo Python (scritto in C) che consente di effettuare le operazioni sulle quote disco chiamando direttamente la suddetta funzione.

Per l’occasione il modulo è stato esteso anche con la gestione dell’impostazione dei grace time, e pubblicato insieme ai sorgenti dei pacchetti Debian di Truelite, pertanto si potrà ottenerne il codice completo a partire dalla relativa pagina, raggiungibile all’indirizzo:

http://labs.truelite.it/projects/packages/wiki/QuotaModule

Share

Revisione del capitolo su terminali e sessioni

Ho completato una breve revisione del capitolo 10, originariamente intitolato “Terminali e sessioni di lavoro“. Il nuovo titolo, che tiene conto del fatto che vi si parla anche di demoni e del syslog, è diventato “Interfaccia utente: terminali e sessioni di lavoro“.

Sono stati aggiornate e riviste alcune parti introduttive, sottolineando il significato della console di sistema, e riscritta in buona parte la sezione su demoni e syslog, aggiungendo alcune funzioni di libreria (vsyslog, closelog) che non erano state trattate e aggiungendo la trattazione della gestione dei log del kernel (klogctl) prima totalmente assente.

Per fare alcuni test relativi all’uso di klogctl si è inoltre scritto un piccolo programma di test (mydmesg.c) che ha anche rivelato che una delle operazioni di klogctl non si comporta esattamente come descritto nella pagina di manuale.

Infine sono state riviste anche le parti relative alla gestione dei terminali, aggiornando i flags di termios, e le varie funzioni associate alla manipolazione delle caratteristiche dei terminali, aggiungendo alcune funzioni non trattate precedentemente (cfmakeraw, cfsetspeed). Resta ancora da fare la parte sulla gestione dei terminali virtuali.

Share

Alcuni dettagli di timerfd.

A partire dal kernel 2.6.25 è stata introdotta una interfaccia di gestione alternativa per i timer di sistema che consente la ricezione delle notifiche di scadenza attraverso dei file descriptor invece che tramite segnali o thread, chiamata convenzionalmente timerfd.

L’interfaccia è specifica di Linux e si unisce ad altre due (signalfd e eventfd) che seguono la stessa filosofia per la ricezione di segnali e di eventi dal kernel. Il grande vantaggio è che queste possono essere usate in combinazione con le funzioni dell’I/O multiplexing (poll, select ed epoll) semplificando notevolmente la gestione l’attesa contemporanea di eventi e dati.

L’interfaccia timerfd segue da vicino quella introdotta da POSIX.1-2001 che è trattata nella sezione 9.5.2 della guida, che però fa ricorso a meccanismi di notifica classici. Nel trattare la nuova interfaccia mi è sorto un dubbio relativo al funzionamento della stessa quando si esegue una fork.

Con i timer ordinari infatti un processo figlio non eredita dopo una fork nessuno dei timer del padre. La semantica Unix prevede però che un file descriptor sia duplicato attraverso una fork, e dato che in questo caso un timer viene associato ad un file descriptor la domanda su cosa accada al timer nel processo figlio sorge spontanea.

La documentazione dice che il file descriptor associato ad un timer continua a seguire la semantica ordinaria e viene duplicato nel figlio. Viene cioè preferita la semantica dei file descriptor rispetto a quella dei timer ordinari. Sorge però spontanea la domanda di cosa succede se padre e figlio iniziano a leggere entrambi da tale file descriptor per ricevere la notifica delle scadenze dei timer.

La documentazione delle pagine di manuale, almeno nella versione della mia Debian, non dice nulla, ma “a naso” ci si aspetterebbe che accada la stessa cosa che accade per un file descriptor duplicato, e cioè che chi legge per primo riceve i dati, lasciando “a bocca asciutta” l’altro processo.

Per verificarlo ho comunque scritto un programma di test, test_timerfdfork.c, che arma un timer con timerfd esegue una fork ed usa epoll per l’attesa in entrambi i processi. Il programma prevede delle opzioni per specificare i valori della struttura itimerspec che impostano prima scadenza e ripetizione del timer.

Se lo eseguiamo mettendo un tempo di prima scadenza a due secondi, ed un tempo di ripetizione ad un secondo, otterremo qualcosa del tipo:

piccardi@hain:~/gapil/sources$ gcc test_timerfdfork.c
piccardi@hain:~/gapil/sources$ ./a.out -i1 -t2
Timer interval 2 sec, timer time 1 sec
Got 1 events, pid 12513, time 1308661930
Timer expired in pid 12513:
Expired 1 times in pid 12513
Got 1 events, pid 0, time 1308661930
Timer expired in pid 0:
Got 1 events, pid 0, time 1308661931
Timer expired in pid 0:
Expired 1 times in pid 0
Got 1 events, pid 0, time 1308661932
Timer expired in pid 0:
Expired 1 times in pid 0
Got 1 events, pid 0, time 1308661933
Timer expired in pid 0:
Expired 1 times in pid 0

e come ci si aspettava viene letta una scadenza alla volta, nel caso la prima volta nel figlio e le successive nel padre (ma la cosa è casuale e rilanciandolo di possono ottenere diversi risultati), cosa che corrisponde al fatto che il primo processo che esegue una lettura sul file descriptor riceve il dato della scadenza.

Share
This work by Simone Piccardi is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported.