Commit edba5eec authored by Federico Vaga's avatar Federico Vaga Committed by Jonathan Corbet

doc:it_IT: add some process/* translations

This patch does not translate entirely the subfolder "process/"
but only part of it (to begin with).

In order to avoid broken links, I included empty documents
for those which are not yet translated.

In order to be able to refer to all documents in "process/",
I added a sphinx label to those which had not one.

Translated documents:
- howto
- 1.Intro
- clang-format
- coding-style
- kernel-driver-statement
- magic-number
- volatile-considered-harmful
- development-process
Signed-off-by: default avatarFederico Vaga <federico.vaga@vaga.pv.it>
Signed-off-by: default avatarAlessia Mantegazza <amantegazza@vaga.pv.it>
Signed-off-by: default avatarJonathan Corbet <corbet@lwn.net>
parent 2a1e03ca
.. _development_process_intro:
Introduction
============
......
.. _addsyscalls:
Adding a New System Call
========================
......
.. _process_howto:
HOWTO do Linux kernel development
=================================
......
.. _process_statement_driver:
Kernel Driver Statement
-----------------------
......
Linux Kernel Enforcement Statement
.. _process_statement_kernel:
Linux Kernel Enforcement Statement
----------------------------------
As developers of the Linux kernel, we have a keen interest in how our software
......
.. _magicnumbers:
Linux magic numbers
===================
......
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/admin-guide/README.rst <readme>`
.. _it_readme:
Rilascio del kernel Linux 4.x <http://kernel.org/>
===================================================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
.. _it_securitybugs:
Bachi di sicurezza
==================
.. warning::
TODO ancora da tradurre
......@@ -86,6 +86,7 @@ vostre modifiche molto più semplice
.. toctree::
:maxdepth: 2
process/index
doc-guide/index
kernel-hacking/index
......
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/1.Intro.rst <development_process_intro>`
:Translator: Alessia Mantegazza <amantegazza@vaga.pv.it>
.. _it_development_intro:
Introduzione
============
Riepilogo generale
------------------
Il resto di questa sezione riguarda la sfera del processo di sviluppo del
kernel e quella sorta di frustrazioni che gli sviluppatori e i loro datori
di lavoro affrontano. Ci sono molte ragioni per le quali del codice per il
kernel debba essere incorporato nel kernel ufficiale, fra le quali:
disponibilità immediata agli utilizzatori, supporto della comunità in
differenti modalità, e la capacità di influenzare la direzione dello sviluppo
kernel.
Il codice che contribuisce al kernel Linux deve essere reso disponibile sotto
una licenza GPL-compatibile.
La sezione :ref:`it_development_process` introduce il processo di sviluppo,
il ciclo di rilascio del kernel, ed i meccanismi della finestra
d'incorporazione. Il capitolo copre le varie fasi di una modifica: sviluppo,
revisione e ciclo d'incorporazione. Ci sono alcuni dibattiti su strumenti e
liste di discussione. Gli sviluppatori che sono in attesa di poter sviluppare
qualcosa per il kernel sono invitati ad individuare e sistemare bachi come
esercizio iniziale.
La sezione :ref: `it_development_early_stage` copre i primi stadi della
pianificazione di un progetto di sviluppo, con particolare enfasi sul
coinvolgimento della comunità, il prima possibile.
La sezione :ref:`it_development_coding` riguarda il processo di scrittura
del codice. Qui, sono esposte le diverse insidie che sono state già affrontate
da altri sviluppatori. Il capitolo copre anche alcuni dei requisiti per le
modifiche, ed esiste un'introduzione ad alcuni strumenti che possono aiutarvi
nell'assicurarvi che le modifiche per il kernel siano corrette.
La sezione :ref:`it_development_posting` parla del processo di pubblicazione
delle modifiche per la revisione. Per essere prese in considerazione dalla
comunità di sviluppo, le modifiche devono essere propriamente formattate ed
esposte, e devono essere inviate nel posto giusto. Seguire i consigli presenti
in questa sezione dovrebbe essere d'aiuto nell'assicurare la migliore
accoglienza possibile del vostro lavoro.
La sezione :ref: `it_development_followthrough` copre ciò che accade dopo
la pubblicazione delle modifiche; a questo punto il lavoro è lontano
dall'essere concluso. Lavorare con i revisori è una parte cruciale del
processo di sviluppo; questa sezione offre una serie di consigli su come
evitare problemi in questa importante fase. Gli sviluppatori sono diffidenti
nell'affermare che il lavoro è concluso quando una modifica è incorporata nei
sorgenti principali.
La sezione :ref::`it_development_advancedtopics` introduce un paio di argomenti
"avanzati": gestire modifiche con git e controllare le modifiche pubblicate da
altri.
La sezione :ref: `it_development_conclusion` chiude il documento con dei
riferimenti ad altre fonti che forniscono ulteriori informazioni sullo sviluppo
del kernel.
Di cosa parla questo documento
------------------------------
Il kernel Linux, ha oltre 8 milioni di linee di codice e ben oltre 1000
contributori ad ogni rilascio; è uno dei più vasti e più attivi software
liberi progettati mai esistiti. Sin dal sul modesto inizio nel 1991,
questo kernel si è evoluto nel miglior componente per sistemi operativi
che fanno funzionare piccoli riproduttori musicali, PC, grandi super computer
e tutte le altre tipologie di sistemi fra questi estremi. È una soluzione
robusta, efficiente ed adattabile a praticamente qualsiasi situazione.
Con la crescita di Linux è arrivato anche un aumento di sviluppatori
(ed aziende) desiderosi di partecipare a questo sviluppo. I produttori di
hardware vogliono assicurarsi che il loro prodotti siano supportati da Linux,
rendendo questi prodotti attrattivi agli utenti Linux. I produttori di
sistemi integrati, che usano Linux come componente di un prodotto integrato,
vogliono che Linux sia capace ed adeguato agli obiettivi ed il più possibile
alla mano. Fornitori ed altri produttori di software che basano i propri
prodotti su Linux hanno chiaro interesse verso capacità, prestazioni ed
affidabilità del kernel Linux. E gli utenti finali, anche, spesso vorrebbero
cambiare Linux per renderlo più aderente alle proprie necessità.
Una delle caratteristiche più coinvolgenti di Linux è quella dell'accessibilità
per gli sviluppatori; chiunque con le capacità richieste può migliorare
Linux ed influenzarne la direzione di sviluppo. Prodotti non open-source non
possono offrire questo tipo di apertura, che è una caratteristica del softwere
libero. Ma, anzi, il kernel è persino più aperto rispetto a molti altri
progetti di software libero. Un classico ciclo di sviluppo trimestrale può
coinvolgere 1000 sviluppatori che lavorano per più di 100 differenti aziende
(o per nessuna azienda).
Lavorare con la comunità di sviluppo del kernel non è particolarmente
difficile. Ma, ciononostante, diversi potenziali contributori hanno trovato
delle difficoltà quando hanno cercato di lavorare sul kernel. La comunità del
kernel utilizza un proprio modo di operare che gli permette di funzionare
agevolmente (e genera un prodotto di alta qualità) in un ambiente dove migliaia
di stringhe di codice sono modificate ogni giorni. Quindi non deve sorprendere
che il processo di sviluppo del kernel differisca notevolmente dai metodi di
sviluppo privati.
Il processo di sviluppo del Kernel può, dall'altro lato, risultare
intimidatorio e strano ai nuovi sviluppatori, ma ha dietro di se buone ragioni
e solide esperienze. Uno sviluppatore che non comprenda i modi della comunità
del kernel (o, peggio, che cerchi di aggirarli o violarli) avrà un'esperienza
deludente nel proprio bagagliaio. La comunità di sviluppo, sebbene sia utile
a coloro che cercano di imparare, ha poco tempo da dedicare a coloro che non
ascoltano o coloro che non sono interessati al processo di sviluppo.
Si spera che coloro che leggono questo documento saranno in grado di evitare
queste esperienze spiacevoli. C'è molto materiale qui, ma lo sforzo della
lettura sarà ripagato in breve tempo. La comunità di sviluppo ha sempre
bisogno di sviluppatori che vogliano aiutare a rendere il kernel migliore;
il testo seguente potrebbe esservi d'aiuto - o essere d'aiuto ai vostri
collaboratori- per entrare a far parte della nostra comunità.
Crediti
-------
Questo documento è stato scritto da Jonathan Corbet, corbet@lwn.net.
È stato migliorato da Johannes Berg, James Berry, Alex Chiang, Roland
Dreier, Randy Dunlap, Jake Edge, Jiri Kosina, Matt Mackall, Arthur Marsh,
Amanda McPherson, Andrew Morton, Andrew Price, Tsugikazu Shibata e Jochen Voß.
Questo lavoro è stato supportato dalla Linux Foundation; un ringraziamento
speciale ad Amanda McPherson, che ha visto il valore di questo lavoro e lo ha
reso possibile.
L'importanza d'avere il codice nei sorgenti principali
------------------------------------------------------
Alcune aziende e sviluppatori ogni tanto si domandano perchè dovrebbero
preoccuparsi di apprendere come lavorare con la comunità del kernel e di
inserire il loro codice nel ramo di sviluppo principale (per ramo principale
s'intende quello mantenuto da Linus Torvalds e usato come base dai
distributori Linux). Nel breve termine, contribuire al codice può sembrare
un costo inutile; può sembra più facile tenere separato il proprio codice e
supportare direttamente i suoi utilizzatori. La verità è che il tenere il
codice separato ("fuori dai sorgenti", *"out-of-tree"*) è un falso risparmio.
Per dimostrare i costi di un codice "fuori dai sorgenti", eccovi
alcuni aspetti rilevanti del processo di sviluppo kernel; la maggior parte
di essi saranno approfonditi dettagliatamente più avanti in questo documento.
Pensate:
- Il codice che è stato inserito nel ramo principale del kernel è disponibile
a tutti gli utilizzatori Linux. Sarà automaticamente presente in tutte le
distribuzioni che lo consentono. Non c'è bisogno di: driver per dischi,
scaricare file, o della scocciatura del dover supportare diverse versoni di
diverse distribuzioni; funziona già tutto, per gli sviluppatori e per gli
utilizzatori. L'inserimento nel ramo principale risolve un gran numero di
problemi di distribuzione e di supporto.
- Nonostante gli sviluppatori kernel si sforzino di tenere stabile
l'interfaccia dello spazio utente, quella interna al kernel è in continuo
cambiamento. La mancanza di un'interfaccia interna è deliberatamente una
decisione di progettazione; ciò permette che i miglioramenti fondamentali
vengano fatti in un qualsiasi momento e che risultino fatti con un codice di
alta qualità. Ma una delle conseguenze di questa politica è che qualsiasi
codice "fuori dai sorgenti" richiede costante manutenzione per renderlo
funzionante coi kernel più recenti. Tenere un codice "fuori dai sorgenti"
richiede una mole di lavoro significativa solo per farlo funzionare.
Invece, il codice che si trova nel ramo principale non necessita di questo
tipo di lavoro poiché ad ogni sviluppatore che faccia una modifica alle
interfacce viene richiesto di sistemare anche il codice che utilizza che
utilizza quell'interfaccia. Quindi, il codice che è stato inserito nel
ramo principale ha dei costi di mantenimento significativamente più bassi.
- Oltre a ciò, spesso il codice che è all'interno del kernel sarà migliorato da
altri sviluppatori. Dare pieni poteri alla vostra comunità di utenti e ai
clienti può portare a sorprendenti risultati che migliorano i vostri
prodotti.
- Il codice kernel è soggetto a revisioni, sia prima che dopo l'inserimento
nel ramo principale. Non importa quanto forti fossero le abilità dello
sviluppatore originale, il processo di revisione trovà il modo di migliore
il codice. Spesso la revisione trova bachi importanti e problemi di
sicurezza. Questo è particolarmente vero per il codice che è stato
sviluppato in un ambiete chiuso; tale codice ottiene un forte beneficio
dalle revisioni provenienti da sviluppatori esteri. Il codice
"fuori dai sorgenti", invece, è un codice di bassa qualità.
- La partecipazione al processo di sviluppo costituisce la vostra via per
influenzare la direzione di sviluppo del kernel. Gli utilizzatori che
"reclamano da bordo campo" sono ascoltati, ma gli sviluppatori attivi
hanno una voce più forte - e la capacità di implementare modifiche che
renderanno il kernel più funzionale alle loro necessità.
- Quando il codice è gestito separatamente, esiste sempre la possibilità che
terze parti contribuiscano con una differente implementazione che fornisce
le stesse funzionalità. Se dovesse accadere, l'inserimento del codice
diventerà molto più difficile - fino all'impossibilità. Poi, dovrete far
fronte a delle alternative poco piacevoli, come: (1) mantenere un elemento
non standard "fuori dai sorgenti" per un tempo indefinito, o (2) abbandonare
il codice e far migrare i vostri utenti alla versione "nei sorgenti".
- Contribuire al codice è l'azione fondamentale che fa funzione tutto il
processo. Contribuendo attraverso il vostro codice potete aggiungere nuove
funzioni al kernel e fornire competenze ed esempi che saranno utili ad
altri sviluppatori. Se avete sviluppato del codice Linux (o state pensando
di farlo), avete chiaramente interesse nel far proseguire il successo di
questa piattaforma. Contribuire al codice è une delle migliori vie per
aiutarne il successo.
Il ragionamento sopra citato si applica ad ogni codice "fuori dai sorgenti"
dal kernel, incluso il codice proprietario distribuito solamente in formato
binario. Ci sono, comunque, dei fattori aggiuntivi che dovrebbero essere
tenuti in conto prima di prendere in considerazione qualsiasi tipo di
distribuzione binaria di codice kernel. Questo include che:
- Le questioni legali legate alla distribuzione di moduli kernel proprietari
sono molto nebbiose; parecchi detentori di copyright sul kernel credono che
molti moduli binari siano prodotti derivati del kernel e che, come risultato,
la loro diffusione sia una violazione della licenza generale di GNU (della
quale si parlerà più avanti). Il vostro ideatore non è un avvocato, e
niente in questo documento può essere considerato come un consiglio legale.
Il vero stato legale dei moduli proprietari può essere determinato
esclusivamente da un giudice. Ma l'incertezza che perseguita quei moduli
è lì comunque.
- I moduli binari aumentano di molto la difficoltà di fare debugging del
kernel, al punto che la maggior parte degli sviluppatori del kernel non
vorranno nemmeno tentare. Quindi la diffusione di moduli esclusivamente
binari renderà difficile ai vostri utilizzatori trovare un supporto dalla
comunità.
- Il supporto è anche difficile per i distributori di moduli binari che devono
fornire una versione del modulo per ogni distribuzione e per ogni versione
del kernel che vogliono supportate. Per fornire una copertura ragionevole e
comprensiva, può essere richiesto di produrre dozzine di singoli moduli.
E inoltre i vostri utilizzatori dovranno aggiornare il vostro modulo
separatamente ogni volta che aggiornano il loro kernel.
- Tutto ciò che è stato detto prima riguardo alla revisione del codice si
applica doppiamente al codice proprietario. Dato che questo codice non é
del tutto disponibile, non può essere revisionato dalla comunità e avrà,
senza dubbio, seri problemi.
I produttori di sistemi integrati, in particolare, potrebbero esser tentati
dall'evitare molto di ciò che è stato detto in questa sezione, credendo che
stiano distribuendo un prodotto finito che utilizza una versione del kernel
immutabile e che non richiede un ulteriore sviluppo dopo il rilascio. Questa
idea non comprende il valore di una vasta revisione del codice e il valore
del permettere ai propri utenti di aggiungere funzionalità al vostro prodotto.
Ma anche questi prodotti, hanno una vita commerciale limitata, dopo la quale
deve essere rilasciata una nuova versione. A quel punto, i produttori il cui
codice è nel ramo principale di sviluppo avranno un codice ben mantenuto e
saranno in una posizione migliore per ottenere velocemente un nuovo prodotto
pronto per essere distribuito.
Licenza
-------
IL codice Linux utilizza diverse licenze, ma il codice completo deve essere
compatibile con la seconda versione della licenza GNU General Public License
(GPLv2), che è la licenza che copre la distribuzione del kernel.
Nella pratica, ciò significa che tutti i contributi al codice sono coperti
anche'essi dalla GPLv2 (con, opzionalmente, una dicitura che permette la
possibilità di distribuirlo con licenze più recenti di GPL) o dalla licenza
three-clause BSD. Qualsiasi contributo che non è coperto da una licenza
compatibile non verrà accettata nel kernel.
Per il codice sottomesso al kernel non è necessario (o richiesto) la
concessione del Copyright. Tutto il codice inserito nel ramo principale del
kernel conserva la sua proprietà originale; ne risulta che ora il kernel abbia
migliaia di proprietari.
Una conseguenza di questa organizzazione della proprietà è che qualsiasi
tentativo di modifica della licenza del kernel è destinata ad quasi sicuro
fallimento. Esistono alcuni scenari pratici nei quali il consenso di tutti
i detentori di copyright può essere ottenuto (o il loro codice verrà rimosso
dal kernel). Quindi, in sostanza, non esiste la possibilità che si giunga ad
una versione 3 della licenza GPL nel prossimo futuro.
È imperativo che tutto il codice che contribuisce al kernel sia legittimamente
software libero. Per questa ragione, un codice proveniente da un contributore
anonimo (o sotto pseudonimo) non verrà accettato. È richiesto a tutti i
contributori di firmare il proprio codice, attestando così che quest'ultimo
può essere distribuito insieme al kernel sotto la licenza GPL. Il codice che
non è stato licenziato come software libero dal proprio creatore, o che
potrebbe creare problemi di copyright per il kernel (come il codice derivante
da processi di ingegneria inversa senza le opportune tutele), non può essere
diffuso.
Domande relative a questioni legate al copyright sono frequenti nelle liste
di discussione dedicate allo sviluppo di Linux. Tali quesiti, normalmente,
non riceveranno alcuna risposta, ma una cosa deve essere tenuta presente:
le persone che risponderanno a quelle domande non sono avvocati e non possono
fornire supporti legali. Se avete questioni legali relative ai sorgenti
del codice Linux, non esiste alternativa che quella di parlare con un
avvocato esperto nel settore. Fare affidamento sulle risposte ottenute da
una lista di discussione tecnica è rischioso.
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/2.Process.rst <development_process>`
.. _it_development_process:
Come funziona il processo di sviluppo
=====================================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/3.Early-stage.rst <development_early_stage>`
.. _it_development_early_stage:
Primi passi della pianificazione
================================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/4.Coding.rst <development_coding>`
.. _it_development_coding:
Scrivere codice corretto
========================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/4.Posting.rst <development_posting>`
.. _it_development_posting:
Pubblicare modifiche
====================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/6.Followthrough.rst <development_followthrough>`
Completamento
=============
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/7.AdvancedTopics.rst <development_advancedtopics>`
.. _it_development_advancedtopics:
Argomenti avanzati
==================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/8.Conclusion.rst <development_conclusion>`
.. _it_development_conclusion:
Per maggiori informazioni
=========================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/adding-syscalls.rst <addsyscalls>`
.. _it_addsyscalls:
Aggiungere una nuova chiamata di sistema
========================================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/applying-patches.rst <applying_patches>`
.. _it_applying_patches:
Applicare modifiche al kernel Linux
===================================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/changes.rst <changes>`
.. _it_changes:
Requisiti minimi per compilare il kernel
++++++++++++++++++++++++++++++++++++++++
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/clang-format.rst <clangformat>`
:Translator: Federico Vaga <federico.vaga@vaga.pv.it>
.. _it_clangformat:
clang-format
============
``clang-format`` è uno strumento per formattare codice C/C++/... secondo
un gruppo di regole ed euristiche. Come tutti gli strumenti, non è perfetto
e non copre tutti i singoli casi, ma è abbastanza buono per essere utile.
``clang-format`` può essere usato per diversi fini:
- Per riformattare rapidamente un blocco di codice secondo lo stile del
kernel. Particolarmente utile quando si sposta del codice e lo si
allinea/ordina. Vedere it_clangformatreformat_.
- Identificare errori di stile, refusi e possibili miglioramenti nei
file che mantieni, le modifiche che revisioni, le differenze,
eccetera. Vedere it_clangformatreview_.
- Ti aiuta a seguire lo stile del codice, particolarmente utile per i
nuovi arrivati o per coloro che lavorano allo stesso tempo su diversi
progetti con stili di codifica differenti.
Il suo file di configurazione è ``.clang-format`` e si trova nella cartella
principale dei sorgenti del kernel. Le regole scritte in quel file tentano
di approssimare le lo stile di codifica del kernel. Si tenta anche di seguire
il più possibile
:ref:`Documentation/translations/it_IT/process/coding-style.rst <it_codingstyle>`.
Dato che non tutto il kernel segue lo stesso stile, potreste voler aggiustare
le regole di base per un particolare sottosistema o cartella. Per farlo,
potete sovrascriverle scrivendole in un altro file ``.clang-format`` in
una sottocartella.
Questo strumento è già stato incluso da molto tempo nelle distribuzioni
Linux più popolari. Cercate ``clang-format`` nel vostro repositorio.
Altrimenti, potete scaricare una versione pre-generata dei binari di LLVM/clang
oppure generarlo dai codici sorgenti:
http://releases.llvm.org/download.html
Troverete più informazioni ai seguenti indirizzi:
https://clang.llvm.org/docs/ClangFormat.html
https://clang.llvm.org/docs/ClangFormatStyleOptions.html
.. _it_clangformatreview:
Revisionare lo stile di codifica per file e modifiche
-----------------------------------------------------
Eseguendo questo programma, potrete revisionare un intero sottosistema,
cartella o singoli file alla ricerca di errori di stile, refusi o
miglioramenti.
Per farlo, potete eseguire qualcosa del genere::
# Make sure your working directory is clean!
clang-format -i kernel/*.[ch]
E poi date un'occhiata a *git diff*.
Osservare le righe di questo diff è utile a migliorare/aggiustare
le opzioni di stile nel file di configurazione; così come per verificare
le nuove funzionalità/versioni di ``clang-format``.
``clang-format`` è in grado di leggere diversi diff unificati, quindi
potrete revisionare facilmente delle modifiche e *git diff*.
La documentazione si trova al seguente indirizzo:
https://clang.llvm.org/docs/ClangFormat.html#script-for-patch-reformatting
Per evitare che ``clang-format`` formatti alcune parti di un file, potete
scrivere nel codice::
int formatted_code;
// clang-format off
void unformatted_code ;
// clang-format on
void formatted_code_again;
Nonostante si attraente l'idea di utilizzarlo per mantenere un file
sempre in sintonia con ``clang-format``, specialmente per file nuovi o
se siete un manutentore, ricordatevi che altre persone potrebbero usare
una versione diversa di ``clang-format`` oppure non utilizzarlo del tutto.
Quindi, dovreste trattenervi dall'usare questi marcatori nel codice del
kernel; almeno finché non vediamo che ``clang-format`` è diventato largamente
utilizzato.
.. _it_clangformatreformat:
Riformattare blocchi di codice
------------------------------
Utilizzando dei plugin per il vostro editor, potete riformattare una
blocco (selezione) di codice con una singola combinazione di tasti.
Questo è particolarmente utile: quando si riorganizza il codice, per codice
complesso, macro multi-riga (e allineare le loro "barre"), eccetera.
Ricordatevi che potete sempre aggiustare le modifiche in quei casi dove
questo strumento non ha fatto un buon lavoro. Ma come prima approssimazione,
può essere davvero molto utile.
Questo programma si integra con molti dei più popolari editor. Alcuni di
essi come vim, emacs, BBEdit, Visaul Studio, lo supportano direttamente.
Al seguente indirizzo troverete le istruzioni:
https://clang.llvm.org/docs/ClangFormat.html
Per Atom, Eclipse, Sublime Text, Visual Studio Code, XCode e altri editor
e IDEs dovreste essere in grado di trovare dei plugin pronti all'uso.
Per questo caso d'uso, considerate l'uso di un secondo ``.clang-format``
che potete personalizzare con le vostre opzioni.
Consultare it_clangformatextra_.
.. _it_clangformatmissing:
Cose non supportate
-------------------
``clang-format`` non ha il supporto per alcune cose che sono comuni nel
codice del kernel. Sono facili da ricordare; quindi, se lo usate
regolarmente, imparerete rapidamente a evitare/ignorare certi problemi.
In particolare, quelli più comuni che noterete sono:
- Allineamento di ``#define`` su una singola riga, per esempio::
#define TRACING_MAP_BITS_DEFAULT 11
#define TRACING_MAP_BITS_MAX 17
#define TRACING_MAP_BITS_MIN 7
contro::
#define TRACING_MAP_BITS_DEFAULT 11
#define TRACING_MAP_BITS_MAX 17
#define TRACING_MAP_BITS_MIN 7
- Allineamento dei valori iniziali, per esempio::
static const struct file_operations uprobe_events_ops = {
.owner = THIS_MODULE,
.open = probes_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
.write = probes_write,
};
contro::
static const struct file_operations uprobe_events_ops = {
.owner = THIS_MODULE,
.open = probes_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
.write = probes_write,
};
.. _it_clangformatextra:
Funzionalità e opzioni aggiuntive
---------------------------------
Al fine di minimizzare le differenze fra il codice attuale e l'output
del programma, alcune opzioni di stile e funzionalità non sono abilitate
nella configurazione base. In altre parole, lo scopo è di rendere le
differenze le più piccole possibili, permettendo la semplificazione
della revisione di file, differenze e modifiche.
In altri casi (per esempio un particolare sottosistema/cartella/file), lo
stile del kernel potrebbe essere diverso e abilitare alcune di queste
opzioni potrebbe dare risultati migliori.
Per esempio:
- Allineare assegnamenti (``AlignConsecutiveAssignments``).
- Allineare dichiarazioni (``AlignConsecutiveDeclarations``).
- Riorganizzare il testo nei commenti (``ReflowComments``).
- Ordinare gli ``#include`` (``SortIncludes``).
Piuttosto che per interi file, solitamente sono utili per la riformattazione
di singoli blocchi. In alternativa, potete creare un altro file
``.clang-format`` da utilizzare con il vostro editor/IDE.
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/code-of-conduct.rst <code_of_conduct>`
.. _it_code_of_conduct:
Accordo dei contributori sul codice di condotta
+++++++++++++++++++++++++++++++++++++++++++++++
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/coding-style.rst <codingstyle>`
:Translator: Federico Vaga <federico.vaga@vaga.pv.it>
.. _it_codingstyle:
Stile del codice per il kernel Linux
====================================
Questo è un breve documento che descrive lo stile di codice preferito per
il kernel Linux. Lo stile di codifica è molto personale e non voglio
**forzare** nessuno ad accettare il mio, ma questo stile è quello che
dev'essere usato per qualsiasi cosa che io sia in grado di mantenere, e l'ho
preferito anche per molte altre cose. Per favore, almeno tenete in
considerazione le osservazioni espresse qui.
La prima cosa che suggerisco è quella di stamparsi una copia degli standard
di codifica GNU e di NON leggerla. Bruciatela, è un grande gesto simbolico.
Comunque, ecco i punti:
1) Indentazione
---------------
La tabulazione (tab) è di 8 caratteri e così anche le indentazioni. Ci sono
alcuni movimenti di eretici che vorrebbero l'indentazione a 4 (o perfino 2!)
caratteri di profondità, che è simile al tentativo di definire il valore del
pi-greco a 3.
Motivazione: l'idea dell'indentazione è di definire chiaramente dove un blocco
di controllo inizia e finisce. Specialmente quando siete rimasti a guardare lo
schermo per 20 ore a file, troverete molto più facile capire i livelli di
indentazione se questi sono larghi.
Ora, alcuni rivendicano che un'indentazione da 8 caratteri sposta il codice
troppo a destra e che quindi rende difficile la lettura su schermi a 80
caratteri. La risposta a questa affermazione è che se vi servono più di 3
livelli di indentazione, siete comunque fregati e dovreste correggere il vostro
programma.
In breve, l'indentazione ad 8 caratteri rende più facile la lettura, e in
aggiunta vi avvisa quando state annidando troppo le vostre funzioni.
Tenete ben a mente questo avviso.
Al fine di facilitare l'indentazione del costrutto switch, si preferisce
allineare sulla stessa colonna la parola chiave ``switch`` e i suoi
subordinati ``case``. In questo modo si evita una doppia indentazione per
i ``case``. Un esempio.:
.. code-block:: c
switch (suffix) {
case 'G':
case 'g':
mem <<= 30;
break;
case 'M':
case 'm':
mem <<= 20;
break;
case 'K':
case 'k':
mem <<= 10;
/* fall through */
default:
break;
}
A meno che non vogliate nascondere qualcosa, non mettete più istruzioni sulla
stessa riga:
.. code-block:: c
if (condition) do_this;
do_something_everytime;
né mettete più assegnamenti sulla stessa riga. Lo stile del kernel
è ultrasemplice. Evitate espressioni intricate.
Al di fuori dei commenti, della documentazione ed escludendo i Kconfig, gli
spazi non vengono mai usati per l'indentazione, e l'esempio qui sopra è
volutamente errato.
Procuratevi un buon editor di testo e non lasciate spazi bianchi alla fine
delle righe.
2) Spezzare righe lunghe e stringhe
-----------------------------------
Lo stile del codice riguarda la leggibilità e la manutenibilità utilizzando
strumenti comuni.
Il limite delle righe è di 80 colonne e questo e un limite fortemente
desiderato.
Espressioni più lunghe di 80 colonne saranno spezzettate in pezzi più piccoli,
a meno che eccedere le 80 colonne non aiuti ad aumentare la leggibilità senza
nascondere informazioni. I pezzi derivati sono sostanzialmente più corti degli
originali e vengono posizionati più a destra. Lo stesso si applica, nei file
d'intestazione, alle funzioni con una lista di argomenti molto lunga. Tuttavia,
non spezzettate mai le stringhe visibili agli utenti come i messaggi di
printk, questo perché inibireste la possibilità d'utilizzare grep per cercarle.
3) Posizionamento di parentesi graffe e spazi
---------------------------------------------
Un altro problema che s'affronta sempre quando si parla di stile in C è
il posizionamento delle parentesi graffe. Al contrario della dimensione
dell'indentazione, non ci sono motivi tecnici sulla base dei quali scegliere
una strategia di posizionamento o un'altra; ma il modo qui preferito,
come mostratoci dai profeti Kernighan e Ritchie, è quello di
posizionare la parentesi graffa di apertura per ultima sulla riga, e quella
di chiusura per prima su una nuova riga, così:
.. code-block:: c
if (x is true) {
we do y
}
Questo è valido per tutte le espressioni che non siano funzioni (if, switch,
for, while, do). Per esempio:
.. code-block:: c
switch (action) {
case KOBJ_ADD:
return "add";
case KOBJ_REMOVE:
return "remove";
case KOBJ_CHANGE:
return "change";
default:
return NULL;
}
Tuttavia, c'è il caso speciale, le funzioni: queste hanno la parentesi graffa
di apertura all'inizio della riga successiva, quindi:
.. code-block:: c
int function(int x)
{
body of function
}
Eretici da tutto il mondo affermano che questa incoerenza è ...
insomma ... incoerente, ma tutte le persone ragionevoli sanno che (a)
K&R hanno **ragione** e (b) K&R hanno ragione. A parte questo, le funzioni
sono comunque speciali (non potete annidarle in C).
Notate che la graffa di chiusura è da sola su una riga propria, ad
**eccezione** di quei casi dove è seguita dalla continuazione della stessa
espressione, in pratica ``while`` nell'espressione do-while, oppure ``else``
nell'espressione if-else, come questo:
.. code-block:: c
do {
body of do-loop
} while (condition);
e
.. code-block:: c
if (x == y) {
..
} else if (x > y) {
...
} else {
....
}
Motivazione: K&R.
Inoltre, notate che questo posizionamento delle graffe minimizza il numero
di righe vuote senza perdere di leggibilità. In questo modo, dato che le
righe sul vostro schermo non sono una risorsa illimitata (pensate ad uno
terminale con 25 righe), avrete delle righe vuote da riempire con dei
commenti.
Non usate inutilmente le graffe dove una singola espressione è sufficiente.
.. code-block:: c
if (condition)
action();
e
.. code-block:: none
if (condition)
do_this();
else
do_that();
Questo non vale nel caso in cui solo un ramo dell'espressione if-else
contiene una sola espressione; in quest'ultimo caso usate le graffe per
entrambe i rami:
.. code-block:: c
if (condition) {
do_this();
do_that();
} else {
otherwise();
}
Inoltre, usate le graffe se un ciclo contiene più di una semplice istruzione:
.. code-block:: c
while (condition) {
if (test)
do_something();
}
3.1) Spazi
**********
Lo stile del kernel Linux per quanto riguarda gli spazi, dipende
(principalmente) dalle funzioni e dalle parole chiave. Usate una spazio dopo
(quasi tutte) le parole chiave. L'eccezioni più evidenti sono sizeof, typeof,
alignof, e __attribute__, il cui aspetto è molto simile a quello delle
funzioni (e in Linux, solitamente, sono usate con le parentesi, anche se il
linguaggio non lo richiede; come ``sizeof info`` dopo aver dichiarato
``struct fileinfo info``).
Quindi utilizzate uno spazio dopo le seguenti parole chiave::
if, switch, case, for, do, while
ma non con sizeof, typeof, alignof, o __attribute__. Ad esempio,
.. code-block:: c
s = sizeof(struct file);
Non aggiungete spazi attorno (dentro) ad un'espressione fra parentesi. Questo
esempio è **brutto**:
.. code-block:: c
s = sizeof( struct file );
Quando dichiarate un puntatore ad una variabile o una funzione che ritorna un
puntatore, il posto suggerito per l'asterisco ``*`` è adiacente al nome della
variabile o della funzione, e non adiacente al nome del tipo. Esempi:
.. code-block:: c
char *linux_banner;
unsigned long long memparse(char *ptr, char **retptr);
char *match_strdup(substring_t *s);
Usate uno spazio attorno (da ogni parte) alla maggior parte degli operatori
binari o ternari, come i seguenti::
= + - < > * / % | & ^ <= >= == != ? :
ma non mettete spazi dopo gli operatori unari::
& * + - ~ ! sizeof typeof alignof __attribute__ defined
nessuno spazio dopo l'operatore unario suffisso di incremento o decremento::
++ --
nessuno spazio dopo l'operatore unario prefisso di incremento o decremento::
++ --
e nessuno spazio attorno agli operatori dei membri di una struttura ``.`` e
``->``.
Non lasciate spazi bianchi alla fine delle righe. Alcuni editor con
l'indentazione ``furba`` inseriranno gli spazi bianchi all'inizio di una nuova
riga in modo appropriato, quindi potrete scrivere la riga di codice successiva
immediatamente. Tuttavia, alcuni di questi stessi editor non rimuovono
questi spazi bianchi quando non scrivete nulla sulla nuova riga, ad esempio
perché volete lasciare una riga vuota. Il risultato è che finirete per avere
delle righe che contengono spazi bianchi in coda.
Git vi avviserà delle modifiche che aggiungono questi spazi vuoti di fine riga,
e può opzionalmente rimuoverli per conto vostro; tuttavia, se state applicando
una serie di modifiche, questo potrebbe far fallire delle modifiche successive
perché il contesto delle righe verrà cambiato.
4) Assegnare nomi
-----------------
C è un linguaggio spartano, e così dovrebbero esserlo i vostri nomi. Al
contrario dei programmatori Modula-2 o Pascal, i programmatori C non usano
nomi graziosi come ThisVariableIsATemporaryCounter. Un programmatore C
chiamerebbe questa variabile ``tmp``, che è molto più facile da scrivere e
non è una delle più difficili da capire.
TUTTAVIA, nonostante i nomi con notazione mista siano da condannare, i nomi
descrittivi per variabili globali sono un dovere. Chiamare una funzione
globale ``pippo`` è un insulto.
Le variabili GLOBALI (da usare solo se vi servono **davvero**) devono avere
dei nomi descrittivi, così come le funzioni globali. Se avete una funzione
che conta gli utenti attivi, dovreste chiamarla ``count_active_users()`` o
qualcosa di simile, **non** dovreste chiamarla ``cntusr()``.
Codificare il tipo di funzione nel suo nome (quella cosa chiamata notazione
ungherese) fa male al cervello - il compilatore conosce comunque il tipo e
può verificarli, e inoltre confonde i programmatori. Non c'è da
sorprendersi che MicroSoft faccia programmi bacati.
Le variabili LOCALI dovrebbero avere nomi corti, e significativi. Se avete
un qualsiasi contatore di ciclo, probabilmente sarà chiamato ``i``.
Chiamarlo ``loop_counter`` non è produttivo, non ci sono possibilità che
``i`` possa non essere capito. Analogamente, ``tmp`` può essere una qualsiasi
variabile che viene usata per salvare temporaneamente un valore.
Se avete paura di fare casino coi nomi delle vostre variabili locali, allora
avete un altro problema che è chiamato sindrome dello squilibrio dell'ormone
della crescita delle funzioni. Vedere il capitolo 6 (funzioni).
5) Definizione di tipi (typedef)
--------------------------------
Per favore non usate cose come ``vps_t``.
Usare il typedef per strutture e puntatori è uno **sbaglio**. Quando vedete:
.. code-block:: c
vps_t a;
nei sorgenti, cosa significa?
Se, invece, dicesse:
.. code-block:: c
struct virtual_container *a;
potreste dire cos'è effettivamente ``a``.
Molte persone pensano che la definizione dei tipi ``migliori la leggibilità``.
Non molto. Sono utili per:
(a) gli oggetti completamente opachi (dove typedef viene proprio usato allo
scopo di **nascondere** cosa sia davvero l'oggetto).
Esempio: ``pte_t`` eccetera sono oggetti opachi che potete usare solamente
con le loro funzioni accessorie.
.. note::
Gli oggetti opachi e le ``funzioni accessorie`` non sono, di per se,
una bella cosa. Il motivo per cui abbiamo cose come pte_t eccetera è
che davvero non c'è alcuna informazione portabile.
(b) i tipi chiaramente interi, dove l'astrazione **aiuta** ad evitare
confusione sul fatto che siano ``int`` oppure ``long``.
u8/u16/u32 sono typedef perfettamente accettabili, anche se ricadono
nella categoria (d) piuttosto che in questa.
.. note::
Ancora - dev'esserci una **ragione** per farlo. Se qualcosa è
``unsigned long``, non c'è alcun bisogno di avere:
typedef unsigned long myfalgs_t;
ma se ci sono chiare circostanze in cui potrebbe essere ``unsigned int``
e in altre configurazioni ``unsigned long``, allora certamente typedef
è una buona scelta.
(c) quando di rado create letteralmente dei **nuovi** tipi su cui effettuare
verifiche.
(d) circostanze eccezionali, in cui si definiscono nuovi tipi identici a
quelli definiti dallo standard C99.
Nonostante ci voglia poco tempo per abituare occhi e cervello all'uso dei
tipi standard come ``uint32_t``, alcune persone ne obiettano l'uso.
Perciò, i tipi specifici di Linux ``u8/u16/u32/u64`` e i loro equivalenti
con segno, identici ai tipi standard, sono permessi- tuttavia, non sono
obbligatori per il nuovo codice.
(e) i tipi sicuri nella spazio utente.
In alcune strutture dati visibili dallo spazio utente non possiamo
richiedere l'uso dei tipi C99 e nemmeno i vari ``u32`` descritti prima.
Perciò, utilizziamo __u32 e tipi simili in tutte le strutture dati
condivise con lo spazio utente.
Magari ci sono altri casi validi, ma la regola di base dovrebbe essere di
non usare MAI MAI un typedef a meno che non rientri in una delle regole
descritte qui.
In generale, un puntatore, o una struttura a cui si ha accesso diretto in
modo ragionevole, non dovrebbero **mai** essere definite con un typedef.
6) Funzioni
-----------
Le funzioni dovrebbero essere brevi e carine, e fare una cosa sola. Dovrebbero
occupare uno o due schermi di testo (come tutti sappiamo, la dimensione
di uno schermo secondo ISO/ANSI è di 80x24), e fare una cosa sola e bene.
La massima lunghezza di una funziona è inversamente proporzionale alla sua
complessità e al livello di indentazione di quella funzione. Quindi, se avete
una funzione che è concettualmente semplice ma che è implementata come un
lunga (ma semplice) sequenza di caso-istruzione, dove avete molte piccole cose
per molti casi differenti, allora va bene avere funzioni più lunghe.
Comunque, se avete una funzione complessa e sospettate che uno studente
non particolarmente dotato del primo anno delle scuole superiori potrebbe
non capire cosa faccia la funzione, allora dovreste attenervi strettamente ai
limiti. Usate funzioni di supporto con nomi descrittivi (potete chiedere al
compilatore di renderle inline se credete che sia necessario per le
prestazioni, e probabilmente farà un lavoro migliore di quanto avreste potuto
fare voi).
Un'altra misura delle funzioni sono il numero di variabili locali. Non
dovrebbero eccedere le 5-10, oppure state sbagliando qualcosa. Ripensate la
funzione, e dividetela in pezzettini. Generalmente, un cervello umano può
seguire facilmente circa 7 cose diverse, di più lo confonderebbe. Lo sai
d'essere brillante, ma magari vorresti riuscire a capire cos'avevi fatto due
settimane prima.
Nei file sorgenti, separate le funzioni con una riga vuota. Se la funzione è
esportata, la macro **EXPORT** per questa funzione deve seguire immediatamente
la riga della parentesi graffa di chiusura. Ad esempio:
.. code-block:: c
int system_is_up(void)
{
return system_state == SYSTEM_RUNNING;
}
EXPORT_SYMBOL(system_is_up);
Nei prototipi di funzione, includete i nomi dei parametri e i loro tipi.
Nonostante questo non sia richiesto dal linguaggio C, in Linux viene preferito
perché è un modo semplice per aggiungere informazioni importanti per il
lettore.
7) Centralizzare il ritorno delle funzioni
------------------------------------------
Sebbene sia deprecata da molte persone, l'istruzione goto è impiegata di
frequente dai compilatori sotto forma di salto incondizionato.
L'istruzione goto diventa utile quando una funzione ha punti d'uscita multipli
e vanno eseguite alcune procedure di pulizia in comune. Se non è necessario
pulire alcunché, allora ritornate direttamente.
Assegnate un nome all'etichetta di modo che suggerisca cosa fa la goto o
perché esiste. Un esempio di un buon nome potrebbe essere ``out_free_buffer:``
se la goto libera (free) un ``buffer``. Evitate l'uso di nomi GW-BASIC come
``err1:`` ed ``err2:``, potreste doverli riordinare se aggiungete o rimuovete
punti d'uscita, e inoltre rende difficile verificarne la correttezza.
I motivo per usare le goto sono:
- i salti incondizionati sono più facili da capire e seguire
- l'annidamento si riduce
- si evita di dimenticare, per errore, di aggiornare un singolo punto d'uscita
- aiuta il compilatore ad ottimizzare il codice ridondante ;)
.. code-block:: c
int fun(int a)
{
int result = 0;
char *buffer;
buffer = kmalloc(SIZE, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
if (condition1) {
while (loop1) {
...
}
result = 1;
goto out_free_buffer;
}
...
out_free_buffer:
kfree(buffer);
return result;
}
Un baco abbastanza comune di cui bisogna prendere nota è il ``one err bugs``
che assomiglia a questo:
.. code-block:: c
err:
kfree(foo->bar);
kfree(foo);
return ret;
Il baco in questo codice è che in alcuni punti d'uscita la variabile ``foo`` è
NULL. Normalmente si corregge questo baco dividendo la gestione dell'errore in
due parti ``err_free_bar:`` e ``err_free_foo:``:
.. code-block:: c
err_free_bar:
kfree(foo->bar);
err_free_foo:
kfree(foo);
return ret;
Idealmente, dovreste simulare condizioni d'errore per verificare i vostri
percorsi d'uscita.
8) Commenti
-----------
I commenti sono una buona cosa, ma c'è anche il rischio di esagerare. MAI
spiegare COME funziona il vostro codice in un commento: è molto meglio
scrivere il codice di modo che il suo funzionamento sia ovvio, inoltre
spiegare codice scritto male è una perdita di tempo.
Solitamente, i commenti devono dire COSA fa il codice, e non COME lo fa.
Inoltre, cercate di evitare i commenti nel corpo della funzione: se la
funzione è così complessa che dovete commentarla a pezzi, allora dovreste
tornare al punto 6 per un momento. Potete mettere dei piccoli commenti per
annotare o avvisare il lettore circa un qualcosa di particolarmente arguto
(o brutto), ma cercate di non esagerare. Invece, mettete i commenti in
testa alla funzione spiegando alle persone cosa fa, e possibilmente anche
il PERCHÉ.
Per favore, quando commentate una funzione dell'API del kernel usate il
formato kernel-doc. Per maggiori dettagli, leggete i file in
:ref::ref:`Documentation/translations/it_IT/doc-guide/ <it_doc_guide>` e in
``script/kernel-doc``.
Lo stile preferito per i commenti più lunghi (multi-riga) è:
.. code-block:: c
/*
* This is the preferred style for multi-line
* comments in the Linux kernel source code.
* Please use it consistently.
*
* Description: A column of asterisks on the left side,
* with beginning and ending almost-blank lines.
*/
Per i file in net/ e in drivers/net/ lo stile preferito per i commenti
più lunghi (multi-riga) è leggermente diverso.
.. code-block:: c
/* The preferred comment style for files in net/ and drivers/net
* looks like this.
*
* It is nearly the same as the generally preferred comment style,
* but there is no initial almost-blank line.
*/
È anche importante commentare i dati, sia per i tipi base che per tipi
derivati. A questo scopo, dichiarate un dato per riga (niente virgole
per una dichiarazione multipla). Questo vi lascerà spazio per un piccolo
commento per spiegarne l'uso.
9) Avete fatto un pasticcio
---------------------------
Va bene, li facciamo tutti. Probabilmente vi è stato detto dal vostro
aiutante Unix di fiducia che ``GNU emacs`` formatta automaticamente il
codice C per conto vostro, e avete notato che sì, in effetti lo fa, ma che
i modi predefiniti non sono proprio allettanti (infatti, sono peggio che
premere tasti a caso - un numero infinito di scimmie che scrivono in
GNU emacs non faranno mai un buon programma).
Quindi, potete sbarazzarvi di GNU emacs, o riconfigurarlo con valori più
sensati. Per fare quest'ultima cosa, potete appiccicare il codice che
segue nel vostro file .emacs:
.. code-block:: none
(defun c-lineup-arglist-tabs-only (ignored)
"Line up argument lists by tabs, not spaces"
(let* ((anchor (c-langelem-pos c-syntactic-element))
(column (c-langelem-2nd-pos c-syntactic-element))
(offset (- (1+ column) anchor))
(steps (floor offset c-basic-offset)))
(* (max steps 1)
c-basic-offset)))
(add-hook 'c-mode-common-hook
(lambda ()
;; Add kernel style
(c-add-style
"linux-tabs-only"
'("linux" (c-offsets-alist
(arglist-cont-nonempty
c-lineup-gcc-asm-reg
c-lineup-arglist-tabs-only))))))
(add-hook 'c-mode-hook
(lambda ()
(let ((filename (buffer-file-name)))
;; Enable kernel mode for the appropriate files
(when (and filename
(string-match (expand-file-name "~/src/linux-trees")
filename))
(setq indent-tabs-mode t)
(setq show-trailing-whitespace t)
(c-set-style "linux-tabs-only")))))
Questo farà funzionare meglio emacs con lo stile del kernel per i file che
si trovano nella cartella ``~/src/linux-trees``.
Ma anche se doveste fallire nell'ottenere una formattazione sensata in emacs
non tutto è perduto: usate ``indent``.
Ora, ancora, GNU indent ha la stessa configurazione decerebrata di GNU emacs,
ed è per questo che dovete passargli alcune opzioni da riga di comando.
Tuttavia, non è così terribile, perché perfino i creatori di GNU indent
riconoscono l'autorità di K&R (le persone del progetto GNU non sono cattive,
sono solo mal indirizzate sull'argomento), quindi date ad indent le opzioni
``-kr -i8`` (che significa ``K&R, 8 caratteri di indentazione``), o utilizzate
``scripts/Lindent`` che indenterà usando l'ultimo stile.
``indent`` ha un sacco di opzioni, e specialmente quando si tratta di
riformattare i commenti dovreste dare un'occhiata alle pagine man.
Ma ricordatevi: ``indent`` non è un correttore per una cattiva programmazione.
Da notare che potete utilizzare anche ``clang-format`` per aiutarvi con queste
regole, per riformattare rapidamente ad automaticamente alcune parti del
vostro codice, e per revisionare interi file al fine di identificare errori
di stile, refusi e possibilmente anche delle migliorie. È anche utile per
ordinare gli ``#include``, per allineare variabili/macro, per ridistribuire
il testo e altre cose simili.
Per maggiori dettagli, consultate il file
:ref:`Documentation/translations/it_IT/process/clang-format.rst <it_clangformat>`.
10) File di configurazione Kconfig
----------------------------------
Per tutti i file di configurazione Kconfig* che si possono trovare nei
sorgenti, l'indentazione è un po' differente. Le linee dopo un ``config``
sono indentate con un tab, mentre il testo descrittivo è indentato di
ulteriori due spazi. Esempio::
config AUDIT
bool "Auditing support"
depends on NET
help
Enable auditing infrastructure that can be used with another
kernel subsystem, such as SELinux (which requires this for
logging of avc messages output). Does not do system-call
auditing without CONFIG_AUDITSYSCALL.
Le funzionalità davvero pericolose (per esempio il supporto alla scrittura
per certi filesystem) dovrebbero essere dichiarate chiaramente come tali
nella stringa di titolo::
config ADFS_FS_RW
bool "ADFS write support (DANGEROUS)"
depends on ADFS_FS
...
Per la documentazione completa sui file di configurazione, consultate
il documento Documentation/translations/it_IT/kbuild/kconfig-language.txt
11) Strutture dati
------------------
Le strutture dati che hanno una visibilità superiore al contesto del
singolo thread in cui vengono create e distrutte, dovrebbero sempre
avere un contatore di riferimenti. Nel kernel non esiste un
*garbage collector* (e fuori dal kernel i *garbage collector* sono lenti
e inefficienti), questo significa che **dovete** assolutamente avere un
contatore di riferimenti per ogni cosa che usate.
Avere un contatore di riferimenti significa che potete evitare la
sincronizzazione e permette a più utenti di accedere alla struttura dati
in parallelo - e non doversi preoccupare di una struttura dati che
improvvisamente sparisce dalla loro vista perché il loro processo dormiva
o stava facendo altro per un attimo.
Da notare che la sincronizzazione **non** si sostituisce al conteggio dei
riferimenti. La sincronizzazione ha lo scopo di mantenere le strutture
dati coerenti, mentre il conteggio dei riferimenti è una tecnica di gestione
della memoria. Solitamente servono entrambe le cose, e non vanno confuse fra
di loro.
Quando si hanno diverse classi di utenti, le strutture dati possono avere
due livelli di contatori di riferimenti. Il contatore di classe conta
il numero dei suoi utenti, e il contatore globale viene decrementato una
sola volta quando il contatore di classe va a zero.
Un esempio di questo tipo di conteggio dei riferimenti multi-livello può
essere trovato nella gestore della memoria (``struct mm_sturct``: mm_user e
mm_count), e nel codice dei filesystem (``struct super_block``: s_count e
s_active).
Ricordatevi: se un altro thread può trovare la vostra struttura dati, e non
avete un contatore di riferimenti per essa, quasi certamente avete un baco.
12) Macro, enumerati e RTL
---------------------------
I nomi delle macro che definiscono delle costanti e le etichette degli
enumerati sono scritte in maiuscolo.
.. code-block:: c
#define CONSTANT 0x12345
Gli enumerati sono da preferire quando si definiscono molte costanti correlate.
I nomi delle macro in MAIUSCOLO sono preferibili ma le macro che assomigliano
a delle funzioni possono essere scritte in minuscolo.
Generalmente, le funzioni inline sono preferibili rispetto alle macro che
sembrano funzioni.
Le macro che contengono più istruzioni dovrebbero essere sempre chiuse in un
blocco do - while:
.. code-block:: c
#define macrofun(a, b, c) \
do { \
if (a == 5) \
do_this(b, c); \
} while (0)
Cose da evitare quando si usano le macro:
1) le macro che hanno effetti sul flusso del codice:
.. code-block:: c
#define FOO(x) \
do { \
if (blah(x) < 0) \
return -EBUGGERED; \
} while (0)
sono **proprio** una pessima idea. Sembra una chiamata a funzione ma termina
la funzione chiamante; non cercate di rompere il decodificatore interno di
chi legge il codice.
2) le macro che dipendono dall'uso di una variabile locale con un nome magico:
.. code-block:: c
#define FOO(val) bar(index, val)
potrebbe sembrare una bella cosa, ma è dannatamente confusionario quando uno
legge il codice e potrebbe romperlo con una cambiamento che sembra innocente.
3) le macro con argomenti che sono utilizzati come l-values; questo potrebbe
ritorcervisi contro se qualcuno, per esempio, trasforma FOO in una funzione
inline.
4) dimenticatevi delle precedenze: le macro che definiscono espressioni devono
essere racchiuse fra parentesi. State attenti a problemi simili con le macro
parametrizzate.
.. code-block:: c
#define CONSTANT 0x4000
#define CONSTEXP (CONSTANT | 3)
5) collisione nello spazio dei nomi quando si definisce una variabile locale in
una macro che sembra una funzione:
.. code-block:: c
#define FOO(x) \
({ \
typeof(x) ret; \
ret = calc_ret(x); \
(ret); \
})
ret è un nome comune per una variabile locale - __foo_ret difficilmente
andrà in conflitto con una variabile già esistente.
Il manuale di cpp si occupa esaustivamente delle macro. Il manuale di sviluppo
di gcc copre anche l'RTL che viene usato frequentemente nel kernel per il
linguaggio assembler.
13) Visualizzare i messaggi del kernel
--------------------------------------
Agli sviluppatori del kernel piace essere visti come dotti. Tenete un occhio
di riguardo per l'ortografia e farete una belle figura. In inglese, evitate
l'uso di parole mozzate come ``dont``: usate ``do not`` oppure ``don't``.
Scrivete messaggi concisi, chiari, e inequivocabili.
I messaggi del kernel non devono terminare con un punto fermo.
Scrivere i numeri fra parentesi (%d) non migliora alcunché e per questo
dovrebbero essere evitati.
Ci sono alcune macro per la diagnostica in <linux/device.h> che dovreste
usare per assicurarvi che i messaggi vengano associati correttamente ai
dispositivi e ai driver, e che siano etichettati correttamente: dev_err(),
dev_warn(), dev_info(), e così via. Per messaggi che non sono associati ad
alcun dispositivo, <linux/printk.h> definisce pr_info(), pr_warn(), pr_err(),
eccetera.
Tirar fuori un buon messaggio di debug può essere una vera sfida; e quando
l'avete può essere d'enorme aiuto per risolvere problemi da remoto.
Tuttavia, i messaggi di debug sono gestiti differentemente rispetto agli
altri. Le funzioni pr_XXX() stampano incondizionatamente ma pr_debug() no;
essa non viene compilata nella configurazione predefinita, a meno che
DEBUG o CONFIG_DYNAMIC_DEBUG non vengono impostati. Questo vale anche per
dev_dbg() e in aggiunta VERBOSE_DEBUG per aggiungere i messaggi dev_vdbg().
Molti sottosistemi hanno delle opzioni di debug in Kconfig che aggiungono
-DDEBUG nei corrispettivi Makefile, e in altri casi aggiungono #define DEBUG
in specifici file. Infine, quando un messaggio di debug dev'essere stampato
incondizionatamente, per esempio perché siete già in una sezione di debug
racchiusa in #ifdef, potete usare printk(KERN_DEBUG ...).
14) Assegnare memoria
---------------------
Il kernel fornisce i seguenti assegnatori ad uso generico:
kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc(), e vzalloc().
Per maggiori informazioni, consultate la documentazione dell'API.
Il modo preferito per passare la dimensione di una struttura è il seguente:
.. code-block:: c
p = kmalloc(sizeof(*p), ...);
La forma alternativa, dove il nome della struttura viene scritto interamente,
peggiora la leggibilità e introduce possibili bachi quando il tipo di
puntatore cambia tipo ma il corrispondente sizeof non viene aggiornato.
Il valore di ritorno è un puntatore void, effettuare un cast su di esso è
ridondante. La conversione fra un puntatore void e un qualsiasi altro tipo
di puntatore è garantito dal linguaggio di programmazione C.
Il modo preferito per assegnare un vettore è il seguente:
.. code-block:: c
p = kmalloc_array(n, sizeof(...), ...);
Il modo preferito per assegnare un vettore a zero è il seguente:
.. code-block:: c
p = kcalloc(n, sizeof(...), ...);
Entrambe verificano la condizione di overflow per la dimensione
d'assegnamento n * sizeof(...), se accade ritorneranno NULL.
15) Il morbo inline
-------------------
Sembra che ci sia la percezione errata che gcc abbia una qualche magica
opzione "rendimi più veloce" chiamata ``inline``. In alcuni casi l'uso di
inline è appropriato (per esempio in sostituzione delle macro, vedi
capitolo 12), ma molto spesso non lo è. L'uso abbondante della parola chiave
inline porta ad avere un kernel più grande, che si traduce in un sistema nel
suo complesso più lento per via di una cache per le istruzioni della CPU più
grande e poi semplicemente perché ci sarà meno spazio disponibile per una
pagina di cache. Pensateci un attimo; una fallimento nella cache causa una
ricerca su disco che può tranquillamente richiedere 5 millisecondi. Ci sono
TANTI cicli di CPU che potrebbero essere usati in questi 5 millisecondi.
Spesso le persone dicono che aggiungere inline a delle funzioni dichiarate
static e utilizzare una sola volta è sempre una scelta vincente perché non
ci sono altri compromessi. Questo è tecnicamente vero ma gcc è in grado di
trasformare automaticamente queste funzioni in inline; i problemi di
manutenzione del codice per rimuovere gli inline quando compare un secondo
utente surclassano il potenziale vantaggio nel suggerire a gcc di fare una
cosa che avrebbe fatto comunque.
16) Nomi e valori di ritorno delle funzioni
-------------------------------------------
Le funzioni possono ritornare diversi tipi di valori, e uno dei più comuni
è quel valore che indica se una funzione ha completato con successo o meno.
Questo valore può essere rappresentato come un codice di errore intero
(-Exxx = fallimento, 0 = successo) oppure un booleano di successo
(0 = fallimento, non-zero = successo).
Mischiare questi due tipi di rappresentazioni è un terreno fertile per
i bachi più insidiosi. Se il linguaggio C includesse una forte distinzione
fra gli interi e i booleani, allora il compilatore potrebbe trovare questi
errori per conto nostro ... ma questo non c'è. Per evitare di imbattersi
in questo tipo di baco, seguite sempre la seguente convenzione::
Se il nome di una funzione è un'azione o un comando imperativo,
essa dovrebbe ritornare un codice di errore intero. Se il nome
è un predicato, la funzione dovrebbe ritornare un booleano di
"successo"
Per esempio, ``add work`` è un comando, e la funzione add_work() ritorna 0
in caso di successo o -EBUSY in caso di fallimento. Allo stesso modo,
``PCI device present`` è un predicato, e la funzione pci_dev_present() ritorna
1 se trova il dispositivo corrispondente con successo, altrimenti 0.
Tutte le funzioni esportate (EXPORT) devono rispettare questa convenzione, e
così dovrebbero anche tutte le funzioni pubbliche. Le funzioni private
(static) possono non seguire questa convenzione, ma è comunque raccomandato
che lo facciano.
Le funzioni il cui valore di ritorno è il risultato di una computazione,
piuttosto che l'indicazione sul successo di tale computazione, non sono
soggette a questa regola. Solitamente si indicano gli errori ritornando un
qualche valore fuori dai limiti. Un tipico esempio è quello delle funzioni
che ritornano un puntatore; queste utilizzano NULL o ERR_PTR come meccanismo
di notifica degli errori.
17) Non reinventate le macro del kernel
---------------------------------------
Il file di intestazione include/linux/kernel.h contiene un certo numero
di macro che dovreste usare piuttosto che implementarne una qualche variante.
Per esempio, se dovete calcolare la lunghezza di un vettore, sfruttate la
macro:
.. code-block:: c
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
Analogamente, se dovete calcolare la dimensione di un qualche campo di una
struttura, usate
.. code-block:: c
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
Ci sono anche le macro min() e max() che, se vi serve, effettuano un controllo
rigido sui tipi. Sentitevi liberi di leggere attentamente questo file
d'intestazione per scoprire cos'altro è stato definito che non dovreste
reinventare nel vostro codice.
18) Linee di configurazione degli editor e altre schifezze
-----------------------------------------------------------
Alcuni editor possono interpretare dei parametri di configurazione integrati
nei file sorgenti e indicati con dai marcatori speciali. Per esempio, emacs
interpreta le linee marcate nel seguente modo:
.. code-block:: c
-*- mode: c -*-
O come queste:
.. code-block:: c
/*
Local Variables:
compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
End:
*/
Vim interpreta i marcatori come questi:
.. code-block:: c
/* vim:set sw=8 noet */
Non includete nessuna di queste cose nei file sorgenti. Le persone hanno le
proprie configurazioni personali per l'editor, e i vostri sorgenti non
dovrebbero sovrascrivergliele. Questo vale anche per i marcatori
d'indentazione e di modalità d'uso. Le persone potrebbero aver configurato una
modalità su misura, oppure potrebbero avere qualche altra magia per far
funzionare bene l'indentazione.
19) Inline assembly
---------------------
Nel codice specifico per un'architettura, potreste aver bisogno di codice
*inline assembly* per interfacciarvi col processore o con una funzionalità
specifica della piattaforma. Non esitate a farlo quando è necessario.
Comunque, non usatele gratuitamente quando il C può fare la stessa cosa.
Potete e dovreste punzecchiare l'hardware in C quando è possibile.
Considerate la scrittura di una semplice funzione che racchiude pezzi comuni
di codice assembler piuttosto che continuare a riscrivere delle piccole
varianti. Ricordatevi che l' *inline assembly* può utilizzare i parametri C.
Il codice assembler più corposo e non banale dovrebbe andare nei file .S,
coi rispettivi prototipi C definiti nei file d'intestazione. I prototipi C
per le funzioni assembler dovrebbero usare ``asmlinkage``.
Potreste aver bisogno di marcare il vostro codice asm come volatile al fine
d'evitare che GCC lo rimuova quando pensa che non ci siano effetti collaterali.
Non c'è sempre bisogno di farlo, e farlo quando non serve limita le
ottimizzazioni.
Quando scrivete una singola espressione *inline assembly* contenente più
istruzioni, mettete ognuna di queste istruzioni in una stringa e riga diversa;
ad eccezione dell'ultima stringa/istruzione, ognuna deve terminare con ``\n\t``
al fine di allineare correttamente l'assembler che verrà generato:
.. code-block:: c
asm ("magic %reg1, #42\n\t"
"more_magic %reg2, %reg3"
: /* outputs */ : /* inputs */ : /* clobbers */);
20) Compilazione sotto condizione
---------------------------------
Ovunque sia possibile, non usate le direttive condizionali del preprocessore
(#if, #ifdef) nei file .c; farlo rende il codice difficile da leggere e da
seguire. Invece, usate queste direttive nei file d'intestazione per definire
le funzioni usate nei file .c, fornendo i relativi stub nel caso #else,
e quindi chiamate queste funzioni senza condizioni di preprocessore. Il
compilatore non produrrà alcun codice per le funzioni stub, produrrà gli
stessi risultati, e la logica rimarrà semplice da seguire.
È preferibile non compilare intere funzioni piuttosto che porzioni d'esse o
porzioni d'espressioni. Piuttosto che mettere una ifdef in un'espressione,
fattorizzate parte dell'espressione, o interamente, in funzioni e applicate
la direttiva condizionale su di esse.
Se avete una variabile o funzione che potrebbe non essere usata in alcune
configurazioni, e quindi il compilatore potrebbe avvisarvi circa la definizione
inutilizzata, marcate questa definizione come __maybe_used piuttosto che
racchiuderla in una direttiva condizionale del preprocessore. (Comunque,
se una variabile o funzione è *sempre* inutilizzata, rimuovetela).
Nel codice, dov'è possibile, usate la macro IS_ENABLED per convertire i
simboli Kconfig in espressioni booleane C, e quindi usatela nelle classiche
condizioni C:
.. code-block:: c
if (IS_ENABLED(CONFIG_SOMETHING)) {
...
}
Il compilatore valuterà la condizione come costante (constant-fold), e quindi
includerà o escluderà il blocco di codice come se fosse in un #ifdef, quindi
non ne aumenterà il tempo di esecuzione. Tuttavia, questo permette al
compilatore C di vedere il codice nel blocco condizionale e verificarne la
correttezza (sintassi, tipi, riferimenti ai simboli, eccetera). Quindi
dovete comunque utilizzare #ifdef se il codice nel blocco condizionale esiste
solo quando la condizione è soddisfatta.
Alla fine di un blocco corposo di #if o #ifdef (più di alcune linee),
mettete un commento sulla stessa riga di #endif, annotando la condizione
che termina. Per esempio:
.. code-block:: c
#ifdef CONFIG_SOMETHING
...
#endif /* CONFIG_SOMETHING */
Appendice I) riferimenti
------------------------
The C Programming Language, Second Edition
by Brian W. Kernighan and Dennis M. Ritchie.
Prentice Hall, Inc., 1988.
ISBN 0-13-110362-8 (paperback), 0-13-110370-9 (hardback).
The Practice of Programming
by Brian W. Kernighan and Rob Pike.
Addison-Wesley, Inc., 1999.
ISBN 0-201-61586-X.
Manuali GNU - nei casi in cui sono compatibili con K&R e questo documento -
per indent, cpp, gcc e i suoi dettagli interni, tutto disponibile qui
http://www.gnu.org/manual/
WG14 è il gruppo internazionale di standardizzazione per il linguaggio C,
URL: http://www.open-std.org/JTC1/SC22/WG14/
Kernel process/coding-style.rst, by greg@kroah.com at OLS 2002:
http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/development-process.rst <development_process_main>`
:Translator: Alessia Mantegazza <amantegazza@vaga.pv.it>
.. _it_development_process_main:
Una guida al processo di sviluppo del Kernel
============================================
Contenuti:
.. toctree::
:numbered:
:maxdepth: 2
1.Intro
2.Process
3.Early-stage
4.Coding
5.Posting
6.Followthrough
7.AdvancedTopics
8.Conclusion
Lo scopo di questo documento è quello di aiutare gli sviluppatori (ed i loro
supervisori) a lavorare con la communità di sviluppo con il minimo sforzo. È
un tentativo di documentare il funzionamento di questa communità in modo che
sia accessibile anche a coloro che non hanno famigliarità con lo sviluppo del
Kernel Linux (o, anzi, con lo sviluppo di software libero in generale). Benchè
qui sia presente del materiale tecnico, questa è una discussione rivolta in
particolare al procedimento, e quindi per essere compreso non richiede una
conoscenza approfondità sullo sviluppo del kernel.
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/email-clients.rst <email_clients>`
.. _it_email_clients:
Informazioni sui programmi di posta elettronica per Linux
=========================================================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/howto.rst <process_howto>`
:Translator: Alessia Mantegazza <amantegazza@vaga.pv.it>
.. _it_process_howto:
Come partecipare allo sviluppo del kernel Linux
===============================================
Questo è il documento fulcro di quanto trattato sull'argomento.
Esso contiene le istruzioni su come diventare uno sviluppatore
del kernel Linux e spiega come lavorare con la comunità di
sviluppo kernel Linux. Il documento non tratterà alcun aspetto
tecnico relativo alla programmazione del kernel, ma vi aiuterà
indirizzandovi sulla corretta strada.
Se qualsiasi cosa presente in questo documento diventasse obsoleta,
vi preghiamo di inviare le correzioni agli amministratori di questo
file, indicati in fondo al presente documento.
Introduzione
------------
Dunque, volete imparare come diventare sviluppatori del kernel Linux?
O vi è stato detto dal vostro capo, "Vai, scrivi un driver Linux per
questo dispositivo". Bene, l'obbiettivo di questo documento è quello
di insegnarvi tutto ciò che dovete sapere per raggiungere il vostro
scopo descrivendo il procedimento da seguire e consigliandovi
su come lavorare con la comunità. Il documento cercherà, inoltre,
di spiegare alcune delle ragioni per le quali la comunità lavora in un
modo suo particolare.
Il kernel è scritto prevalentemente nel linguaggio C con alcune parti
specifiche dell'architettura scritte in linguaggio assembly.
Per lo sviluppo kernel è richiesta una buona conoscenza del linguaggio C.
L'assembly (di qualsiasi architettura) non è richiesto, a meno che non
pensiate di fare dello sviluppo di basso livello per un'architettura.
Sebbene essi non siano un buon sostituto ad un solido studio del
linguaggio C o ad anni di esperienza, i seguenti libri sono, se non
altro, utili riferimenti:
- "The C Programming Language" di Kernighan e Ritchie [Prentice Hall]
- "Practical C Programming" di Steve Oualline [O'Reilly]
- "C: A Reference Manual" di Harbison and Steele [Prentice Hall]
Il kernel è stato scritto usando GNU C e la toolchain GNU.
Sebbene si attenga allo standard ISO C89, esso utilizza una serie di
estensioni che non sono previste in questo standard. Il kernel è un
ambiente C indipendente, che non ha alcuna dipendenza dalle librerie
C standard, così alcune parti del C standard non sono supportate.
Le divisioni ``long long`` e numeri in virgola mobile non sono permessi.
Qualche volta è difficile comprendere gli assunti che il kernel ha
riguardo gli strumenti e le estensioni in uso, e sfortunatamente non
esiste alcuna indicazione definitiva. Per maggiori informazioni, controllate,
la pagina `info gcc`.
Tenete a mente che state cercando di apprendere come lavorare con la comunità
di sviluppo già esistente. Questo è un gruppo eterogeneo di persone, con alti
standard di codifica, di stile e di procedura. Questi standard sono stati
creati nel corso del tempo basandosi su quanto hanno riscontrato funzionare al
meglio per un squadra così grande e geograficamente sparsa. Cercate di
imparare, in anticipo, il più possibile circa questi standard, poichè ben
spiegati; non aspettatevi che gli altri si adattino al vostro modo di fare
o a quello della vostra azienda.
Note legali
------------
Il codice sorgente del kernel Linux è rilasciato sotto GPL. Siete pregati
di visionare il file, COPYING, presente nella cartella principale dei
sorgente, per eventuali dettagli sulla licenza. Se avete ulteriori domande
sulla licenza, contattate un avvocato, non chiedete sulle liste di discussione
del kernel Linux. Le persone presenti in queste liste non sono avvocati,
e non dovreste basarvi sulle loro dichiarazioni in materia giuridica.
Per domande più frequenti e risposte sulla licenza GPL, guardare:
https://www.gnu.org/licenses/gpl-faq.html
Documentazione
--------------
I sorgenti del kernel Linux hanno una vasta base di documenti che vi
insegneranno come interagire con la comunità del kernel. Quando nuove
funzionalità vengono aggiunte al kernel, si raccomanda di aggiungere anche i
relativi file di documentatione che spiegano come usarele.
Quando un cambiamento del kernel genera anche un cambiamento nell'interfaccia
con lo spazio utente, è raccomandabile che inviate una notifica o una
correzione alle pagine *man* spiegando tale modifica agli amministratori di
queste pagine all'indirizzo mtk.manpages@gmail.com, aggiungendo
in CC la lista linux-api@vger.kernel.org.
Di seguito una lista di file che sono presenti nei sorgente del kernel e che
è richiesto che voi leggiate:
:ref:`Documentation/translations/it_IT/admin-guide/README.rst <it_readme>`
Questo file da una piccola anteprima del kernel Linux e descrive il
minimo necessario per configurare e generare il kernel. I novizi
del kernel dovrebbero iniziare da qui.
:ref:`Documentation/translations/it_IT/process/changes.rst <it_changes>`
Questo file fornisce una lista dei pacchetti software necessari
a compilare e far funzionare il kernel con successo.
:ref:`Documentation/translations/it_IT/process/coding-style.rst <it_codingstyle>`
Questo file descrive lo stile della codifica per il kernel Linux,
e parte delle motivazioni che ne sono alla base. Tutto il nuovo codice deve
seguire le linee guida in questo documento. Molti amministratori
accetteranno patch solo se queste osserveranno tali regole, e molte
persone revisioneranno il codice solo se scritto nello stile appropriato.
:ref:`Documentation/translations/it_IT/process/submitting-patches.rst <it_submittingpatches>` e
:ref:`Documentation/translations/it_IT/process/submitting-drivers.rst <it_submittingdrivers>`
Questo file descrive dettagliatamente come creare ed inviare una patch
con successo, includendo (ma non solo questo):
- Contenuto delle email
- Formato delle email
- I destinatari delle email
Seguire tali regole non garantirà il successo (tutte le patch sono soggette
a controlli realitivi a contenuto e stile), ma non seguirle lo precluderà
sempre.
Altre ottime descrizioni di come creare buone patch sono:
"The Perfect Patch"
https://www.ozlabs.org/~akpm/stuff/tpp.txt
"Linux kernel patch submission format"
http://linux.yyz.us/patch-format.html
:ref:`Documentation/process/translations/it_IT/stable-api-nonsense.rst <it_stable_api_nonsense>`
Questo file descrive la motivazioni sottostanti la conscia decisione di
non avere un API stabile all'interno del kernel, incluso cose come:
- Sottosistemi shim-layers (per compatibilità?)
- Portabilità fra Sistemi Operativi dei driver.
- Attenuare i rapidi cambiamenti all'interno dei sorgenti del kernel
(o prevenirli)
Questo documento è vitale per la comprensione della filosifia alla base
dello sviluppo di Linux ed è molto importante per le persone che arrivano
da esperienze con altri Sistemi Operativi.
:ref:`Documentation/translations/it_IT/admin-guide/security-bugs.rst <it_securitybugs>`
Se ritenete di aver trovato un problema di sicurezza nel kernel Linux,
seguite i passaggi scritti in questo documento per notificarlo agli
sviluppatori del kernel, ed aiutare la risoluzione del problema.
:ref:`Documentation/translations/it_IT/process/management-style.rst <it_managementstyle>`
Questo documento descrive come i manutentori del kernel Linux operano
e la filosofia comune alla base del loro metodo. Questa è un'importante
lettura per tutti coloro che sono nuovi allo sviluppo del kernel (o per
chi è semplicemente curioso), poiché risolve molti dei più comuni
fraintendimenti e confusioni dovuti al particolare comportamento dei
manutentori del kernel.
:ref:`Documentation/translations/it_IT/process/stable-kernel-rules.rst <it_stable_kernel_rules>`
Questo file descrive le regole sulle quali vengono basati i rilasci del
kernel, e spiega cosa fare se si vuole che una modifica venga inserita
in uno di questi rilasci.
:ref:`Documentation/translations/it_IT/process/kernel-docs.rst <it_kernel_docs>`
Una lista di documenti pertinenti allo sviluppo del kernel.
Per favore consultate questa lista se non trovate ciò che cercate nella
documentazione interna del kernel.
:ref:`Documentation/translations/it_IT/process/applying-patches.rst <it_applying_patches>`
Una buona introduzione che descrivere esattamente cos'è una patch e come
applicarla ai differenti rami di sviluppo del kernel.
Il kernel inoltre ha un vasto numero di documenti che possono essere
automaticamente generati dal codice sorgente stesso o da file
ReStructuredText (ReST), come questo. Esso include una completa
descrizione dell'API interna del kernel, e le regole su come gestire la
sincronizzazione (locking) correttamente
Tutte queste tipologie di documenti possono essere generati in PDF o in
HTML utilizzando::
make pdfdocs
make htmldocs
rispettivamente dalla cartella principale dei sorgenti del kernel.
I documenti che impiegano ReST saranno generati nella cartella
Documentation/output.
Questi posso essere generati anche in formato LaTex e ePub con::
make latexdocs
make epubdocs
Diventare uno sviluppatore del kernel
-------------------------------------
Se non sapete nulla sullo sviluppo del kernel Linux, dovreste dare uno
sguardo al progetto *Linux KernelNewbies*:
https://kernelnewbies.org
Esso prevede un'utile lista di discussione dove potete porre più o meno ogni
tipo di quesito relativo ai concetti fondamentali sullo sviluppo del kernel
(assicuratevi di cercare negli archivi, prima di chiedere qualcosa alla
quale è già stata fornita risposta in passato). Esistono inoltre, un canale IRC
che potete usare per formulare domande in tempo reale, e molti documenti utili
che vi faciliteranno nell'apprendimento dello sviluppo del kernel Linux.
Il sito internet contiene informazioni di base circa l'organizzazione del
codice, sottosistemi e progetti attuali (sia interni che esterni a Linux).
Esso descrive, inoltre, informazioni logistiche di base, riguardanti ad esempio
la compilazione del kernel e l'applicazione di una modifica.
Se non sapete dove cominciare, ma volete cercare delle attività dalle quali
partire per partecipare alla comunità di sviluppo, andate al progetto Linux
Kernel Janitor's.
https://kernelnewbies.org/KernelJanitors
È un buon posto da cui iniziare. Esso presenta una lista di problematiche
relativamente semplici da sistemare e pulire all'interno della sorgente del
kernel Linux. Lavorando con gli sviluppatori incaricati di questo progetto,
imparerete le basi per l'inserimento delle vostre modifiche all'interno dei
sorgenti del kernel Linux, e possibilmente, sarete indirizzati al lavoro
successivo da svolgere, se non ne avrete ancora idea.
Prima di apportare una qualsiasi modifica al codice del kernel Linux,
è imperativo comprendere come tale codice funziona. A questo scopo, non c'è
nulla di meglio che leggerlo direttamente (la maggior parte dei bit più
complessi sono ben commentati), eventualmente anche con l'aiuto di strumenti
specializzati. Uno degli strumenti che è particolarmente raccomandato è
il progetto Linux Cross-Reference, che è in grado di presentare codice
sorgente in un formato autoreferenziale ed indicizzato. Un eccellente ed
aggiornata fonte di consultazione del codice del kernel la potete trovare qui:
http://lxr.free-electrons.com/
Il processo di sviluppo
-----------------------
Il processo di sviluppo del kernel Linux si compone di pochi "rami" principali
e di molti altri rami per specifici sottosistemi. Questi rami sono:
- I sorgenti kernel 4.x
- I sorgenti stabili del kernel 4.x.y -stable
- Le modifiche in 4.x -git
- Sorgenti dei sottosistemi del kernel e le loro modifiche
- Il kernel 4.x -next per test d'integrazione
I sorgenti kernel 4.x
~~~~~~~~~~~~~~~~~~~~~
I kernel 4.x sono amministrati da Linus Torvald, e possono essere trovati
su https://kernel.org nella cartella pub/linux/kernel/v4.x/. Il processo
di sviluppo è il seguente:
- Non appena un nuovo kernel viene rilasciato si apre una finestra di due
settimane. Durante questo periodo i manutentori possono proporre a Linus
dei grossi cambiamenti; solitamente i cambiamenti che sono già stati
inseriti nel ramo -next del kernel per alcune settimane. Il modo migliore
per sottoporre dei cambiamenti è attraverso git (lo strumento usato per
gestire i sorgenti del kernel, più informazioni sul sito
https://git-scm.com/) ma anche delle patch vanno bene.
- Al termine delle due settimane un kernel -rc1 viene rilasciato e
l'obbiettivo ora è quello di renderlo il più solido possibile. A questo
punto la maggior parte delle patch dovrebbero correggere un'eventuale
regressione. I bachi che sono sempre esistiti non sono considerabili come
regressioni, quindi inviate questo tipo di cambiamenti solo se sono
importanti. Notate che un intero driver (o filesystem) potrebbe essere
accettato dopo la -rc1 poiché non esistono rischi di una possibile
regressione con tale cambiamento, fintanto che quest'ultimo è
auto-contenuto e non influisce su aree esterne al codice che è stato
aggiunto. git può essere utilizzato per inviare le patch a Linus dopo che
la -rc1 è stata rilasciata, ma è anche necessario inviare le patch ad
una lista di discussione pubblica per un'ulteriore revisione.
- Una nuova -rc viene rilasciata ogni volta che Linus reputa che gli attuali
sorgenti siano in uno stato di salute ragionevolmente adeguato ai test.
L'obiettivo è quello di rilasciare una nuova -rc ogni settimana.
- Il processo continua fino a che il kernel è considerato "pronto"; tale
processo dovrebbe durare circa in 6 settimane.
È utile menzionare quanto scritto da Andrew Morton sulla lista di discussione
kernel-linux in merito ai rilasci del kernel:
*"Nessuno sa quando un kernel verrà rilasciato, poichè questo è
legato allo stato dei bachi e non ad una cronologia preventiva."*
I sorgenti stabili del kernel 4.x.y -stable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I kernel con versioni in 3-parti sono "kernel stabili". Essi contengono
correzioni critiche relativamente piccole nell'ambito della sicurezza
oppure significative regressioni scoperte in un dato 4.x kernel.
Questo è il ramo raccomandato per gli utenti che vogliono un kernel recente
e stabile e non sono interessati a dare il proprio contributo alla verifica
delle versioni di sviluppo o sperimentali.
Se non è disponibile alcun kernel 4.x.y., quello più aggiornato e stabile
sarà il kernel 4.x con la numerazione più alta.
4.x.y sono amministrati dal gruppo "stable" <stable@vger.kernel.org>, e sono
rilasciati a seconda delle esigenze. Il normale periodo di rilascio è
approssimativamente di due settimane, ma può essere più lungo se non si
verificano problematiche urgenti. Un problema relativo alla sicurezza, invece,
può determinare un rilascio immediato.
Il file Documentation/process/stable-kernel-rules.rst (nei sorgenti) documenta
quali tipologie di modifiche sono accettate per i sorgenti -stable, e come
avviene il processo di rilascio.
Le modifiche in 4.x -git
~~~~~~~~~~~~~~~~~~~~~~~~
Queste sono istantanee quotidiane del kernel di Linus e sono gestite in
una repositorio git (da qui il nome). Queste modifiche sono solitamente
rilasciate giornalmente e rappresentano l'attuale stato dei sorgenti di
Linus. Queste sono da considerarsi più sperimentali di un -rc in quanto
generate automaticamente senza nemmeno aver dato una rapida occhiata
per verificarne lo stato.
Sorgenti dei sottosistemi del kernel e le loro patch
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I manutentori dei diversi sottosistemi del kernel --- ed anche molti
sviluppatori di sottosistemi --- mostrano il loro attuale stato di sviluppo
nei loro repositori. In questo modo, altri possono vedere cosa succede nelle
diverse parti del kernel. In aree dove lo sviluppo è rapido, potrebbe essere
chiesto ad uno sviluppatore di basare le proprie modifiche su questi repositori
in modo da evitare i conflitti fra le sottomissioni ed altri lavori in corso
La maggior parte di questi repositori sono git, ma esistono anche altri SCM
in uso, o file di patch pubblicate come una serie quilt.
Gli indirizzi dei repositori di sottosistema sono indicati nel file
MAINTAINERS. Molti di questi posso essere trovati su https://git.kernel.org/.
Prima che una modifica venga inclusa in questi sottosistemi, sarà soggetta ad
una revisione che inizialmente avviene tramite liste di discussione (vedere la
sezione dedicata qui sotto). Per molti sottosistemi del kernel, tale processo
di revisione è monitorato con lo strumento patchwork.
Patchwork offre un'interfaccia web che mostra le patch pubblicate, inclusi i
commenti o le revisioni fatte, e gli amministratori possono indicare le patch
come "in revisione", "accettate", o "rifiutate". Diversi siti Patchwork sono
elencati al sito https://patchwork.kernel.org/.
Il kernel 4.x -next per test d'integrazione
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Prima che gli aggiornamenti dei sottosistemi siano accorpati nel ramo
principale 4.x, sarà necessario un test d'integrazione.
A tale scopo, esiste un repositorio speciale di test nel quale virtualmente
tutti i rami dei sottosistemi vengono inclusi su base quotidiana:
https://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
In questo modo, i kernel -next offrono uno sguardo riassuntivo su quello che
ci si aspetterà essere nel kernel principale nel successivo periodo
d'incorporazione.
Coloro che vorranno fare dei test d'esecuzione del kernel -next sono più che
benvenuti.
Riportare Bug
-------------
https://bugzilla.kernel.org è dove gli sviluppatori del kernel Linux tracciano
i bachi del kernel. Gli utenti sono incoraggiati nel riportare tutti i bachi
che trovano utilizzando questo strumento.
Per maggiori dettagli su come usare il bugzilla del kernel, guardare:
https://bugzilla.kernel.org/page.cgi?id=faq.html
Il file admin-guide/reporting-bugs.rst nella cartella principale del kernel
fornisce un buon modello sul come segnalare un baco nel kernel, e spiega quali
informazioni sono necessarie agli sviluppatori per poter aiutare il
rintracciamento del problema.
Gestire i rapporti sui bug
--------------------------
Uno dei modi migliori per mettere in pratica le vostre capacità di hacking è
quello di riparare bachi riportati da altre persone. Non solo aiuterete a far
diventare il kernel più stabile, ma imparerete a riparare problemi veri dal
mondo ed accrescerete le vostre competenze, e gli altri sviluppatori saranno
al corrente della vostra presenza. Riparare bachi è una delle migliori vie per
acquisire meriti tra gli altri sviluppatori, perchè non a molte persone piace
perdere tempo a sistemare i bachi di altri.
Per lavorare sui rapporti di bachi già riportati, andate su
https://bugzilla.kernel.org.
Liste di discussione
--------------------
Come descritto in molti dei documenti qui sopra, la maggior parte degli
sviluppatori del kernel partecipano alla lista di discussione Linux Kernel.
I dettagli su come iscriversi e disiscriversi dalla lista possono essere
trovati al sito:
http://vger.kernel.org/vger-lists.html#linux-kernel
Ci sono diversi archivi della lista di discussione. Usate un qualsiasi motore
di ricerca per trovarli. Per esempio:
http://dir.gmane.org/gmane.linux.kernel
É caldamente consigliata una ricerca in questi archivi sul tema che volete
sollevare, prima di pubblicarlo sulla lista. Molte cose sono già state
discusse in dettaglio e registrate negli archivi della lista di discussione.
Molti dei sottosistemi del kernel hanno anche una loro lista di discussione
dedicata. Guardate nel file MAINTAINERS per avere una lista delle liste di
discussione e il loro uso.
Molte di queste liste sono gestite su kernel.org. Per informazioni consultate
la seguente pagina:
http://vger.kernel.org/vger-lists.html
Per favore ricordatevi della buona educazione quando utilizzate queste liste.
Sebbene sia un pò dozzinale, il seguente URL contiene alcune semplici linee
guida per interagire con la lista (o con qualsiasi altra lista):
http://www.albion.com/netiquette/
Se diverse persone rispondo alla vostra mail, la lista dei riceventi (copia
conoscenza) potrebbe diventare abbastanza lunga. Non cancellate nessuno dalla
lista di CC: senza un buon motivo, e non rispondete solo all'indirizzo
della lista di discussione. Fateci l'abitudine perché capita spesso di
ricevere la stessa email due volte: una dal mittente ed una dalla lista; e non
cercate di modificarla aggiungendo intestazioni stravaganti, agli altri non
piacerà.
Ricordate di rimanere sempre in argomento e di mantenere le attribuzioni
delle vostre risposte invariate; mantenete il "John Kernelhacker wrote ...:"
in cima alla vostra replica e aggiungete le vostre risposte fra i singoli
blocchi citati, non scrivete all'inizio dell'email.
Se aggiungete patch alla vostra mail, assicuratevi che siano del tutto
leggibili come indicato in Documentation/process/submitting-patches.rst.
Gli sviluppatori kernel non vogliono avere a che fare con allegati o patch
compresse; vogliono invece poter commentare le righe dei vostri cambiamenti,
il che può funzionare solo in questo modo.
Assicuratevi di utilizzare un gestore di mail che non alterì gli spazi ed i
caratteri. Un ottimo primo test è quello di inviare a voi stessi una mail e
cercare di sottoporre la vostra stessa patch. Se non funziona, sistemate il
vostro programma di posta, o cambiatelo, finché non funziona.
Ed infine, per favore ricordatevi di mostrare rispetto per gli altri
sottoscriventi.
Lavorare con la comunità
------------------------
L'obiettivo di questa comunità è quello di fornire il miglior kernel possibile.
Quando inviate una modifica che volete integrare, sarà valutata esclusivamente
dal punto di vista tecnico. Quindi, cosa dovreste aspettarvi?
- critiche
- commenti
- richieste di cambiamento
- richieste di spiegazioni
- nulla
Ricordatevi che questo fa parte dell'integrazione della vostra modifica
all'interno del kernel. Dovete essere in grado di accettare le critiche,
valutarle a livello tecnico ed eventualmente rielaborare nuovamente le vostre
modifiche o fornire delle chiare e concise motivazioni per le quali le
modifiche suggerite non dovrebbero essere fatte.
Se non riceverete risposte, aspettate qualche giorno e riprovate ancora,
qualche volta le cose si perdono nell'enorme mucchio di email.
Cosa non dovreste fare?
- aspettarvi che la vostra modifica venga accettata senza problemi
- mettervi sulla difensiva
- ignorare i commenti
- sottomettere nuovamente la modifica senza fare nessuno dei cambiamenti
richiesti
In una comunità che è alla ricerca delle migliori soluzioni tecniche possibili,
ci saranno sempre opinioni differenti sull'utilità di una modifica.
Siate cooperativi e vogliate adattare la vostra idea in modo che sia inserita
nel kernel. O almeno vogliate dimostrare che la vostra idea vale.
Ricordatevi, sbagliare è accettato fintanto che siate disposti a lavorare verso
una soluzione che è corretta.
È normale che le risposte alla vostra prima modifica possa essere
semplicemente una lista con dozzine di cose che dovreste correggere.
Questo **non** implica che la vostra patch non sarà accettata, e questo
**non** è contro di voi personalmente.
Semplicemente correggete tutte le questioni sollevate contro la vostra modifica
ed inviatela nuovamente.
Differenze tra la comunità del kernel e le strutture aziendali
--------------------------------------------------------------
La comunità del kernel funziona diversamente rispetto a molti ambienti di
sviluppo aziendali. Qui di seguito una lista di cose che potete provare a
fare per evitare problemi:
Cose da dire riguardanti le modifiche da voi proposte:
- "Questo risolve più problematiche."
- "Questo elimina 2000 stringhe di codice."
- "Qui una modifica che spiega cosa sto cercando di fare."
- "L'ho testato su 5 diverse architetture.."
- "Qui una serie di piccole modifiche che.."
- "Questo aumenta le prestazioni di macchine standard..."
Cose che dovreste evitare di dire:
- "Lo abbiamo fatto in questo modo in AIX/ptx/Solaris, di conseguenza
deve per forza essere giusto..."
- "Ho fatto questo per 20 anni, quindi.."
- "Questo è richiesto dalla mia Azienda per far soldi"
- "Questo è per la linea di prodotti della nostra Azienda"
- "Ecco il mio documento di design di 1000 pagine che descrive ciò che ho
in mente"
- "Ci ho lavorato per 6 mesi..."
- "Ecco una patch da 5000 righe che.."
- "Ho riscritto il pasticcio attuale, ed ecco qua.."
- "Ho una scadenza, e questa modifica ha bisogno di essere approvata ora"
Un'altra cosa nella quale la comunità del kernel si differenzia dai più
classici ambienti di ingegneria del software è la natura "senza volto" delle
interazioni umane. Uno dei benefici dell'uso delle email e di irc come forma
primordiale di comunicazione è l'assenza di discriminazione basata su genere e
razza. L'ambienti di lavoro Linux accetta donne e minoranze perchè tutto quello
che sei è un indirizzo email. Aiuta anche l'aspetto internazionale nel
livellare il terreno di gioco perchè non è possibile indovinare il genere
basandosi sul nome di una persona. Un uomo può chiamarsi Andrea ed una donna
potrebbe chiamarsi Pat. Gran parte delle donne che hanno lavorato al kernel
Linux e che hanno espresso una personale opinione hanno avuto esperienze
positive.
La lingua potrebbe essere un ostacolo per quelle persone che non si trovano
a loro agio con l'inglese. Una buona padronanza del linguaggio può essere
necessaria per esporre le proprie idee in maniera appropiata all'interno
delle liste di discussione, quindi è consigliabile che rileggiate le vostre
email prima di inviarle in modo da essere certi che abbiano senso in inglese.
Spezzare le vostre modifiche
----------------------------
La comunità del kernel Linux non accetta con piacere grossi pezzi di codice
buttati lì tutti in una volta. Le modifiche necessitano di essere
adeguatamente presentate, discusse, e suddivise in parti più piccole ed
indipendenti. Questo è praticamente l'esatto opposto di quello che le
aziende fanno solitamente. La vostra proposta dovrebbe, inoltre, essere
presentata prestissimo nel processo di sviluppo, così che possiate ricevere
un riscontro su quello che state facendo. Lasciate che la comunità
senta che state lavorando con loro, e che non li stiate sfruttando come
discarica per le vostre aggiunte. In ogni caso, non inviate 50 email nello
stesso momento in una lista di discussione, il più delle volte la vostra serie
di modifiche dovrebbe essere più piccola.
I motivi per i quali dovreste frammentare le cose sono i seguenti:
1) Piccole modifiche aumentano le probabilità che vengano accettate,
altrimenti richiederebbe troppo tempo o sforzo nel verificarne
la correttezza. Una modifica di 5 righe può essere accettata da un
manutentore con a mala pena una seconda occhiata. Invece, una modifica da
500 linee può richiedere ore di rilettura per verificarne la correttezza
(il tempo necessario è esponenzialmente proporzionale alla dimensione della
modifica, o giù di lì)
Piccole modifiche sono inoltre molto facili da debuggare quando qualcosa
non va. È molto più facile annullare le modifiche una per una che
dissezionare una patch molto grande dopo la sua sottomissione (e rompere
qualcosa).
2) È importante non solo inviare piccole modifiche, ma anche riscriverle e
semplificarle (o più semplicemente ordinarle) prima di sottoporle.
Qui un'analogia dello sviluppatore kernel Al Viro:
*"Pensate ad un insegnante di matematica che corregge il compito
di uno studente (di matematica). L'insegnante non vuole vedere le
prove e gli errori commessi dallo studente prima che arrivi alla
soluzione. Vuole vedere la risposta più pulita ed elegante
possibile. Un buono studente lo sa, e non presenterebbe mai le
proprie bozze prima prima della soluzione finale"*
*"Lo stesso vale per lo sviluppo del kernel. I manutentori ed i
revisori non vogliono vedere il procedimento che sta dietro al
problema che uno sta risolvendo. Vogliono vedere una soluzione
semplice ed elegante."*
Può essere una vera sfida il saper mantenere l'equilibrio fra una presentazione
elegante della vostra soluzione, lavorare insieme ad una comunità e dibattere
su un lavoro incompleto. Pertanto è bene entrare presto nel processo di
revisione per migliorare il vostro lavoro, ma anche per riuscire a tenere le
vostre modifiche in pezzettini che potrebbero essere già accettate, nonostante
la vostra intera attività non lo sia ancora.
In fine, rendetevi conto che non è accettabile inviare delle modifiche
incomplete con la promessa che saranno "sistemate dopo".
Giustificare le vostre modifiche
--------------------------------
Insieme alla frammentazione delle vostre modifiche, è altrettanto importante
permettere alla comunità Linux di capire perché dovrebbero accettarle.
Nuove funzionalità devono essere motivate come necessarie ed utili.
Documentare le vostre modifiche
-------------------------------
Quando inviate le vostre modifiche, fate particolare attenzione a quello che
scrivete nella vostra email. Questa diventerà il *ChangeLog* per la modifica,
e sarà visibile a tutti per sempre. Dovrebbe descrivere la modifica nella sua
interezza, contenendo:
- perchè la modifica è necessaria
- l'approccio d'insieme alla patch
- dettagli supplementari
- risultati dei test
Per maggiori dettagli su come tutto ciò dovrebbe apparire, riferitevi alla
sezione ChangeLog del documento:
"The Perfect Patch"
http://www.ozlabs.org/~akpm/stuff/tpp.txt
A volte tutto questo è difficile da realizzare. Il perfezionamento di queste
pratiche può richiedere anni (eventualmente). È un processo continuo di
miglioramento che richiede molta pazienza e determinazione. Ma non mollate,
si può fare. Molti lo hanno fatto prima, ed ognuno ha dovuto iniziare dove
siete voi ora.
----------
Grazie a Paolo Ciarrocchi che ha permesso che la sezione "Development Process"
(https://lwn.net/Articles/94386/) fosse basata sui testi da lui scritti, ed a
Randy Dunlap e Gerrit Huizenga per la lista di cose che dovreste e non
dovreste dire. Grazie anche a Pat Mochel, Hanna Linder, Randy Dunlap,
Kay Sievers, Vojtech Pavlik, Jan Kara, Josh Boyer, Kees Cook, Andrew Morton,
Andi Kleen, Vadim Lobanov, Jesper Juhl, Adrian Bunk, Keri Harris, Frans Pop,
David A. Wheeler, Junio Hamano, Michael Kerrisk, e Alex Shepard per le
loro revisioni, commenti e contributi. Senza il loro aiuto, questo documento
non sarebbe stato possibile.
Manutentore: Greg Kroah-Hartman <greg@kroah.com>
.. raw:: latex
\renewcommand\thesection*
\renewcommand\thesubsection*
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/index.rst <process_index>`
:Translator: Federico Vaga <federico.vaga@vaga.pv.it>
.. _it_process_index:
Lavorare con la comunità di sviluppo del kernel
===============================================
Quindi volete diventare sviluppatori del kernel? Benvenuti! C'è molto da
imparare sul lato tecnico del kernel, ma è anche importante capire come
funziona la nostra comunità. Leggere questi documenti renderà più facile
l'accettazione delle vostre modifiche con il minimo sforzo.
Di seguito le guide che ogni sviluppatore dovrebbe leggere.
.. toctree::
:maxdepth: 1
howto
code-of-conduct
development-process
submitting-patches
coding-style
maintainer-pgp-guide
email-clients
kernel-enforcement-statement
kernel-driver-statement
Poi ci sono altre guide sulla comunità che sono di interesse per molti
degli sviluppatori:
.. toctree::
:maxdepth: 1
changes
submitting-drivers
stable-api-nonsense
management-style
stable-kernel-rules
submit-checklist
kernel-docs
Ed infine, qui ci sono alcune guide più tecniche che son state messe qua solo
perché non si è trovato un posto migliore.
.. toctree::
:maxdepth: 1
applying-patches
adding-syscalls
magic-number
volatile-considered-harmful
clang-format
.. only:: subproject and html
Indices
=======
* :ref:`genindex`
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
.. _it_kernel_docs:
Indice di documenti per le persone interessate a capire e/o scrivere per il kernel Linux
========================================================================================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/kernel-driver-statement.rst <process_statement_driver>`
:Translator: Federico Vaga <federico.vaga@vaga.pv.it>
.. _it_process_statement_driver:
Dichiarazioni sui driver per il kernel
======================================
Presa di posizione sui moduli per il kernel Linux
-------------------------------------------------
Noi, i sottoscritti sviluppatori del kernel, consideriamo pericoloso
o indesiderato qualsiasi modulo o driver per il kernel Linux di tipo
*a sorgenti chiusi* (*closed-source*). Ripetutamente, li abbiamo
trovati deleteri per gli utenti Linux, le aziende, ed in generale
l'ecosistema Linux. Questi moduli impediscono l'apertura, la stabilità,
la flessibilità, e la manutenibilità del modello di sviluppo di Linux
e impediscono ai loro utenti di beneficiare dell'esperienza dalla
comunità Linux. I fornitori che distribuiscono codice a sorgenti chiusi
obbligano i propri utenti a rinunciare ai principali vantaggi di Linux
o a cercarsi nuovi fornitori.
Perciò, al fine di sfruttare i vantaggi che codice aperto ha da offrire,
come l'abbattimento dei costi e un supporto condiviso, spingiamo i
fornitori ad adottare una politica di supporto ai loro clienti Linux
che preveda il rilascio dei sorgenti per il kernel.
Parliamo solo per noi stessi, e non per una qualsiasi azienda per la
quale lavoriamo oggi, o abbiamo lavorato in passato, o lavoreremo in
futuro.
- Dave Airlie
- Nick Andrew
- Jens Axboe
- Ralf Baechle
- Felipe Balbi
- Ohad Ben-Cohen
- Muli Ben-Yehuda
- Jiri Benc
- Arnd Bergmann
- Thomas Bogendoerfer
- Vitaly Bordug
- James Bottomley
- Josh Boyer
- Neil Brown
- Mark Brown
- David Brownell
- Michael Buesch
- Franck Bui-Huu
- Adrian Bunk
- François Cami
- Ralph Campbell
- Luiz Fernando N. Capitulino
- Mauro Carvalho Chehab
- Denis Cheng
- Jonathan Corbet
- Glauber Costa
- Alan Cox
- Magnus Damm
- Ahmed S. Darwish
- Robert P. J. Day
- Hans de Goede
- Arnaldo Carvalho de Melo
- Helge Deller
- Jean Delvare
- Mathieu Desnoyers
- Sven-Thorsten Dietrich
- Alexey Dobriyan
- Daniel Drake
- Alex Dubov
- Randy Dunlap
- Michael Ellerman
- Pekka Enberg
- Jan Engelhardt
- Mark Fasheh
- J. Bruce Fields
- Larry Finger
- Jeremy Fitzhardinge
- Mike Frysinger
- Kumar Gala
- Robin Getz
- Liam Girdwood
- Jan-Benedict Glaw
- Thomas Gleixner
- Brice Goglin
- Cyrill Gorcunov
- Andy Gospodarek
- Thomas Graf
- Krzysztof Halasa
- Harvey Harrison
- Stephen Hemminger
- Michael Hennerich
- Tejun Heo
- Benjamin Herrenschmidt
- Kristian Høgsberg
- Henrique de Moraes Holschuh
- Marcel Holtmann
- Mike Isely
- Takashi Iwai
- Olof Johansson
- Dave Jones
- Jesper Juhl
- Matthias Kaehlcke
- Kenji Kaneshige
- Jan Kara
- Jeremy Kerr
- Russell King
- Olaf Kirch
- Roel Kluin
- Hans-Jürgen Koch
- Auke Kok
- Peter Korsgaard
- Jiri Kosina
- Aaro Koskinen
- Mariusz Kozlowski
- Greg Kroah-Hartman
- Michael Krufky
- Aneesh Kumar
- Clemens Ladisch
- Christoph Lameter
- Gunnar Larisch
- Anders Larsen
- Grant Likely
- John W. Linville
- Yinghai Lu
- Tony Luck
- Pavel Machek
- Matt Mackall
- Paul Mackerras
- Roland McGrath
- Patrick McHardy
- Kyle McMartin
- Paul Menage
- Thierry Merle
- Eric Miao
- Akinobu Mita
- Ingo Molnar
- James Morris
- Andrew Morton
- Paul Mundt
- Oleg Nesterov
- Luca Olivetti
- S.Çağlar Onur
- Pierre Ossman
- Keith Owens
- Venkatesh Pallipadi
- Nick Piggin
- Nicolas Pitre
- Evgeniy Polyakov
- Richard Purdie
- Mike Rapoport
- Sam Ravnborg
- Gerrit Renker
- Stefan Richter
- David Rientjes
- Luis R. Rodriguez
- Stefan Roese
- Francois Romieu
- Rami Rosen
- Stephen Rothwell
- Maciej W. Rozycki
- Mark Salyzyn
- Yoshinori Sato
- Deepak Saxena
- Holger Schurig
- Amit Shah
- Yoshihiro Shimoda
- Sergei Shtylyov
- Kay Sievers
- Sebastian Siewior
- Rik Snel
- Jes Sorensen
- Alexey Starikovskiy
- Alan Stern
- Timur Tabi
- Hirokazu Takata
- Eliezer Tamir
- Eugene Teo
- Doug Thompson
- FUJITA Tomonori
- Dmitry Torokhov
- Marcelo Tosatti
- Steven Toth
- Theodore Tso
- Matthias Urlichs
- Geert Uytterhoeven
- Arjan van de Ven
- Ivo van Doorn
- Rik van Riel
- Wim Van Sebroeck
- Hans Verkuil
- Horst H. von Brand
- Dmitri Vorobiev
- Anton Vorontsov
- Daniel Walker
- Johannes Weiner
- Harald Welte
- Matthew Wilcox
- Dan J. Williams
- Darrick J. Wong
- David Woodhouse
- Chris Wright
- Bryan Wu
- Rafael J. Wysocki
- Herbert Xu
- Vlad Yasevich
- Peter Zijlstra
- Bartlomiej Zolnierkiewicz
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/kernel-enforcement-statement.rst <process_statement_kernel>`
.. _it_process_statement_kernel:
Applicazione della licenza sul kernel Linux
===========================================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/magic-numbers.rst <magicnumbers>`
:Translator: Federico Vaga <federico.vaga@vaga.pv.it>
.. _it_magicnumbers:
I numeri magici di Linux
========================
Questo documento è un registro dei numeri magici in uso. Quando
aggiungete un numero magico ad una struttura, dovreste aggiungerlo anche
a questo documento; la cosa migliore è che tutti i numeri magici usati
dalle varie strutture siano unici.
È **davvero** un'ottima idea proteggere le strutture dati del kernel con
dei numeri magici. Questo vi permette in fase d'esecuzione di (a) verificare
se una struttura è stata malmenata, o (b) avete passato a una procedura la
struttura errata. Quest'ultimo è molto utile - particolarmente quando si passa
una struttura dati tramite un puntatore void \*. Il codice tty, per esempio,
effettua questa operazione con regolarità passando avanti e indietro le
strutture specifiche per driver e discipline.
Per utilizzare un numero magico, dovete dichiararlo all'inizio della struttura
dati, come di seguito::
struct tty_ldisc {
int magic;
...
};
Per favore, seguite questa direttiva quando aggiungerete migliorie al kernel!
Mi ha risparmiato un numero illimitato di ore di debug, specialmente nei casi
più ostici dove si è andati oltre la dimensione di un vettore e la struttura
dati che lo seguiva in memoria è stata sovrascritta. Seguendo questa
direttiva, questi casi vengono identificati velocemente e in sicurezza.
Registro dei cambiamenti::
Theodore Ts'o
31 Mar 94
La tabella magica è aggiornata a Linux 2.1.55.
Michael Chastain
<mailto:mec@shout.net>
22 Sep 1997
Ora dovrebbe essere aggiornata a Linux 2.1.112. Dato che
siamo in un momento di congelamento delle funzionalità
(*feature freeze*) è improbabile che qualcosa cambi prima
della versione 2.2.x. Le righe sono ordinate secondo il
campo numero.
Krzysztof G. Baranowski
<mailto: kgb@knm.org.pl>
29 Jul 1998
Aggiornamento della tabella a Linux 2.5.45. Giusti nel congelamento
delle funzionalità ma è comunque possibile che qualche nuovo
numero magico s'intrufoli prima del kernel 2.6.x.
Petr Baudis
<pasky@ucw.cz>
03 Nov 2002
Aggiornamento della tabella magica a Linux 2.5.74.
Fabian Frederick
<ffrederick@users.sourceforge.net>
09 Jul 2003
===================== ================ ======================== ==========================================
Nome magico Numero Struttura File
===================== ================ ======================== ==========================================
PG_MAGIC 'P' pg_{read,write}_hdr ``include/linux/pg.h``
CMAGIC 0x0111 user ``include/linux/a.out.h``
MKISS_DRIVER_MAGIC 0x04bf mkiss_channel ``drivers/net/mkiss.h``
HDLC_MAGIC 0x239e n_hdlc ``drivers/char/n_hdlc.c``
APM_BIOS_MAGIC 0x4101 apm_user ``arch/x86/kernel/apm_32.c``
CYCLADES_MAGIC 0x4359 cyclades_port ``include/linux/cyclades.h``
DB_MAGIC 0x4442 fc_info ``drivers/net/iph5526_novram.c``
DL_MAGIC 0x444d fc_info ``drivers/net/iph5526_novram.c``
FASYNC_MAGIC 0x4601 fasync_struct ``include/linux/fs.h``
FF_MAGIC 0x4646 fc_info ``drivers/net/iph5526_novram.c``
ISICOM_MAGIC 0x4d54 isi_port ``include/linux/isicom.h``
PTY_MAGIC 0x5001 ``drivers/char/pty.c``
PPP_MAGIC 0x5002 ppp ``include/linux/if_pppvar.h``
SERIAL_MAGIC 0x5301 async_struct ``include/linux/serial.h``
SSTATE_MAGIC 0x5302 serial_state ``include/linux/serial.h``
SLIP_MAGIC 0x5302 slip ``drivers/net/slip.h``
STRIP_MAGIC 0x5303 strip ``drivers/net/strip.c``
X25_ASY_MAGIC 0x5303 x25_asy ``drivers/net/x25_asy.h``
SIXPACK_MAGIC 0x5304 sixpack ``drivers/net/hamradio/6pack.h``
AX25_MAGIC 0x5316 ax_disp ``drivers/net/mkiss.h``
TTY_MAGIC 0x5401 tty_struct ``include/linux/tty.h``
MGSL_MAGIC 0x5401 mgsl_info ``drivers/char/synclink.c``
TTY_DRIVER_MAGIC 0x5402 tty_driver ``include/linux/tty_driver.h``
MGSLPC_MAGIC 0x5402 mgslpc_info ``drivers/char/pcmcia/synclink_cs.c``
TTY_LDISC_MAGIC 0x5403 tty_ldisc ``include/linux/tty_ldisc.h``
USB_SERIAL_MAGIC 0x6702 usb_serial ``drivers/usb/serial/usb-serial.h``
FULL_DUPLEX_MAGIC 0x6969 ``drivers/net/ethernet/dec/tulip/de2104x.c``
USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth ``drivers/usb/class/bluetty.c``
RFCOMM_TTY_MAGIC 0x6d02 ``net/bluetooth/rfcomm/tty.c``
USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port ``drivers/usb/serial/usb-serial.h``
CG_MAGIC 0x00090255 ufs_cylinder_group ``include/linux/ufs_fs.h``
RPORT_MAGIC 0x00525001 r_port ``drivers/char/rocket_int.h``
LSEMAGIC 0x05091998 lse ``drivers/fc4/fc.c``
GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str ``drivers/scsi/gdth_ioctl.h``
RIEBL_MAGIC 0x09051990 ``drivers/net/atarilance.c``
NBD_REQUEST_MAGIC 0x12560953 nbd_request ``include/linux/nbd.h``
RED_MAGIC2 0x170fc2a5 (any) ``mm/slab.c``
BAYCOM_MAGIC 0x19730510 baycom_state ``drivers/net/baycom_epp.c``
ISDN_X25IFACE_MAGIC 0x1e75a2b9 isdn_x25iface_proto_data ``drivers/isdn/isdn_x25iface.h``
ECP_MAGIC 0x21504345 cdkecpsig ``include/linux/cdk.h``
LSOMAGIC 0x27091997 lso ``drivers/fc4/fc.c``
LSMAGIC 0x2a3b4d2a ls ``drivers/fc4/fc.c``
WANPIPE_MAGIC 0x414C4453 sdla_{dump,exec} ``include/linux/wanpipe.h``
CS_CARD_MAGIC 0x43525553 cs_card ``sound/oss/cs46xx.c``
LABELCL_MAGIC 0x4857434c labelcl_info_s ``include/asm/ia64/sn/labelcl.h``
ISDN_ASYNC_MAGIC 0x49344C01 modem_info ``include/linux/isdn.h``
CTC_ASYNC_MAGIC 0x49344C01 ctc_tty_info ``drivers/s390/net/ctctty.c``
ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s ``drivers/isdn/i4l/isdn_net_lib.h``
SAVEKMSG_MAGIC2 0x4B4D5347 savekmsg ``arch/*/amiga/config.c``
CS_STATE_MAGIC 0x4c4f4749 cs_state ``sound/oss/cs46xx.c``
SLAB_C_MAGIC 0x4f17a36d kmem_cache ``mm/slab.c``
COW_MAGIC 0x4f4f4f4d cow_header_v1 ``arch/um/drivers/ubd_user.c``
I810_CARD_MAGIC 0x5072696E i810_card ``sound/oss/i810_audio.c``
TRIDENT_CARD_MAGIC 0x5072696E trident_card ``sound/oss/trident.c``
ROUTER_MAGIC 0x524d4157 wan_device [in ``wanrouter.h`` pre 3.9]
SAVEKMSG_MAGIC1 0x53415645 savekmsg ``arch/*/amiga/config.c``
GDA_MAGIC 0x58464552 gda ``arch/mips/include/asm/sn/gda.h``
RED_MAGIC1 0x5a2cf071 (any) ``mm/slab.c``
EEPROM_MAGIC_VALUE 0x5ab478d2 lanai_dev ``drivers/atm/lanai.c``
HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state ``include/linux/hdlcdrv.h``
PCXX_MAGIC 0x5c6df104 channel ``drivers/char/pcxx.h``
KV_MAGIC 0x5f4b565f kernel_vars_s ``arch/mips/include/asm/sn/klkernvars.h``
I810_STATE_MAGIC 0x63657373 i810_state ``sound/oss/i810_audio.c``
TRIDENT_STATE_MAGIC 0x63657373 trient_state ``sound/oss/trident.c``
M3_CARD_MAGIC 0x646e6f50 m3_card ``sound/oss/maestro3.c``
FW_HEADER_MAGIC 0x65726F66 fw_header ``drivers/atm/fore200e.h``
SLOT_MAGIC 0x67267321 slot ``drivers/hotplug/cpqphp.h``
SLOT_MAGIC 0x67267322 slot ``drivers/hotplug/acpiphp.h``
LO_MAGIC 0x68797548 nbd_device ``include/linux/nbd.h``
OPROFILE_MAGIC 0x6f70726f super_block ``drivers/oprofile/oprofilefs.h``
M3_STATE_MAGIC 0x734d724d m3_state ``sound/oss/maestro3.c``
VMALLOC_MAGIC 0x87654320 snd_alloc_track ``sound/core/memory.c``
KMALLOC_MAGIC 0x87654321 snd_alloc_track ``sound/core/memory.c``
PWC_MAGIC 0x89DC10AB pwc_device ``drivers/usb/media/pwc.h``
NBD_REPLY_MAGIC 0x96744668 nbd_reply ``include/linux/nbd.h``
ENI155_MAGIC 0xa54b872d midway_eprom ``drivers/atm/eni.h``
CODA_MAGIC 0xC0DAC0DA coda_file_info ``fs/coda/coda_fs_i.h``
DPMEM_MAGIC 0xc0ffee11 gdt_pci_sram ``drivers/scsi/gdth.h``
YAM_MAGIC 0xF10A7654 yam_port ``drivers/net/hamradio/yam.c``
CCB_MAGIC 0xf2691ad2 ccb ``drivers/scsi/ncr53c8xx.c``
QUEUE_MAGIC_FREE 0xf7e1c9a3 queue_entry ``drivers/scsi/arm/queue.c``
QUEUE_MAGIC_USED 0xf7e1cc33 queue_entry ``drivers/scsi/arm/queue.c``
HTB_CMAGIC 0xFEFAFEF1 htb_class ``net/sched/sch_htb.c``
NMI_MAGIC 0x48414d4d455201 nmi_s ``arch/mips/include/asm/sn/nmi.h``
===================== ================ ======================== ==========================================
Da notare che ci sono anche dei numeri magici specifici per driver nel
*sound memory management*. Consultate ``include/sound/sndmagic.h`` per una
lista completa. Molti driver audio OSS hanno i loro numeri magici costruiti a
partire dall'identificativo PCI della scheda audio - nemmeno questi sono
elencati in questo file.
Il file-system HFS è un altro grande utilizzatore di numeri magici - potete
trovarli qui ``fs/hfs/hfs.h``.
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/maintainer-pgp-guide.rst <pgpguide>`
.. _it_pgpguide:
========================================
Guida a PGP per i manutentori del kernel
========================================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/management-style.rst <managementstyle>`
.. _it_managementstyle:
Tipo di gestione del kernel Linux
=================================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/stable-api-nonsense.rst <stable_api_nonsense>`
.. _it_stable_api_nonsense:
L'interfaccia dei driver per il kernel Linux
============================================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
.. _it_stable_kernel_rules:
Tutto quello che volevate sapere sui rilasci -stable di Linux
==============================================================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/submit-checklist.rst <submitchecklist>`
.. _it_submitchecklist:
Lista delle cose da fare per inviare una modifica al kernel Linux
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
.. _it_submittingdrivers:
Sottomettere driver per il kernel Linux
=======================================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
.. _it_submittingpatches:
Sottomettere modifiche: la guida essenziale per vedere il vostro codice nel kernel
==================================================================================
.. warning::
TODO ancora da tradurre
.. include:: ../disclaimer-ita.rst
:Original: :ref:`Documentation/process/volatile-considered-harmful.rst <volatile_considered_harmful>`
:Translator: Federico Vaga <federico.vaga@vaga.pv.it>
.. _it_volatile_considered_harmful:
Perché la parola chiave "volatile" non dovrebbe essere usata
------------------------------------------------------------
Spesso i programmatori C considerano volatili quelle variabili che potrebbero
essere cambiate al di fuori dal thread di esecuzione corrente; come risultato,
a volte saranno tentati dall'utilizzare *volatile* nel kernel per le
strutture dati condivise. In altre parole, gli è stato insegnato ad usare
*volatile* come una variabile atomica di facile utilizzo, ma non è così.
L'uso di *volatile* nel kernel non è quasi mai corretto; questo documento ne
descrive le ragioni.
Il punto chiave da capire su *volatile* è che il suo scopo è quello di
sopprimere le ottimizzazioni, che non è quasi mai quello che si vuole.
Nel kernel si devono proteggere le strutture dati condivise contro accessi
concorrenti e indesiderati: questa è un'attività completamente diversa.
Il processo di protezione contro gli accessi concorrenti indesiderati eviterà
anche la maggior parte dei problemi relativi all'ottimizzazione in modo più
efficiente.
Come *volatile*, le primitive del kernel che rendono sicuro l'accesso ai dati
(spinlock, mutex, barriere di sincronizzazione, ecc) sono progettate per
prevenire le ottimizzazioni indesiderate. Se vengono usate opportunamente,
non ci sarà bisogno di utilizzare *volatile*. Se vi sembra che *volatile* sia
comunque necessario, ci dev'essere quasi sicuramente un baco da qualche parte.
In un pezzo di codice kernel scritto a dovere, *volatile* può solo servire a
rallentare le cose.
Considerate questo tipico blocco di codice kernel::
spin_lock(&the_lock);
do_something_on(&shared_data);
do_something_else_with(&shared_data);
spin_unlock(&the_lock);
Se tutto il codice seguisse le regole di sincronizzazione, il valore di un
dato condiviso non potrebbe cambiare inaspettatamente mentre si trattiene un
lock. Un qualsiasi altro blocco di codice che vorrà usare quel dato rimarrà
in attesa del lock. Gli spinlock agiscono come barriere di sincronizzazione
- sono stati esplicitamente scritti per agire così - il che significa che gli
accessi al dato condiviso non saranno ottimizzati. Quindi il compilatore
potrebbe pensare di sapere cosa ci sarà nel dato condiviso ma la chiamata
spin_lock(), che agisce come una barriera di sincronizzazione, gli imporrà di
dimenticarsi tutto ciò che sapeva su di esso.
Se il dato condiviso fosse stato dichiarato come *volatile*, la
sincronizzazione rimarrebbe comunque necessaria. Ma verrà impedito al
compilatore di ottimizzare gli accessi al dato anche _dentro_ alla sezione
critica, dove sappiamo che in realtà nessun altro può accedervi. Mentre si
trattiene un lock, il dato condiviso non è *volatile*. Quando si ha a che
fare con dei dati condivisi, un'opportuna sincronizzazione rende inutile
l'uso di *volatile* - anzi potenzialmente dannoso.
L'uso di *volatile* fu originalmente pensato per l'accesso ai registri di I/O
mappati in memoria. All'interno del kernel, l'accesso ai registri, dovrebbe
essere protetto dai lock, ma si potrebbe anche desiderare che il compilatore
non "ottimizzi" l'accesso ai registri all'interno di una sezione critica.
Ma, all'interno del kernel, l'accesso alla memoria di I/O viene sempre fatto
attraverso funzioni d'accesso; accedere alla memoria di I/O direttamente
con i puntatori è sconsigliato e non funziona su tutte le architetture.
Queste funzioni d'accesso sono scritte per evitare ottimizzazioni indesiderate,
quindi, di nuovo, *volatile* è inutile.
Un'altra situazione dove qualcuno potrebbe essere tentato dall'uso di
*volatile*, è nel caso in cui il processore è in un'attesa attiva sul valore
di una variabile. Il modo giusto di fare questo tipo di attesa è il seguente::
while (my_variable != what_i_want)
cpu_relax();
La chiamata cpu_relax() può ridurre il consumo di energia del processore
o cedere il passo ad un processore hyperthreaded gemello; funziona anche come
una barriera per il compilatore, quindi, ancora una volta, *volatile* non è
necessario. Ovviamente, tanto per puntualizzare, le attese attive sono
generalmente un atto antisociale.
Ci sono comunque alcune rare situazioni dove l'uso di *volatile* nel kernel
ha senso:
- Le funzioni d'accesso sopracitate potrebbero usare *volatile* su quelle
architetture che supportano l'accesso diretto alla memoria di I/O.
In pratica, ogni chiamata ad una funzione d'accesso diventa una piccola
sezione critica a se stante, e garantisce che l'accesso avvenga secondo
le aspettative del programmatore.
- I codice *inline assembly* che fa cambiamenti nella memoria, ma che non
ha altri effetti espliciti, rischia di essere rimosso da GCC. Aggiungere
la parola chiave *volatile* a questo codice ne previene la rimozione.
- La variabile jiffies è speciale in quanto assume un valore diverso ogni
volta che viene letta ma può essere lette senza alcuna sincronizzazione.
Quindi jiffies può essere *volatile*, ma l'aggiunta ad altre variabili di
questo è sconsigliata. Jiffies è considerata uno "stupido retaggio"
(parole di Linus) in questo contesto; correggerla non ne varrebbe la pena e
causerebbe più problemi.
- I puntatori a delle strutture dati in una memoria coerente che potrebbe
essere modificata da dispositivi di I/O può, a volte, essere legittimamente
*volatile*. Un esempio pratico può essere quello di un adattatore di rete
che utilizza un puntatore ad un buffer circolare, questo viene cambiato
dall'adattatore per indicare quali descrittori sono stati processati.
Per la maggior parte del codice, nessuna delle giustificazioni sopracitate può
essere considerata. Di conseguenza, l'uso di *volatile* è probabile che venga
visto come un baco e porterà a verifiche aggiuntive. Gli sviluppatori tentati
dall'uso di *volatile* dovrebbero fermarsi e pensare a cosa vogliono davvero
ottenere.
Le modifiche che rimuovono variabili *volatile* sono generalmente ben accette
- purché accompagnate da una giustificazione che dimostri che i problemi di
concorrenza siano stati opportunamente considerati.
Riferimenti
===========
[1] http://lwn.net/Articles/233481/
[2] http://lwn.net/Articles/233482/
Crediti
=======
Impulso e ricerca originale di Randy Dunlap
Scritto da Jonathan Corbet
Migliorato dai commenti di Satyam Sharma, Johannes Stezenbach, Jesper
Juhl, Heikki Orsila, H. Peter Anvin, Philipp Hahn, e Stefan Richter.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment