1181643Skmacy.. include:: ../disclaimer-ita.rst 2181643Skmacy 3181643Skmacy:Original: :ref:`Documentation/process/coding-style.rst <codingstyle>` 4181643Skmacy:Translator: Federico Vaga <federico.vaga@vaga.pv.it> 5181643Skmacy 6181643Skmacy.. _it_codingstyle: 7181643Skmacy 8181643SkmacyStile del codice per il kernel Linux 9181643Skmacy==================================== 10181643Skmacy 11181643SkmacyQuesto �� un breve documento che descrive lo stile di codice preferito per 12181643Skmacyil kernel Linux. Lo stile di codifica �� molto personale e non voglio 13181643Skmacy**forzare** nessuno ad accettare il mio, ma questo stile �� quello che 14181643Skmacydev'essere usato per qualsiasi cosa che io sia in grado di mantenere, e l'ho 15181643Skmacypreferito anche per molte altre cose. Per favore, almeno tenete in 16181643Skmacyconsiderazione le osservazioni espresse qui. 17181643Skmacy 18181643SkmacyLa prima cosa che suggerisco �� quella di stamparsi una copia degli standard 19181643Skmacydi codifica GNU e di NON leggerla. Bruciatela, �� un grande gesto simbolico. 20181643Skmacy 21181643SkmacyComunque, ecco i punti: 22181643Skmacy 23181643Skmacy1) Indentazione 24181643Skmacy--------------- 25181643Skmacy 26181643SkmacyLa tabulazione (tab) �� di 8 caratteri e cos�� anche le indentazioni. Ci sono 27181643Skmacyalcuni movimenti di eretici che vorrebbero l'indentazione a 4 (o perfino 2!) 28181643Skmacycaratteri di profondit��, che �� simile al tentativo di definire il valore del 29181643Skmacypi-greco a 3. 30181643Skmacy 31181643SkmacyMotivazione: l'idea dell'indentazione �� di definire chiaramente dove un blocco 32181643Skmacydi controllo inizia e finisce. Specialmente quando siete rimasti a guardare lo 33181643Skmacyschermo per 20 ore a file, troverete molto pi�� facile capire i livelli di 34181643Skmacyindentazione se questi sono larghi. 35181643Skmacy 36181643SkmacyOra, alcuni rivendicano che un'indentazione da 8 caratteri sposta il codice 37181643Skmacytroppo a destra e che quindi rende difficile la lettura su schermi a 80 38181643Skmacycaratteri. La risposta a questa affermazione �� che se vi servono pi�� di 3 39181643Skmacylivelli di indentazione, siete comunque fregati e dovreste correggere il vostro 40181643Skmacyprogramma. 41181643Skmacy 42181643SkmacyIn breve, l'indentazione ad 8 caratteri rende pi�� facile la lettura, e in 43181643Skmacyaggiunta vi avvisa quando state annidando troppo le vostre funzioni. 44181643SkmacyTenete ben a mente questo avviso. 45181643Skmacy 46181643SkmacyAl fine di facilitare l'indentazione del costrutto switch, si preferisce 47181643Skmacyallineare sulla stessa colonna la parola chiave ``switch`` e i suoi 48181643Skmacysubordinati ``case``. In questo modo si evita una doppia indentazione per 49181643Skmacyi ``case``. Un esempio.: 50181643Skmacy 51181643Skmacy.. code-block:: c 52181643Skmacy 53181643Skmacy switch (suffix) { 54181643Skmacy case 'G': 55181643Skmacy case 'g': 56181643Skmacy mem <<= 30; 57181643Skmacy break; 58181643Skmacy case 'M': 59181643Skmacy case 'm': 60181643Skmacy mem <<= 20; 61181643Skmacy break; 62181643Skmacy case 'K': 63181643Skmacy case 'k': 64181643Skmacy mem <<= 10; 65181643Skmacy fallthrough; 66181643Skmacy default: 67181643Skmacy break; 68181643Skmacy } 69181643Skmacy 70181643SkmacyA meno che non vogliate nascondere qualcosa, non mettete pi�� istruzioni sulla 71181643Skmacystessa riga: 72181643Skmacy 73181643Skmacy.. code-block:: c 74181643Skmacy 75181643Skmacy if (condition) do_this; 76181643Skmacy do_something_everytime; 77181643Skmacy 78181643SkmacyNon usate le virgole per evitare le parentesi: 79181643Skmacy 80181643Skmacy.. code-block:: c 81181643Skmacy 82181643Skmacy if (condition) 83181643Skmacy do_this(), do_that(); 84181643Skmacy 85181643SkmacyInvece, usate sempre le parentesi per racchiudere pi�� istruzioni. 86181643Skmacy 87181643Skmacy.. code-block:: c 88181643Skmacy 89181643Skmacy if (condition) { 90181643Skmacy do_this(); 91181643Skmacy do_that(); 92181643Skmacy } 93181643Skmacy 94181643SkmacyNon mettete nemmeno pi�� assegnamenti sulla stessa riga. Lo stile del kernel 95181643Skmacy�� ultrasemplice. Evitate espressioni intricate. 96181643Skmacy 97181643Skmacy 98181643SkmacyAl di fuori dei commenti, della documentazione ed escludendo i Kconfig, gli 99181643Skmacyspazi non vengono mai usati per l'indentazione, e l'esempio qui sopra �� 100181643Skmacyvolutamente errato. 101181643Skmacy 102181643SkmacyProcuratevi un buon editor di testo e non lasciate spazi bianchi alla fine 103181643Skmacydelle righe. 104181643Skmacy 105181643Skmacy 106181643Skmacy2) Spezzare righe lunghe e stringhe 107181643Skmacy----------------------------------- 108181643Skmacy 109181643SkmacyLo stile del codice riguarda la leggibilit�� e la manutenibilit�� utilizzando 110181643Skmacystrumenti comuni. 111181643Skmacy 112181643SkmacyCome limite di riga si preferiscono le 80 colonne. 113181643Skmacy 114181643SkmacyEspressioni pi�� lunghe di 80 colonne dovrebbero essere spezzettate in 115181643Skmacypezzi pi�� piccoli, a meno che eccedere le 80 colonne non aiuti ad 116181643Skmacyaumentare la leggibilit�� senza nascondere informazioni. 117181643Skmacy 118181643SkmacyI nuovi pezzi derivati sono sostanzialmente pi�� corti degli originali 119181643Skmacye vengono posizionati pi�� a destra. Uno stile molto comune �� quello di 120181643Skmacyallineare i nuovi pezzi alla parentesi aperta di una funzione. 121181643Skmacy 122181643SkmacyLo stesso si applica, nei file d'intestazione, alle funzioni con una 123181643Skmacylista di argomenti molto lunga. 124181643Skmacy 125181643SkmacyTuttavia, non spezzettate mai le stringhe visibili agli utenti come i 126181643Skmacymessaggi di printk, questo perch�� inibireste la possibilit�� 127181643Skmacyd'utilizzare grep per cercarle. 128181643Skmacy 129181643Skmacy3) Posizionamento di parentesi graffe e spazi 130181643Skmacy--------------------------------------------- 131181643Skmacy 132181643SkmacyUn altro problema che s'affronta sempre quando si parla di stile in C �� 133181643Skmacyil posizionamento delle parentesi graffe. Al contrario della dimensione 134181643Skmacydell'indentazione, non ci sono motivi tecnici sulla base dei quali scegliere 135181643Skmacyuna strategia di posizionamento o un'altra; ma il modo qui preferito, 136181643Skmacycome mostratoci dai profeti Kernighan e Ritchie, �� quello di 137181643Skmacyposizionare la parentesi graffa di apertura per ultima sulla riga, e quella 138181643Skmacydi chiusura per prima su una nuova riga, cos��: 139181643Skmacy 140181643Skmacy.. code-block:: c 141181643Skmacy 142181643Skmacy if (x is true) { 143181643Skmacy we do y 144181643Skmacy } 145181643Skmacy 146181643SkmacyQuesto �� valido per tutte le espressioni che non siano funzioni (if, switch, 147181643Skmacyfor, while, do). Per esempio: 148181643Skmacy 149181643Skmacy.. code-block:: c 150181643Skmacy 151181643Skmacy switch (action) { 152181643Skmacy case KOBJ_ADD: 153181643Skmacy return "add"; 154181643Skmacy case KOBJ_REMOVE: 155181643Skmacy return "remove"; 156181643Skmacy case KOBJ_CHANGE: 157181643Skmacy return "change"; 158181643Skmacy default: 159181643Skmacy return NULL; 160181643Skmacy } 161181643Skmacy 162181643SkmacyTuttavia, c'�� il caso speciale, le funzioni: queste hanno la parentesi graffa 163181643Skmacydi apertura all'inizio della riga successiva, quindi: 164181643Skmacy 165181643Skmacy.. code-block:: c 166181643Skmacy 167181643Skmacy int function(int x) 168181643Skmacy { 169181643Skmacy body of function 170181643Skmacy } 171181643Skmacy 172181643SkmacyEretici da tutto il mondo affermano che questa incoerenza �� ... 173181643Skmacyinsomma ... incoerente, ma tutte le persone ragionevoli sanno che (a) 174181643SkmacyK&R hanno **ragione** e (b) K&R hanno ragione. A parte questo, le funzioni 175181643Skmacysono comunque speciali (non potete annidarle in C). 176181643Skmacy 177181643SkmacyNotate che la graffa di chiusura �� da sola su una riga propria, ad 178181643Skmacy**eccezione** di quei casi dove �� seguita dalla continuazione della stessa 179181643Skmacyespressione, in pratica ``while`` nell'espressione do-while, oppure ``else`` 180181643Skmacynell'espressione if-else, come questo: 181181643Skmacy 182181643Skmacy.. code-block:: c 183181643Skmacy 184181643Skmacy do { 185181643Skmacy body of do-loop 186181643Skmacy } while (condition); 187181643Skmacy 188181643Skmacye 189181643Skmacy 190181643Skmacy.. code-block:: c 191181643Skmacy 192181643Skmacy if (x == y) { 193181643Skmacy .. 194181643Skmacy } else if (x > y) { 195181643Skmacy ... 196181643Skmacy } else { 197181643Skmacy .... 198181643Skmacy } 199181643Skmacy 200181643SkmacyMotivazione: K&R. 201181643Skmacy 202181643SkmacyInoltre, notate che questo posizionamento delle graffe minimizza il numero 203181643Skmacydi righe vuote senza perdere di leggibilit��. In questo modo, dato che le 204181643Skmacyrighe sul vostro schermo non sono una risorsa illimitata (pensate ad uno 205181643Skmacyterminale con 25 righe), avrete delle righe vuote da riempire con dei 206181643Skmacycommenti. 207181643Skmacy 208181643SkmacyNon usate inutilmente le graffe dove una singola espressione �� sufficiente. 209181643Skmacy 210181643Skmacy.. code-block:: c 211181643Skmacy 212181643Skmacy if (condition) 213181643Skmacy action(); 214181643Skmacy 215181643Skmacye 216181643Skmacy 217181643Skmacy.. code-block:: none 218181643Skmacy 219181643Skmacy if (condition) 220181643Skmacy do_this(); 221181643Skmacy else 222181643Skmacy do_that(); 223181643Skmacy 224181643SkmacyQuesto non vale nel caso in cui solo un ramo dell'espressione if-else 225181643Skmacycontiene una sola espressione; in quest'ultimo caso usate le graffe per 226181643Skmacyentrambe i rami: 227181643Skmacy 228181643Skmacy.. code-block:: c 229181643Skmacy 230181643Skmacy if (condition) { 231181643Skmacy do_this(); 232181643Skmacy do_that(); 233181643Skmacy } else { 234181643Skmacy otherwise(); 235181643Skmacy } 236181643Skmacy 237181643SkmacyInoltre, usate le graffe se un ciclo contiene pi�� di una semplice istruzione: 238181643Skmacy 239181643Skmacy.. code-block:: c 240181643Skmacy 241181643Skmacy while (condition) { 242181643Skmacy if (test) 243181643Skmacy do_something(); 244181643Skmacy } 245181643Skmacy 246181643Skmacy3.1) Spazi 247181643Skmacy********** 248181643Skmacy 249181643SkmacyLo stile del kernel Linux per quanto riguarda gli spazi, dipende 250181643Skmacy(principalmente) dalle funzioni e dalle parole chiave. Usate una spazio dopo 251181643Skmacy(quasi tutte) le parole chiave. L'eccezioni pi�� evidenti sono sizeof, typeof, 252181643Skmacyalignof, e __attribute__, il cui aspetto �� molto simile a quello delle 253181643Skmacyfunzioni (e in Linux, solitamente, sono usate con le parentesi, anche se il 254181643Skmacylinguaggio non lo richiede; come ``sizeof info`` dopo aver dichiarato 255181643Skmacy``struct fileinfo info``). 256181643Skmacy 257181643SkmacyQuindi utilizzate uno spazio dopo le seguenti parole chiave:: 258181643Skmacy 259181643Skmacy if, switch, case, for, do, while 260181643Skmacy 261181643Skmacyma non con sizeof, typeof, alignof, o __attribute__. Ad esempio, 262181643Skmacy 263181643Skmacy.. code-block:: c 264181643Skmacy 265181643Skmacy 266181643Skmacy s = sizeof(struct file); 267181643Skmacy 268181643SkmacyNon aggiungete spazi attorno (dentro) ad un'espressione fra parentesi. Questo 269181643Skmacyesempio �� **brutto**: 270181643Skmacy 271181643Skmacy.. code-block:: c 272181643Skmacy 273181643Skmacy 274181643Skmacy s = sizeof( struct file ); 275181643Skmacy 276181643SkmacyQuando dichiarate un puntatore ad una variabile o una funzione che ritorna un 277181643Skmacypuntatore, il posto suggerito per l'asterisco ``*`` �� adiacente al nome della 278181643Skmacyvariabile o della funzione, e non adiacente al nome del tipo. Esempi: 279181643Skmacy 280181643Skmacy.. code-block:: c 281181643Skmacy 282181643Skmacy 283181643Skmacy char *linux_banner; 284181643Skmacy unsigned long long memparse(char *ptr, char **retptr); 285181643Skmacy char *match_strdup(substring_t *s); 286181643Skmacy 287181643SkmacyUsate uno spazio attorno (da ogni parte) alla maggior parte degli operatori 288181643Skmacybinari o ternari, come i seguenti:: 289181643Skmacy 290181643Skmacy = + - < > * / % | & ^ <= >= == != ? : 291181643Skmacy 292181643Skmacyma non mettete spazi dopo gli operatori unari:: 293181643Skmacy 294181643Skmacy & * + - ~ ! sizeof typeof alignof __attribute__ defined 295181643Skmacy 296181643Skmacynessuno spazio dopo l'operatore unario suffisso di incremento o decremento:: 297181643Skmacy 298181643Skmacy ++ -- 299181643Skmacy 300181643Skmacynessuno spazio dopo l'operatore unario prefisso di incremento o decremento:: 301181643Skmacy 302181643Skmacy ++ -- 303181643Skmacy 304181643Skmacye nessuno spazio attorno agli operatori dei membri di una struttura ``.`` e 305181643Skmacy``->``. 306181643Skmacy 307181643SkmacyNon lasciate spazi bianchi alla fine delle righe. Alcuni editor con 308181643Skmacyl'indentazione ``furba`` inseriranno gli spazi bianchi all'inizio di una nuova 309181643Skmacyriga in modo appropriato, quindi potrete scrivere la riga di codice successiva 310181643Skmacyimmediatamente. Tuttavia, alcuni di questi stessi editor non rimuovono 311181643Skmacyquesti spazi bianchi quando non scrivete nulla sulla nuova riga, ad esempio 312181643Skmacyperch�� volete lasciare una riga vuota. Il risultato �� che finirete per avere 313181643Skmacydelle righe che contengono spazi bianchi in coda. 314181643Skmacy 315181643SkmacyGit vi avviser�� delle modifiche che aggiungono questi spazi vuoti di fine riga, 316181643Skmacye pu�� opzionalmente rimuoverli per conto vostro; tuttavia, se state applicando 317181643Skmacyuna serie di modifiche, questo potrebbe far fallire delle modifiche successive 318181643Skmacyperch�� il contesto delle righe verr�� cambiato. 319181643Skmacy 320181643Skmacy4) Assegnare nomi 321181643Skmacy----------------- 322181643Skmacy 323181643SkmacyC �� un linguaggio spartano, e cos�� dovrebbero esserlo i vostri nomi. Al 324181643Skmacycontrario dei programmatori Modula-2 o Pascal, i programmatori C non usano 325181643Skmacynomi graziosi come ThisVariableIsATemporaryCounter. Un programmatore C 326181643Skmacychiamerebbe questa variabile ``tmp``, che �� molto pi�� facile da scrivere e 327181643Skmacynon �� una delle pi�� difficili da capire. 328181643Skmacy 329181643SkmacyTUTTAVIA, nonostante i nomi con notazione mista siano da condannare, i nomi 330181643Skmacydescrittivi per variabili globali sono un dovere. Chiamare una funzione 331181643Skmacyglobale ``pippo`` �� un insulto. 332181643Skmacy 333181643SkmacyLe variabili GLOBALI (da usare solo se vi servono **davvero**) devono avere 334181643Skmacydei nomi descrittivi, cos�� come le funzioni globali. Se avete una funzione 335181643Skmacyche conta gli utenti attivi, dovreste chiamarla ``count_active_users()`` o 336181643Skmacyqualcosa di simile, **non** dovreste chiamarla ``cntusr()``. 337181643Skmacy 338181643SkmacyCodificare il tipo di funzione nel suo nome (quella cosa chiamata notazione 339181643Skmacyungherese) �� stupido - il compilatore conosce comunque il tipo e 340181643Skmacypu�� verificarli, e inoltre confonde i programmatori. 341181643Skmacy 342181643SkmacyLe variabili LOCALI dovrebbero avere nomi corti, e significativi. Se avete 343181643Skmacyun qualsiasi contatore di ciclo, probabilmente sar�� chiamato ``i``. 344181643SkmacyChiamarlo ``loop_counter`` non �� produttivo, non ci sono possibilit�� che 345181643Skmacy``i`` possa non essere capito. Analogamente, ``tmp`` pu�� essere una qualsiasi 346181643Skmacyvariabile che viene usata per salvare temporaneamente un valore. 347181643Skmacy 348181643SkmacySe avete paura di fare casino coi nomi delle vostre variabili locali, allora 349181643Skmacyavete un altro problema che �� chiamato sindrome dello squilibrio dell'ormone 350181643Skmacydella crescita delle funzioni. Vedere il capitolo 6 (funzioni). 351181643Skmacy 352181643Skmacy5) Definizione di tipi (typedef) 353181643Skmacy-------------------------------- 354181643Skmacy 355181643SkmacyPer favore non usate cose come ``vps_t``. 356181643SkmacyUsare il typedef per strutture e puntatori �� uno **sbaglio**. Quando vedete: 357181643Skmacy 358181643Skmacy.. code-block:: c 359181643Skmacy 360181643Skmacy vps_t a; 361181643Skmacy 362181643Skmacynei sorgenti, cosa significa? 363181643SkmacySe, invece, dicesse: 364181643Skmacy 365181643Skmacy.. code-block:: c 366181643Skmacy 367181643Skmacy struct virtual_container *a; 368181643Skmacy 369181643Skmacypotreste dire cos'�� effettivamente ``a``. 370181643Skmacy 371181643SkmacyMolte persone pensano che la definizione dei tipi ``migliori la leggibilit��``. 372181643SkmacyNon molto. Sono utili per: 373181643Skmacy 374181643Skmacy (a) gli oggetti completamente opachi (dove typedef viene proprio usato allo 375181643Skmacy scopo di **nascondere** cosa sia davvero l'oggetto). 376181643Skmacy 377181643Skmacy Esempio: ``pte_t`` eccetera sono oggetti opachi che potete usare solamente 378181643Skmacy con le loro funzioni accessorie. 379181643Skmacy 380181643Skmacy .. note:: 381181643Skmacy Gli oggetti opachi e le ``funzioni accessorie`` non sono, di per se, 382181643Skmacy una bella cosa. Il motivo per cui abbiamo cose come pte_t eccetera �� 383181643Skmacy che davvero non c'�� alcuna informazione portabile. 384181643Skmacy 385181643Skmacy (b) i tipi chiaramente interi, dove l'astrazione **aiuta** ad evitare 386181643Skmacy confusione sul fatto che siano ``int`` oppure ``long``. 387181643Skmacy 388181643Skmacy u8/u16/u32 sono typedef perfettamente accettabili, anche se ricadono 389181643Skmacy nella categoria (d) piuttosto che in questa. 390181643Skmacy 391181643Skmacy .. note:: 392181643Skmacy 393181643Skmacy Ancora - dev'esserci una **ragione** per farlo. Se qualcosa �� 394181643Skmacy ``unsigned long``, non c'�� alcun bisogno di avere: 395181643Skmacy 396181643Skmacy typedef unsigned long myfalgs_t; 397181643Skmacy 398181643Skmacy ma se ci sono chiare circostanze in cui potrebbe essere ``unsigned int`` 399181643Skmacy e in altre configurazioni ``unsigned long``, allora certamente typedef 400181643Skmacy �� una buona scelta. 401181643Skmacy 402181643Skmacy (c) quando di rado create letteralmente dei **nuovi** tipi su cui effettuare 403181643Skmacy verifiche. 404181643Skmacy 405181643Skmacy (d) circostanze eccezionali, in cui si definiscono nuovi tipi identici a 406181643Skmacy quelli definiti dallo standard C99. 407181643Skmacy 408181643Skmacy Nonostante ci voglia poco tempo per abituare occhi e cervello all'uso dei 409181643Skmacy tipi standard come ``uint32_t``, alcune persone ne obiettano l'uso. 410181643Skmacy 411181643Skmacy Perci��, i tipi specifici di Linux ``u8/u16/u32/u64`` e i loro equivalenti 412181643Skmacy con segno, identici ai tipi standard, sono permessi- tuttavia, non sono 413181643Skmacy obbligatori per il nuovo codice. 414181643Skmacy 415181643Skmacy (e) i tipi sicuri nella spazio utente. 416181643Skmacy 417181643Skmacy In alcune strutture dati visibili dallo spazio utente non possiamo 418181643Skmacy richiedere l'uso dei tipi C99 e nemmeno i vari ``u32`` descritti prima. 419181643Skmacy Perci��, utilizziamo __u32 e tipi simili in tutte le strutture dati 420181643Skmacy condivise con lo spazio utente. 421181643Skmacy 422181643SkmacyMagari ci sono altri casi validi, ma la regola di base dovrebbe essere di 423181643Skmacynon usare MAI MAI un typedef a meno che non rientri in una delle regole 424181643Skmacydescritte qui. 425181643Skmacy 426181643SkmacyIn generale, un puntatore, o una struttura a cui si ha accesso diretto in 427181643Skmacymodo ragionevole, non dovrebbero **mai** essere definite con un typedef. 428181643Skmacy 429181643Skmacy6) Funzioni 430181643Skmacy----------- 431181643Skmacy 432181643SkmacyLe funzioni dovrebbero essere brevi e carine, e fare una cosa sola. Dovrebbero 433181643Skmacyoccupare uno o due schermi di testo (come tutti sappiamo, la dimensione 434181643Skmacydi uno schermo secondo ISO/ANSI �� di 80x24), e fare una cosa sola e bene. 435181643Skmacy 436181643SkmacyLa massima lunghezza di una funziona �� inversamente proporzionale alla sua 437181643Skmacycomplessit�� e al livello di indentazione di quella funzione. Quindi, se avete 438181643Skmacyuna funzione che �� concettualmente semplice ma che �� implementata come un 439181643Skmacylunga (ma semplice) sequenza di caso-istruzione, dove avete molte piccole cose 440181643Skmacyper molti casi differenti, allora va bene avere funzioni pi�� lunghe. 441181643Skmacy 442181643SkmacyComunque, se avete una funzione complessa e sospettate che uno studente 443181643Skmacynon particolarmente dotato del primo anno delle scuole superiori potrebbe 444181643Skmacynon capire cosa faccia la funzione, allora dovreste attenervi strettamente ai 445181643Skmacylimiti. Usate funzioni di supporto con nomi descrittivi (potete chiedere al 446181643Skmacycompilatore di renderle inline se credete che sia necessario per le 447181643Skmacyprestazioni, e probabilmente far�� un lavoro migliore di quanto avreste potuto 448181643Skmacyfare voi). 449181643Skmacy 450181643SkmacyUn'altra misura delle funzioni sono il numero di variabili locali. Non 451181643Skmacydovrebbero eccedere le 5-10, oppure state sbagliando qualcosa. Ripensate la 452181643Skmacyfunzione, e dividetela in pezzettini. Generalmente, un cervello umano pu�� 453181643Skmacyseguire facilmente circa 7 cose diverse, di pi�� lo confonderebbe. Lo sai 454181643Skmacyd'essere brillante, ma magari vorresti riuscire a capire cos'avevi fatto due 455181643Skmacysettimane prima. 456181643Skmacy 457181643SkmacyNei file sorgenti, separate le funzioni con una riga vuota. Se la funzione �� 458181643Skmacyesportata, la macro **EXPORT** per questa funzione deve seguire immediatamente 459181643Skmacyla riga della parentesi graffa di chiusura. Ad esempio: 460181643Skmacy 461181643Skmacy.. code-block:: c 462181643Skmacy 463181643Skmacy int system_is_up(void) 464181643Skmacy { 465181643Skmacy return system_state == SYSTEM_RUNNING; 466181643Skmacy } 467181643Skmacy EXPORT_SYMBOL(system_is_up); 468181643Skmacy 469181643Skmacy6.1) Prototipi di funzione 470181643Skmacy************************** 471181643Skmacy 472181643SkmacyNei prototipi di funzione, includete i nomi dei parametri e i loro tipi. 473181643SkmacyNonostante questo non sia richiesto dal linguaggio C, in Linux viene preferito 474181643Skmacyperch�� �� un modo semplice per aggiungere informazioni importanti per il 475181643Skmacylettore. 476181643Skmacy 477181643SkmacyNon usate la parola chiave ``extern`` con le dichiarazioni di funzione perch�� 478181643Skmacyrende le righe pi�� lunghe e non �� strettamente necessario. 479181643Skmacy 480181643SkmacyQuando scrivete i prototipi di funzione mantenete `l'ordine degli elementi <https://lore.kernel.org/mm-commits/CAHk-=wiOCLRny5aifWNhr621kYrJwhfURsa0vFPeUEm8mF0ufg@mail.gmail.com/>`_. 481181643Skmacy 482181643SkmacyPrendiamo questa dichiarazione di funzione come esempio:: 483181643Skmacy 484181643Skmacy __init void * __must_check action(enum magic value, size_t size, u8 count, 485181643Skmacy char *fmt, ...) __printf(4, 5) __malloc; 486181643Skmacy 487181643SkmacyL'ordine suggerito per gli elementi di un prototipo di funzione �� il seguente: 488181643Skmacy 489181643Skmacy- classe d'archiviazione (in questo caso ``static __always_inline``. Da notare 490181643Skmacy che ``__always_inline`` �� tecnicamente un attributo ma che viene trattato come 491181643Skmacy ``inline``) 492181643Skmacy- attributi della classe di archiviazione (in questo caso ``__init``, in altre 493181643Skmacy parole la sezione, ma anche cose tipo ``__cold``) 494181643Skmacy- il tipo di ritorno (in questo caso, ``void *``) 495181643Skmacy- attributi per il valore di ritorno (in questo caso, ``__must_check``) 496181643Skmacy- il nome della funzione (in questo caso, ``action``) 497181643Skmacy- i parametri della funzione(in questo caso, 498181643Skmacy ``(enum magic value, size_t size, u8 count, char *fmt, ...)``, 499181643Skmacy da notare che va messo anche il nome del parametro) 500181643Skmacy- attributi dei parametri (in questo caso, ``__printf(4, 5)``) 501181643Skmacy- attributi per il comportamento della funzione (in questo caso, ``__malloc_``) 502181643Skmacy 503181643SkmacyNotate che per la **definizione** di una funzione (il altre parole il corpo 504181643Skmacydella funzione), il compilatore non permette di usare gli attributi per i 505181643Skmacyparametri dopo i parametri. In questi casi, devono essere messi dopo gli 506181643Skmacyattributi della classe d'archiviazione (notate che la posizione di 507181643Skmacy``__printf(4,5)`` cambia rispetto alla **dichiarazione**):: 508181643Skmacy 509181643Skmacy static __always_inline __init __printf(4, 5) void * __must_check action(enum magic value, 510181643Skmacy size_t size, u8 count, char *fmt, ...) __malloc 511181643Skmacy { 512181643Skmacy ... 513181643Skmacy }*)**``)**``)``)``*)``)``)``)``*``)``)``)*) 514181643Skmacy 515181643Skmacy7) Centralizzare il ritorno delle funzioni 516181643Skmacy------------------------------------------ 517181643Skmacy 518181643SkmacySebbene sia deprecata da molte persone, l'istruzione goto �� impiegata di 519181643Skmacyfrequente dai compilatori sotto forma di salto incondizionato. 520181643Skmacy 521181643SkmacyL'istruzione goto diventa utile quando una funzione ha punti d'uscita multipli 522181643Skmacye vanno eseguite alcune procedure di pulizia in comune. Se non �� necessario 523181643Skmacypulire alcunch��, allora ritornate direttamente. 524181643Skmacy 525181643SkmacyAssegnate un nome all'etichetta di modo che suggerisca cosa fa la goto o 526181643Skmacyperch�� esiste. Un esempio di un buon nome potrebbe essere ``out_free_buffer:`` 527181643Skmacyse la goto libera (free) un ``buffer``. Evitate l'uso di nomi GW-BASIC come 528181643Skmacy``err1:`` ed ``err2:``, potreste doverli riordinare se aggiungete o rimuovete 529181643Skmacypunti d'uscita, e inoltre rende difficile verificarne la correttezza. 530181643Skmacy 531181643SkmacyI motivo per usare le goto sono: 532181643Skmacy 533181643Skmacy- i salti incondizionati sono pi�� facili da capire e seguire 534181643Skmacy- l'annidamento si riduce 535181643Skmacy- si evita di dimenticare, per errore, di aggiornare un singolo punto d'uscita 536181643Skmacy- aiuta il compilatore ad ottimizzare il codice ridondante ;) 537181643Skmacy 538181643Skmacy.. code-block:: c 539181643Skmacy 540181643Skmacy int fun(int a) 541181643Skmacy { 542181643Skmacy int result = 0; 543181643Skmacy char *buffer; 544181643Skmacy 545181643Skmacy buffer = kmalloc(SIZE, GFP_KERNEL); 546181643Skmacy if (!buffer) 547181643Skmacy return -ENOMEM; 548181643Skmacy 549181643Skmacy if (condition1) { 550181643Skmacy while (loop1) { 551181643Skmacy ... 552181643Skmacy } 553181643Skmacy result = 1; 554181643Skmacy goto out_free_buffer; 555181643Skmacy } 556181643Skmacy ... 557181643Skmacy out_free_buffer: 558181643Skmacy kfree(buffer); 559181643Skmacy return result; 560181643Skmacy } 561181643Skmacy 562181643SkmacyUn baco abbastanza comune di cui bisogna prendere nota �� il ``one err bugs`` 563181643Skmacyche assomiglia a questo: 564181643Skmacy 565181643Skmacy.. code-block:: c 566181643Skmacy 567181643Skmacy err: 568181643Skmacy kfree(foo->bar); 569181643Skmacy kfree(foo); 570181643Skmacy return ret; 571181643Skmacy 572181643SkmacyIl baco in questo codice �� che in alcuni punti d'uscita la variabile ``foo`` �� 573181643SkmacyNULL. Normalmente si corregge questo baco dividendo la gestione dell'errore in 574181643Skmacydue parti ``err_free_bar:`` e ``err_free_foo:``: 575181643Skmacy 576181643Skmacy.. code-block:: c 577181643Skmacy 578181643Skmacy err_free_bar: 579181643Skmacy kfree(foo->bar); 580181643Skmacy err_free_foo: 581181643Skmacy kfree(foo); 582181643Skmacy return ret; 583181643Skmacy 584181643SkmacyIdealmente, dovreste simulare condizioni d'errore per verificare i vostri 585181643Skmacypercorsi d'uscita. 586181643Skmacy 587181643Skmacy 588181643Skmacy8) Commenti 589181643Skmacy----------- 590181643Skmacy 591181643SkmacyI commenti sono una buona cosa, ma c'�� anche il rischio di esagerare. MAI 592181643Skmacyspiegare COME funziona il vostro codice in un commento: �� molto meglio 593181643Skmacyscrivere il codice di modo che il suo funzionamento sia ovvio, inoltre 594181643Skmacyspiegare codice scritto male �� una perdita di tempo. 595181643Skmacy 596181643SkmacySolitamente, i commenti devono dire COSA fa il codice, e non COME lo fa. 597181643SkmacyInoltre, cercate di evitare i commenti nel corpo della funzione: se la 598181643Skmacyfunzione �� cos�� complessa che dovete commentarla a pezzi, allora dovreste 599181643Skmacytornare al punto 6 per un momento. Potete mettere dei piccoli commenti per 600181643Skmacyannotare o avvisare il lettore circa un qualcosa di particolarmente arguto 601181643Skmacy(o brutto), ma cercate di non esagerare. Invece, mettete i commenti in 602181643Skmacytesta alla funzione spiegando alle persone cosa fa, e possibilmente anche 603181643Skmacyil PERCH��. 604181643Skmacy 605181643SkmacyPer favore, quando commentate una funzione dell'API del kernel usate il 606181643Skmacyformato kernel-doc. Per maggiori dettagli, leggete i file in 607181643Skmacy:ref::ref:`Documentation/translations/it_IT/doc-guide/ <it_doc_guide>` e in 608181643Skmacy``script/kernel-doc``. 609181643Skmacy 610181643SkmacyLo stile preferito per i commenti pi�� lunghi (multi-riga) ��: 611181643Skmacy 612181643Skmacy.. code-block:: c 613181643Skmacy 614181643Skmacy /* 615181643Skmacy * This is the preferred style for multi-line 616181643Skmacy * comments in the Linux kernel source code. 617181643Skmacy * Please use it consistently. 618181643Skmacy * 619181643Skmacy * Description: A column of asterisks on the left side, 620181643Skmacy * with beginning and ending almost-blank lines. 621181643Skmacy */ 622181643Skmacy 623181643SkmacyPer i file in net/ e in drivers/net/ lo stile preferito per i commenti 624181643Skmacypi�� lunghi (multi-riga) �� leggermente diverso. 625181643Skmacy 626181643Skmacy.. code-block:: c 627181643Skmacy 628181643Skmacy /* The preferred comment style for files in net/ and drivers/net 629181643Skmacy * looks like this. 630181643Skmacy * 631181643Skmacy * It is nearly the same as the generally preferred comment style, 632181643Skmacy * but there is no initial almost-blank line. 633181643Skmacy */ 634181643Skmacy 635181643Skmacy�� anche importante commentare i dati, sia per i tipi base che per tipi 636181643Skmacyderivati. A questo scopo, dichiarate un dato per riga (niente virgole 637181643Skmacyper una dichiarazione multipla). Questo vi lascer�� spazio per un piccolo 638181643Skmacycommento per spiegarne l'uso. 639181643Skmacy 640181643Skmacy 641181643Skmacy9) Avete fatto un pasticcio 642181643Skmacy--------------------------- 643181643Skmacy 644181643SkmacyVa bene, li facciamo tutti. Probabilmente vi �� stato detto dal vostro 645181643Skmacyaiutante Unix di fiducia che ``GNU emacs`` formatta automaticamente il 646181643Skmacycodice C per conto vostro, e avete notato che s��, in effetti lo fa, ma che 647181643Skmacyi modi predefiniti non sono proprio allettanti (infatti, sono peggio che 648181643Skmacypremere tasti a caso - un numero infinito di scimmie che scrivono in 649181643SkmacyGNU emacs non faranno mai un buon programma). 650181643Skmacy 651181643SkmacyQuindi, potete sbarazzarvi di GNU emacs, o riconfigurarlo con valori pi�� 652181643Skmacysensati. Per fare quest'ultima cosa, potete appiccicare il codice che 653181643Skmacysegue nel vostro file .emacs: 654181643Skmacy 655181643Skmacy.. code-block:: none 656181643Skmacy 657181643Skmacy (defun c-lineup-arglist-tabs-only (ignored) 658181643Skmacy "Line up argument lists by tabs, not spaces" 659181643Skmacy (let* ((anchor (c-langelem-pos c-syntactic-element)) 660181643Skmacy (column (c-langelem-2nd-pos c-syntactic-element)) 661181643Skmacy (offset (- (1+ column) anchor)) 662181643Skmacy (steps (floor offset c-basic-offset))) 663181643Skmacy (* (max steps 1) 664181643Skmacy c-basic-offset))) 665181643Skmacy 666181643Skmacy (dir-locals-set-class-variables 667181643Skmacy 'linux-kernel 668181643Skmacy '((c-mode . ( 669181643Skmacy (c-basic-offset . 8) 670181643Skmacy (c-label-minimum-indentation . 0) 671181643Skmacy (c-offsets-alist . ( 672181643Skmacy (arglist-close . c-lineup-arglist-tabs-only) 673181643Skmacy (arglist-cont-nonempty . 674181643Skmacy (c-lineup-gcc-asm-reg c-lineup-arglist-tabs-only)) 675181643Skmacy (arglist-intro . +) 676181643Skmacy (brace-list-intro . +) 677181643Skmacy (c . c-lineup-C-comments) 678181643Skmacy (case-label . 0) 679181643Skmacy (comment-intro . c-lineup-comment) 680181643Skmacy (cpp-define-intro . +) 681181643Skmacy (cpp-macro . -1000) 682181643Skmacy (cpp-macro-cont . +) 683181643Skmacy (defun-block-intro . +) 684181643Skmacy (else-clause . 0) 685181643Skmacy (func-decl-cont . +) 686181643Skmacy (inclass . +) 687181643Skmacy (inher-cont . c-lineup-multi-inher) 688181643Skmacy (knr-argdecl-intro . 0) 689181643Skmacy (label . -1000) 690181643Skmacy (statement . 0) 691181643Skmacy (statement-block-intro . +) 692181643Skmacy (statement-case-intro . +) 693181643Skmacy (statement-cont . +) 694181643Skmacy (substatement . +) 695181643Skmacy )) 696181643Skmacy (indent-tabs-mode . t) 697181643Skmacy (show-trailing-whitespace . t) 698181643Skmacy )))) 699181643Skmacy 700181643Skmacy (dir-locals-set-directory-class 701181643Skmacy (expand-file-name "~/src/linux-trees") 702181643Skmacy 'linux-kernel) 703181643Skmacy 704181643SkmacyQuesto far�� funzionare meglio emacs con lo stile del kernel per i file che 705181643Skmacysi trovano nella cartella ``~/src/linux-trees``. 706181643Skmacy 707181643SkmacyMa anche se doveste fallire nell'ottenere una formattazione sensata in emacs 708181643Skmacynon tutto �� perduto: usate ``indent``. 709181643Skmacy 710181643SkmacyOra, ancora, GNU indent ha la stessa configurazione decerebrata di GNU emacs, 711181643Skmacyed �� per questo che dovete passargli alcune opzioni da riga di comando. 712181643SkmacyTuttavia, non �� cos�� terribile, perch�� perfino i creatori di GNU indent 713181643Skmacyriconoscono l'autorit�� di K&R (le persone del progetto GNU non sono cattive, 714181643Skmacysono solo mal indirizzate sull'argomento), quindi date ad indent le opzioni 715181643Skmacy``-kr -i8`` (che significa ``K&R, 8 caratteri di indentazione``), o utilizzate 716181643Skmacy``scripts/Lindent`` che indenter�� usando l'ultimo stile. 717181643Skmacy 718181643Skmacy``indent`` ha un sacco di opzioni, e specialmente quando si tratta di 719181643Skmacyriformattare i commenti dovreste dare un'occhiata alle pagine man. 720181643SkmacyMa ricordatevi: ``indent`` non �� un correttore per una cattiva programmazione. 721181643Skmacy 722181643SkmacyDa notare che potete utilizzare anche ``clang-format`` per aiutarvi con queste 723181643Skmacyregole, per riformattare rapidamente ad automaticamente alcune parti del 724181643Skmacyvostro codice, e per revisionare interi file al fine di identificare errori 725181643Skmacydi stile, refusi e possibilmente anche delle migliorie. �� anche utile per 726181643Skmacyordinare gli ``#include``, per allineare variabili/macro, per ridistribuire 727181643Skmacyil testo e altre cose simili. 728181643SkmacyPer maggiori dettagli, consultate il file 729181643Skmacy:ref:`Documentation/translations/it_IT/process/clang-format.rst <it_clangformat>`. 730181643Skmacy 731181643Skmacy 732181643Skmacy10) File di configurazione Kconfig 733181643Skmacy---------------------------------- 734181643Skmacy 735181643SkmacyPer tutti i file di configurazione Kconfig* che si possono trovare nei 736181643Skmacysorgenti, l'indentazione �� un po' differente. Le linee dopo un ``config`` 737181643Skmacysono indentate con un tab, mentre il testo descrittivo �� indentato di 738181643Skmacyulteriori due spazi. Esempio:: 739181643Skmacy 740181643Skmacy config AUDIT 741181643Skmacy bool "Auditing support" 742181643Skmacy depends on NET 743181643Skmacy help 744181643Skmacy Enable auditing infrastructure that can be used with another 745181643Skmacy kernel subsystem, such as SELinux (which requires this for 746181643Skmacy logging of avc messages output). Does not do system-call 747181643Skmacy auditing without CONFIG_AUDITSYSCALL. 748181643Skmacy 749181643SkmacyLe funzionalit�� davvero pericolose (per esempio il supporto alla scrittura 750181643Skmacyper certi filesystem) dovrebbero essere dichiarate chiaramente come tali 751181643Skmacynella stringa di titolo:: 752181643Skmacy 753181643Skmacy config ADFS_FS_RW 754181643Skmacy bool "ADFS write support (DANGEROUS)" 755181643Skmacy depends on ADFS_FS 756181643Skmacy ... 757181643Skmacy 758181643SkmacyPer la documentazione completa sui file di configurazione, consultate 759181643Skmacyil documento Documentation/kbuild/kconfig-language.rst 760181643Skmacy 761181643Skmacy 762181643Skmacy11) Strutture dati 763181643Skmacy------------------ 764181643Skmacy 765181643SkmacyLe strutture dati che hanno una visibilit�� superiore al contesto del 766181643Skmacysingolo thread in cui vengono create e distrutte, dovrebbero sempre 767181643Skmacyavere un contatore di riferimenti. Nel kernel non esiste un 768181643Skmacy*garbage collector* (e fuori dal kernel i *garbage collector* sono lenti 769181643Skmacye inefficienti), questo significa che **dovete** assolutamente avere un 770181643Skmacycontatore di riferimenti per ogni cosa che usate. 771181643Skmacy 772181643SkmacyAvere un contatore di riferimenti significa che potete evitare la 773181643Skmacysincronizzazione e permette a pi�� utenti di accedere alla struttura dati 774181643Skmacyin parallelo - e non doversi preoccupare di una struttura dati che 775181643Skmacyimprovvisamente sparisce dalla loro vista perch�� il loro processo dormiva 776181643Skmacyo stava facendo altro per un attimo. 777181643Skmacy 778181643SkmacyDa notare che la sincronizzazione **non** si sostituisce al conteggio dei 779181643Skmacyriferimenti. La sincronizzazione ha lo scopo di mantenere le strutture 780181643Skmacydati coerenti, mentre il conteggio dei riferimenti �� una tecnica di gestione 781181643Skmacydella memoria. Solitamente servono entrambe le cose, e non vanno confuse fra 782181643Skmacydi loro. 783181643Skmacy 784181643SkmacyQuando si hanno diverse classi di utenti, le strutture dati possono avere 785181643Skmacydue livelli di contatori di riferimenti. Il contatore di classe conta 786181643Skmacyil numero dei suoi utenti, e il contatore globale viene decrementato una 787181643Skmacysola volta quando il contatore di classe va a zero. 788181643Skmacy 789181643SkmacyUn esempio di questo tipo di conteggio dei riferimenti multi-livello pu�� 790181643Skmacyessere trovato nella gestore della memoria (``struct mm_sturct``: mm_user e 791181643Skmacymm_count), e nel codice dei filesystem (``struct super_block``: s_count e 792181643Skmacys_active). 793181643Skmacy 794181643SkmacyRicordatevi: se un altro thread pu�� trovare la vostra struttura dati, e non 795181643Skmacyavete un contatore di riferimenti per essa, quasi certamente avete un baco. 796181643Skmacy 797181643Skmacy12) Macro, enumerati e RTL 798181643Skmacy--------------------------- 799181643Skmacy 800181643SkmacyI nomi delle macro che definiscono delle costanti e le etichette degli 801181643Skmacyenumerati sono scritte in maiuscolo. 802181643Skmacy 803181643Skmacy.. code-block:: c 804181643Skmacy 805181643Skmacy #define CONSTANT 0x12345 806181643Skmacy 807181643SkmacyGli enumerati sono da preferire quando si definiscono molte costanti correlate. 808181643Skmacy 809181643SkmacyI nomi delle macro in MAIUSCOLO sono preferibili ma le macro che assomigliano 810181643Skmacya delle funzioni possono essere scritte in minuscolo. 811181643Skmacy 812181643SkmacyGeneralmente, le funzioni inline sono preferibili rispetto alle macro che 813181643Skmacysembrano funzioni. 814181643Skmacy 815181643SkmacyLe macro che contengono pi�� istruzioni dovrebbero essere sempre chiuse in un 816181643Skmacyblocco do - while: 817181643Skmacy 818181643Skmacy.. code-block:: c 819181643Skmacy 820181643Skmacy #define macrofun(a, b, c) \ 821181643Skmacy do { \ 822181643Skmacy if (a == 5) \ 823181643Skmacy do_this(b, c); \ 824181643Skmacy } while (0) 825181643Skmacy 826181643SkmacyCose da evitare quando si usano le macro: 827181643Skmacy 828181643Skmacy1) le macro che hanno effetti sul flusso del codice: 829181643Skmacy 830181643Skmacy.. code-block:: c 831181643Skmacy 832181643Skmacy #define FOO(x) \ 833181643Skmacy do { \ 834181643Skmacy if (blah(x) < 0) \ 835181643Skmacy return -EBUGGERED; \ 836181643Skmacy } while (0) 837181643Skmacy 838181643Skmacysono **proprio** una pessima idea. Sembra una chiamata a funzione ma termina 839181643Skmacyla funzione chiamante; non cercate di rompere il decodificatore interno di 840181643Skmacychi legge il codice. 841181643Skmacy 842181643Skmacy2) le macro che dipendono dall'uso di una variabile locale con un nome magico: 843181643Skmacy 844181643Skmacy.. code-block:: c 845181643Skmacy 846181643Skmacy #define FOO(val) bar(index, val) 847181643Skmacy 848181643Skmacypotrebbe sembrare una bella cosa, ma �� dannatamente confusionario quando uno 849181643Skmacylegge il codice e potrebbe romperlo con una cambiamento che sembra innocente. 850181643Skmacy 851181643Skmacy3) le macro con argomenti che sono utilizzati come l-values; questo potrebbe 852181643Skmacyritorcervisi contro se qualcuno, per esempio, trasforma FOO in una funzione 853181643Skmacyinline. 854181643Skmacy 855181643Skmacy4) dimenticatevi delle precedenze: le macro che definiscono espressioni devono 856181643Skmacyessere racchiuse fra parentesi. State attenti a problemi simili con le macro 857181643Skmacyparametrizzate. 858181643Skmacy 859181643Skmacy.. code-block:: c 860181643Skmacy 861181643Skmacy #define CONSTANT 0x4000 862181643Skmacy #define CONSTEXP (CONSTANT | 3) 863181643Skmacy 864181643Skmacy5) collisione nello spazio dei nomi quando si definisce una variabile locale in 865181643Skmacyuna macro che sembra una funzione: 866181643Skmacy 867181643Skmacy.. code-block:: c 868181643Skmacy 869181643Skmacy #define FOO(x) \ 870181643Skmacy ({ \ 871181643Skmacy typeof(x) ret; \ 872181643Skmacy ret = calc_ret(x); \ 873181643Skmacy (ret); \ 874181643Skmacy }) 875181643Skmacy 876181643Skmacyret �� un nome comune per una variabile locale - __foo_ret difficilmente 877181643Skmacyandr�� in conflitto con una variabile gi�� esistente. 878181643Skmacy 879181643SkmacyIl manuale di cpp si occupa esaustivamente delle macro. Il manuale di sviluppo 880181643Skmacydi gcc copre anche l'RTL che viene usato frequentemente nel kernel per il 881181643Skmacylinguaggio assembler. 882181643Skmacy 883181643Skmacy13) Visualizzare i messaggi del kernel 884181643Skmacy-------------------------------------- 885181643Skmacy 886181643SkmacyAgli sviluppatori del kernel piace essere visti come dotti. Tenete un occhio 887181643Skmacydi riguardo per l'ortografia e farete una belle figura. In inglese, evitate 888181643Skmacyl'uso incorretto di abbreviazioni come ``dont``: usate ``do not`` oppure 889181643Skmacy``don't``. Scrivete messaggi concisi, chiari, e inequivocabili. 890181643Skmacy 891181643SkmacyI messaggi del kernel non devono terminare con un punto fermo. 892181643Skmacy 893181643SkmacyScrivere i numeri fra parentesi (%d) non migliora alcunch�� e per questo 894181643Skmacydovrebbero essere evitati. 895181643Skmacy 896181643SkmacyCi sono alcune macro per la diagnostica in <linux/dev_printk.h> che dovreste 897181643Skmacyusare per assicurarvi che i messaggi vengano associati correttamente ai 898181643Skmacydispositivi e ai driver, e che siano etichettati correttamente: dev_err(), 899181643Skmacydev_warn(), dev_info(), e cos�� via. Per messaggi che non sono associati ad 900181643Skmacyalcun dispositivo, <linux/printk.h> definisce pr_info(), pr_warn(), pr_err(), 901181643Skmacyeccetera. 902181643Skmacy 903181643SkmacyTirar fuori un buon messaggio di debug pu�� essere una vera sfida; e quando 904181643Skmacyl'avete pu�� essere d'enorme aiuto per risolvere problemi da remoto. 905181643SkmacyTuttavia, i messaggi di debug sono gestiti differentemente rispetto agli 906181643Skmacyaltri. Le funzioni pr_XXX() stampano incondizionatamente ma pr_debug() no; 907181643Skmacyessa non viene compilata nella configurazione predefinita, a meno che 908181643SkmacyDEBUG o CONFIG_DYNAMIC_DEBUG non vengono impostati. Questo vale anche per 909181643Skmacydev_dbg() e in aggiunta VERBOSE_DEBUG per aggiungere i messaggi dev_vdbg(). 910181643Skmacy 911181643SkmacyMolti sottosistemi hanno delle opzioni di debug in Kconfig che aggiungono 912181643Skmacy-DDEBUG nei corrispettivi Makefile, e in altri casi aggiungono #define DEBUG 913181643Skmacyin specifici file. Infine, quando un messaggio di debug dev'essere stampato 914181643Skmacyincondizionatamente, per esempio perch�� siete gi�� in una sezione di debug 915181643Skmacyracchiusa in #ifdef, potete usare printk(KERN_DEBUG ...). 916181643Skmacy 917181643Skmacy14) Assegnare memoria 918181643Skmacy--------------------- 919181643Skmacy 920181643SkmacyIl kernel fornisce i seguenti assegnatori ad uso generico: 921181643Skmacykmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc(), e vzalloc(). 922181643SkmacyPer maggiori informazioni, consultate la documentazione dell'API: 923181643Skmacy:ref:`Documentation/translations/it_IT/core-api/memory-allocation.rst <it_memory_allocation>` 924181643Skmacy 925181643SkmacyIl modo preferito per passare la dimensione di una struttura �� il seguente: 926181643Skmacy 927181643Skmacy.. code-block:: c 928181643Skmacy 929181643Skmacy p = kmalloc(sizeof(*p), ...); 930181643Skmacy 931181643SkmacyLa forma alternativa, dove il nome della struttura viene scritto interamente, 932181643Skmacypeggiora la leggibilit�� e introduce possibili bachi quando il tipo di 933181643Skmacypuntatore cambia tipo ma il corrispondente sizeof non viene aggiornato. 934181643Skmacy 935181643SkmacyIl valore di ritorno �� un puntatore void, effettuare un cast su di esso �� 936181643Skmacyridondante. La conversione fra un puntatore void e un qualsiasi altro tipo 937181643Skmacydi puntatore �� garantito dal linguaggio di programmazione C. 938181643Skmacy 939181643SkmacyIl modo preferito per assegnare un vettore �� il seguente: 940181643Skmacy 941181643Skmacy.. code-block:: c 942181643Skmacy 943181643Skmacy p = kmalloc_array(n, sizeof(...), ...); 944181643Skmacy 945181643SkmacyIl modo preferito per assegnare un vettore a zero �� il seguente: 946181643Skmacy 947181643Skmacy.. code-block:: c 948181643Skmacy 949181643Skmacy p = kcalloc(n, sizeof(...), ...); 950181643Skmacy 951181643SkmacyEntrambe verificano la condizione di overflow per la dimensione 952181643Skmacyd'assegnamento n * sizeof(...), se accade ritorneranno NULL. 953181643Skmacy 954181643SkmacyQuesti allocatori generici producono uno *stack dump* in caso di fallimento 955181643Skmacya meno che non venga esplicitamente specificato __GFP_NOWARN. Quindi, nella 956181643Skmacymaggior parte dei casi, �� inutile stampare messaggi aggiuntivi quando uno di 957181643Skmacyquesti allocatori ritornano un puntatore NULL. 958181643Skmacy 959181643Skmacy15) Il morbo inline 960181643Skmacy------------------- 961181643Skmacy 962181643SkmacySembra che ci sia la percezione errata che gcc abbia una qualche magica 963181643Skmacyopzione "rendimi pi�� veloce" chiamata ``inline``. In alcuni casi l'uso di 964181643Skmacyinline �� appropriato (per esempio in sostituzione delle macro, vedi 965181643Skmacycapitolo 12), ma molto spesso non lo ��. L'uso abbondante della parola chiave 966181643Skmacyinline porta ad avere un kernel pi�� grande, che si traduce in un sistema nel 967181643Skmacysuo complesso pi�� lento per via di una cache per le istruzioni della CPU pi�� 968181643Skmacygrande e poi semplicemente perch�� ci sar�� meno spazio disponibile per una 969181643Skmacypagina di cache. Pensateci un attimo; una fallimento nella cache causa una 970181643Skmacyricerca su disco che pu�� tranquillamente richiedere 5 millisecondi. Ci sono 971181643SkmacyTANTI cicli di CPU che potrebbero essere usati in questi 5 millisecondi. 972181643Skmacy 973181643SkmacySpesso le persone dicono che aggiungere inline a delle funzioni dichiarate 974181643Skmacystatic e utilizzare una sola volta �� sempre una scelta vincente perch�� non 975181643Skmacyci sono altri compromessi. Questo �� tecnicamente vero ma gcc �� in grado di 976181643Skmacytrasformare automaticamente queste funzioni in inline; i problemi di 977181643Skmacymanutenzione del codice per rimuovere gli inline quando compare un secondo 978181643Skmacyutente surclassano il potenziale vantaggio nel suggerire a gcc di fare una 979181643Skmacycosa che avrebbe fatto comunque. 980181643Skmacy 981181643Skmacy16) Nomi e valori di ritorno delle funzioni 982181643Skmacy------------------------------------------- 983181643Skmacy 984181643SkmacyLe funzioni possono ritornare diversi tipi di valori, e uno dei pi�� comuni 985181643Skmacy�� quel valore che indica se una funzione ha completato con successo o meno. 986181643SkmacyQuesto valore pu�� essere rappresentato come un codice di errore intero 987181643Skmacy(-Exxx = fallimento, 0 = successo) oppure un booleano di successo 988181643Skmacy(0 = fallimento, non-zero = successo). 989181643Skmacy 990181643SkmacyMischiare questi due tipi di rappresentazioni �� un terreno fertile per 991181643Skmacyi bachi pi�� insidiosi. Se il linguaggio C includesse una forte distinzione 992181643Skmacyfra gli interi e i booleani, allora il compilatore potrebbe trovare questi 993181643Skmacyerrori per conto nostro ... ma questo non c'��. Per evitare di imbattersi 994181643Skmacyin questo tipo di baco, seguite sempre la seguente convenzione:: 995181643Skmacy 996181643Skmacy Se il nome di una funzione �� un'azione o un comando imperativo, 997181643Skmacy essa dovrebbe ritornare un codice di errore intero. Se il nome 998181643Skmacy �� un predicato, la funzione dovrebbe ritornare un booleano di 999181643Skmacy "successo" 1000181643Skmacy 1001181643SkmacyPer esempio, ``add work`` �� un comando, e la funzione add_work() ritorna 0 1002181643Skmacyin caso di successo o -EBUSY in caso di fallimento. Allo stesso modo, 1003181643Skmacy``PCI device present`` �� un predicato, e la funzione pci_dev_present() ritorna 1004181643Skmacy1 se trova il dispositivo corrispondente con successo, altrimenti 0. 1005181643Skmacy 1006181643SkmacyTutte le funzioni esportate (EXPORT) devono rispettare questa convenzione, e 1007181643Skmacycos�� dovrebbero anche tutte le funzioni pubbliche. Le funzioni private 1008181643Skmacy(static) possono non seguire questa convenzione, ma �� comunque raccomandato 1009181643Skmacyche lo facciano. 1010181643Skmacy 1011181643SkmacyLe funzioni il cui valore di ritorno �� il risultato di una computazione, 1012181643Skmacypiuttosto che l'indicazione sul successo di tale computazione, non sono 1013181643Skmacysoggette a questa regola. Solitamente si indicano gli errori ritornando un 1014181643Skmacyqualche valore fuori dai limiti. Un tipico esempio �� quello delle funzioni 1015181643Skmacyche ritornano un puntatore; queste utilizzano NULL o ERR_PTR come meccanismo 1016181643Skmacydi notifica degli errori. 1017181643Skmacy 1018181643Skmacy17) L'uso di bool 1019181643Skmacy----------------- 1020181643Skmacy 1021181643SkmacyNel kernel Linux il tipo bool deriva dal tipo _Bool dello standard C99. 1022181643SkmacyUn valore bool pu�� assumere solo i valori 0 o 1, e implicitamente o 1023181643Skmacyesplicitamente la conversione a bool converte i valori in vero (*true*) o 1024181643Skmacyfalso (*false*). Quando si usa un tipo bool il costrutto !! non sar�� pi�� 1025181643Skmacynecessario, e questo va ad eliminare una certa serie di bachi. 1026181643Skmacy 1027181643SkmacyQuando si usano i valori booleani, dovreste utilizzare le definizioni di true 1028181643Skmacye false al posto dei valori 1 e 0. 1029181643Skmacy 1030181643SkmacyPer il valore di ritorno delle funzioni e per le variabili sullo stack, l'uso 1031181643Skmacydel tipo bool �� sempre appropriato. L'uso di bool viene incoraggiato per 1032181643Skmacymigliorare la leggibilit�� e spesso �� molto meglio di 'int' nella gestione di 1033181643Skmacyvalori booleani. 1034181643Skmacy 1035181643SkmacyNon usate bool se per voi sono importanti l'ordine delle righe di cache o 1036181643Skmacyla loro dimensione; la dimensione e l'allineamento cambia a seconda 1037181643Skmacydell'architettura per la quale �� stato compilato. Le strutture che sono state 1038181643Skmacyottimizzate per l'allineamento o la dimensione non dovrebbero usare bool. 1039181643Skmacy 1040181643SkmacySe una struttura ha molti valori true/false, considerate l'idea di raggrupparli 1041181643Skmacyin un intero usando campi da 1 bit, oppure usate un tipo dalla larghezza fissa, 1042181643Skmacycome u8. 1043181643Skmacy 1044181643SkmacyCome per gli argomenti delle funzioni, molti valori true/false possono essere 1045181643Skmacyraggruppati in un singolo argomento a bit denominato 'flags'; spesso 'flags' �� 1046181643Skmacyun'alternativa molto pi�� leggibile se si hanno valori costanti per true/false. 1047181643Skmacy 1048181643SkmacyDetto ci��, un uso parsimonioso di bool nelle strutture dati e negli argomenti 1049181643Skmacypu�� migliorare la leggibilit��. 1050181643Skmacy 1051181643Skmacy18) Non reinventate le macro del kernel 1052181643Skmacy--------------------------------------- 1053181643Skmacy 1054181643SkmacyIl file di intestazione include/linux/kernel.h contiene un certo numero 1055181643Skmacydi macro che dovreste usare piuttosto che implementarne una qualche variante. 1056181643SkmacyPer esempio, se dovete calcolare la lunghezza di un vettore, sfruttate la 1057181643Skmacymacro: 1058181643Skmacy 1059181643Skmacy.. code-block:: c 1060181643Skmacy 1061181643Skmacy #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 1062181643Skmacy 1063181643SkmacyAnalogamente, se dovete calcolare la dimensione di un qualche campo di una 1064181643Skmacystruttura, usate 1065181643Skmacy 1066181643Skmacy.. code-block:: c 1067181643Skmacy 1068181643Skmacy #define sizeof_field(t, f) (sizeof(((t*)0)->f)) 1069181643Skmacy 1070181643SkmacyCi sono anche le macro min() e max() che, se vi serve, effettuano un controllo 1071181643Skmacyrigido sui tipi. Sentitevi liberi di leggere attentamente questo file 1072181643Skmacyd'intestazione per scoprire cos'altro �� stato definito che non dovreste 1073181643Skmacyreinventare nel vostro codice. 1074181643Skmacy 1075181643Skmacy19) Linee di configurazione degli editor e altre schifezze 1076181643Skmacy----------------------------------------------------------- 1077181643Skmacy 1078181643SkmacyAlcuni editor possono interpretare dei parametri di configurazione integrati 1079181643Skmacynei file sorgenti e indicati con dai marcatori speciali. Per esempio, emacs 1080181643Skmacyinterpreta le linee marcate nel seguente modo: 1081181643Skmacy 1082181643Skmacy.. code-block:: c 1083181643Skmacy 1084181643Skmacy -*- mode: c -*- 1085181643Skmacy 1086181643SkmacyO come queste: 1087181643Skmacy 1088181643Skmacy.. code-block:: c 1089181643Skmacy 1090181643Skmacy /* 1091181643Skmacy Local Variables: 1092181643Skmacy compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c" 1093181643Skmacy End: 1094181643Skmacy */ 1095181643Skmacy 1096181643SkmacyVim interpreta i marcatori come questi: 1097181643Skmacy 1098181643Skmacy.. code-block:: c 1099181643Skmacy 1100181643Skmacy /* vim:set sw=8 noet */ 1101181643Skmacy 1102181643SkmacyNon includete nessuna di queste cose nei file sorgenti. Le persone hanno le 1103181643Skmacyproprie configurazioni personali per l'editor, e i vostri sorgenti non 1104181643Skmacydovrebbero sovrascrivergliele. Questo vale anche per i marcatori 1105181643Skmacyd'indentazione e di modalit�� d'uso. Le persone potrebbero aver configurato una 1106181643Skmacymodalit�� su misura, oppure potrebbero avere qualche altra magia per far 1107181643Skmacyfunzionare bene l'indentazione. 1108181643Skmacy 1109181643Skmacy20) Inline assembly 1110181643Skmacy------------------- 1111181643Skmacy 1112181643SkmacyNel codice specifico per un'architettura, potreste aver bisogno di codice 1113181643Skmacy*inline assembly* per interfacciarvi col processore o con una funzionalit�� 1114181643Skmacyspecifica della piattaforma. Non esitate a farlo quando �� necessario. 1115181643SkmacyComunque, non usatele gratuitamente quando il C pu�� fare la stessa cosa. 1116181643SkmacyPotete e dovreste punzecchiare l'hardware in C quando �� possibile. 1117181643Skmacy 1118181643SkmacyConsiderate la scrittura di una semplice funzione che racchiude pezzi comuni 1119181643Skmacydi codice assembler piuttosto che continuare a riscrivere delle piccole 1120181643Skmacyvarianti. Ricordatevi che l' *inline assembly* pu�� utilizzare i parametri C. 1121181643Skmacy 1122181643SkmacyIl codice assembler pi�� corposo e non banale dovrebbe andare nei file .S, 1123181643Skmacycoi rispettivi prototipi C definiti nei file d'intestazione. I prototipi C 1124181643Skmacyper le funzioni assembler dovrebbero usare ``asmlinkage``. 1125181643Skmacy 1126181643SkmacyPotreste aver bisogno di marcare il vostro codice asm come volatile al fine 1127181643Skmacyd'evitare che GCC lo rimuova quando pensa che non ci siano effetti collaterali. 1128181643SkmacyNon c'�� sempre bisogno di farlo, e farlo quando non serve limita le 1129181643Skmacyottimizzazioni. 1130181643Skmacy 1131181643SkmacyQuando scrivete una singola espressione *inline assembly* contenente pi�� 1132181643Skmacyistruzioni, mettete ognuna di queste istruzioni in una stringa e riga diversa; 1133181643Skmacyad eccezione dell'ultima stringa/istruzione, ognuna deve terminare con ``\n\t`` 1134181643Skmacyal fine di allineare correttamente l'assembler che verr�� generato: 1135181643Skmacy 1136181643Skmacy.. code-block:: c 1137181643Skmacy 1138181643Skmacy asm ("magic %reg1, #42\n\t" 1139181643Skmacy "more_magic %reg2, %reg3" 1140181643Skmacy : /* outputs */ : /* inputs */ : /* clobbers */); 1141181643Skmacy 1142181643Skmacy21) Compilazione sotto condizione 1143181643Skmacy--------------------------------- 1144181643Skmacy 1145181643SkmacyOvunque sia possibile, non usate le direttive condizionali del preprocessore 1146181643Skmacy(#if, #ifdef) nei file .c; farlo rende il codice difficile da leggere e da 1147181643Skmacyseguire. Invece, usate queste direttive nei file d'intestazione per definire 1148181643Skmacyle funzioni usate nei file .c, fornendo i relativi stub nel caso #else, 1149181643Skmacye quindi chiamate queste funzioni senza condizioni di preprocessore. Il 1150181643Skmacycompilatore non produrr�� alcun codice per le funzioni stub, produrr�� gli 1151181643Skmacystessi risultati, e la logica rimarr�� semplice da seguire. 1152181643Skmacy 1153181643Skmacy�� preferibile non compilare intere funzioni piuttosto che porzioni d'esse o 1154181643Skmacyporzioni d'espressioni. Piuttosto che mettere una ifdef in un'espressione, 1155181643Skmacyfattorizzate parte dell'espressione, o interamente, in funzioni e applicate 1156181643Skmacyla direttiva condizionale su di esse. 1157181643Skmacy 1158181643SkmacySe avete una variabile o funzione che potrebbe non essere usata in alcune 1159181643Skmacyconfigurazioni, e quindi il compilatore potrebbe avvisarvi circa la definizione 1160181643Skmacyinutilizzata, marcate questa definizione come __maybe_unused piuttosto che 1161181643Skmacyracchiuderla in una direttiva condizionale del preprocessore. (Comunque, 1162181643Skmacyse una variabile o funzione �� *sempre* inutilizzata, rimuovetela). 1163181643Skmacy 1164181643SkmacyNel codice, dov'�� possibile, usate la macro IS_ENABLED per convertire i 1165181643Skmacysimboli Kconfig in espressioni booleane C, e quindi usatela nelle classiche 1166181643Skmacycondizioni C: 1167181643Skmacy 1168181643Skmacy.. code-block:: c 1169181643Skmacy 1170181643Skmacy if (IS_ENABLED(CONFIG_SOMETHING)) { 1171181643Skmacy ... 1172181643Skmacy } 1173181643Skmacy 1174181643SkmacyIl compilatore valuter�� la condizione come costante (constant-fold), e quindi 1175181643Skmacyincluder�� o escluder�� il blocco di codice come se fosse in un #ifdef, quindi 1176181643Skmacynon ne aumenter�� il tempo di esecuzione. Tuttavia, questo permette al 1177181643Skmacycompilatore C di vedere il codice nel blocco condizionale e verificarne la 1178181643Skmacycorrettezza (sintassi, tipi, riferimenti ai simboli, eccetera). Quindi 1179181643Skmacydovete comunque utilizzare #ifdef se il codice nel blocco condizionale esiste 1180181643Skmacysolo quando la condizione �� soddisfatta. 1181181643Skmacy 1182181643SkmacyAlla fine di un blocco corposo di #if o #ifdef (pi�� di alcune linee), 1183181643Skmacymettete un commento sulla stessa riga di #endif, annotando la condizione 1184181643Skmacyche termina. Per esempio: 1185181643Skmacy 1186181643Skmacy.. code-block:: c 1187181643Skmacy 1188181643Skmacy #ifdef CONFIG_SOMETHING 1189181643Skmacy ... 1190181643Skmacy #endif /* CONFIG_SOMETHING */ 1191181643Skmacy 1192181643SkmacyAppendice I) riferimenti 1193181643Skmacy------------------------ 1194181643Skmacy 1195181643SkmacyThe C Programming Language, Second Edition 1196181643Skmacyby Brian W. Kernighan and Dennis M. Ritchie. 1197181643SkmacyPrentice Hall, Inc., 1988. 1198181643SkmacyISBN 0-13-110362-8 (paperback), 0-13-110370-9 (hardback). 1199181643Skmacy 1200181643SkmacyThe Practice of Programming 1201181643Skmacyby Brian W. Kernighan and Rob Pike. 1202181643SkmacyAddison-Wesley, Inc., 1999. 1203181643SkmacyISBN 0-201-61586-X. 1204181643Skmacy 1205181643SkmacyManuali GNU - nei casi in cui sono compatibili con K&R e questo documento - 1206181643Skmacyper indent, cpp, gcc e i suoi dettagli interni, tutto disponibile qui 1207181643Skmacyhttps://www.gnu.org/manual/ 1208181643Skmacy 1209181643SkmacyWG14 �� il gruppo internazionale di standardizzazione per il linguaggio C, 1210181643SkmacyURL: https://www.open-std.org/JTC1/SC22/WG14/ 1211181643Skmacy 1212181643SkmacyKernel CodingStyle, by greg@kroah.com at OLS 2002: 1213181643Skmacyhttp://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/ 1214181643Skmacy