18c2ecf20Sopenharmony_ci.. include:: ../disclaimer-ita.rst 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci.. note:: Per leggere la documentazione originale in inglese: 48c2ecf20Sopenharmony_ci :ref:`Documentation/kernel-hacking/hacking.rst <kernel_hacking_hack>` 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci:Original: :ref:`Documentation/kernel-hacking/hacking.rst <kernel_hacking_hack>` 78c2ecf20Sopenharmony_ci:Translator: Federico Vaga <federico.vaga@vaga.pv.it> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci.. _it_kernel_hacking_hack: 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci================================================= 128c2ecf20Sopenharmony_ciL'inaffidabile guida all'hacking del kernel Linux 138c2ecf20Sopenharmony_ci================================================= 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci:Author: Rusty Russell 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ciIntroduzione 188c2ecf20Sopenharmony_ci============ 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ciBenvenuto, gentile lettore, alla notevole ed inaffidabile guida all'hacking 218c2ecf20Sopenharmony_cidel kernel Linux ad opera di Rusty. Questo documento descrive le procedure 228c2ecf20Sopenharmony_cipiù usate ed i concetti necessari per scrivere codice per il kernel: lo scopo 238c2ecf20Sopenharmony_ciè di fornire ai programmatori C più esperti un manuale di base per sviluppo. 248c2ecf20Sopenharmony_ciEviterò dettagli implementativi: per questo abbiamo il codice, 258c2ecf20Sopenharmony_cied ignorerò intere parti di alcune procedure. 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ciPrima di leggere questa guida, sappiate che non ho mai voluto scriverla, 288c2ecf20Sopenharmony_ciessendo esageratamente sotto qualificato, ma ho sempre voluto leggere 298c2ecf20Sopenharmony_ciqualcosa di simile, e quindi questa era l'unica via. Spero che possa 308c2ecf20Sopenharmony_cicrescere e diventare un compendio di buone pratiche, punti di partenza 318c2ecf20Sopenharmony_cie generiche informazioni. 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ciGli attori 348c2ecf20Sopenharmony_ci========== 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ciIn qualsiasi momento ognuna delle CPU di un sistema può essere: 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci- non associata ad alcun processo, servendo un'interruzione hardware; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci- non associata ad alcun processo, servendo un softirq o tasklet; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci- in esecuzione nello spazio kernel, associata ad un processo 438c2ecf20Sopenharmony_ci (contesto utente); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci- in esecuzione di un processo nello spazio utente; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ciEsiste un ordine fra questi casi. Gli ultimi due possono avvicendarsi (preempt) 488c2ecf20Sopenharmony_cil'un l'altro, ma a parte questo esiste una gerarchia rigida: ognuno di questi 498c2ecf20Sopenharmony_cipuò avvicendarsi solo ad uno di quelli sottostanti. Per esempio, mentre un 508c2ecf20Sopenharmony_cisoftirq è in esecuzione su d'una CPU, nessun altro softirq può avvicendarsi 518c2ecf20Sopenharmony_cinell'esecuzione, ma un'interruzione hardware può. Ciò nonostante, le altre CPU 528c2ecf20Sopenharmony_cidel sistema operano indipendentemente. 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ciPiù avanti vedremo alcuni modi in cui dal contesto utente è possibile bloccare 558c2ecf20Sopenharmony_cile interruzioni, così da impedirne davvero il diritto di prelazione. 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ciContesto utente 588c2ecf20Sopenharmony_ci--------------- 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ciCi si trova nel contesto utente quando si arriva da una chiamata di sistema 618c2ecf20Sopenharmony_ciod altre eccezioni: come nello spazio utente, altre procedure più importanti, 628c2ecf20Sopenharmony_cio le interruzioni, possono far valere il proprio diritto di prelazione sul 638c2ecf20Sopenharmony_civostro processo. Potete sospendere l'esecuzione chiamando :c:func:`schedule()`. 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci.. note:: 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci Si è sempre in contesto utente quando un modulo viene caricato o rimosso, 688c2ecf20Sopenharmony_ci e durante le operazioni nello strato dei dispositivi a blocchi 698c2ecf20Sopenharmony_ci (*block layer*). 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ciNel contesto utente, il puntatore ``current`` (il quale indica il processo al 728c2ecf20Sopenharmony_cimomento in esecuzione) è valido, e :c:func:`in_interrupt()` 738c2ecf20Sopenharmony_ci(``include/linux/preempt.h``) è falsa. 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci.. warning:: 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci Attenzione che se avete la prelazione o i softirq disabilitati (vedere 788c2ecf20Sopenharmony_ci di seguito), :c:func:`in_interrupt()` ritornerà un falso positivo. 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ciInterruzioni hardware (Hard IRQs) 818c2ecf20Sopenharmony_ci--------------------------------- 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ciTemporizzatori, schede di rete e tastiere sono esempi di vero hardware 848c2ecf20Sopenharmony_ciche possono produrre interruzioni in un qualsiasi momento. Il kernel esegue 858c2ecf20Sopenharmony_cii gestori d'interruzione che prestano un servizio all'hardware. Il kernel 868c2ecf20Sopenharmony_cigarantisce che questi gestori non vengano mai interrotti: se una stessa 878c2ecf20Sopenharmony_ciinterruzione arriva, questa verrà accodata (o scartata). 888c2ecf20Sopenharmony_ciDato che durante la loro esecuzione le interruzioni vengono disabilitate, 898c2ecf20Sopenharmony_cii gestori d'interruzioni devono essere veloci: spesso si limitano 908c2ecf20Sopenharmony_ciesclusivamente a notificare la presa in carico dell'interruzione, 918c2ecf20Sopenharmony_ciprogrammare una 'interruzione software' per l'esecuzione e quindi terminare. 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ciPotete dire d'essere in una interruzione hardware perché :c:func:`in_irq()` 948c2ecf20Sopenharmony_ciritorna vero. 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci.. warning:: 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci Attenzione, questa ritornerà un falso positivo se le interruzioni 998c2ecf20Sopenharmony_ci sono disabilitate (vedere di seguito). 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ciContesto d'interruzione software: softirq e tasklet 1028c2ecf20Sopenharmony_ci--------------------------------------------------- 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ciQuando una chiamata di sistema sta per tornare allo spazio utente, 1058c2ecf20Sopenharmony_cioppure un gestore d'interruzioni termina, qualsiasi 'interruzione software' 1068c2ecf20Sopenharmony_cimarcata come pendente (solitamente da un'interruzione hardware) viene 1078c2ecf20Sopenharmony_cieseguita (``kernel/softirq.c``). 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ciLa maggior parte del lavoro utile alla gestione di un'interruzione avviene qui. 1108c2ecf20Sopenharmony_ciAll'inizio della transizione ai sistemi multiprocessore, c'erano solo i 1118c2ecf20Sopenharmony_cicosiddetti 'bottom half' (BH), i quali non traevano alcun vantaggio da questi 1128c2ecf20Sopenharmony_cisistemi. Non appena abbandonammo i computer raffazzonati con fiammiferi e 1138c2ecf20Sopenharmony_cicicche, abbandonammo anche questa limitazione e migrammo alle interruzioni 1148c2ecf20Sopenharmony_cisoftware 'softirqs'. 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ciIl file ``include/linux/interrupt.h`` elenca i differenti tipi di 'softirq'. 1178c2ecf20Sopenharmony_ciUn tipo di softirq molto importante è il timer (``include/linux/timer.h``): 1188c2ecf20Sopenharmony_cipotete programmarlo per far si che esegua funzioni dopo un determinato 1198c2ecf20Sopenharmony_ciperiodo di tempo. 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ciDato che i softirq possono essere eseguiti simultaneamente su più di un 1228c2ecf20Sopenharmony_ciprocessore, spesso diventa estenuante l'averci a che fare. Per questa ragione, 1238c2ecf20Sopenharmony_cii tasklet (``include/linux/interrupt.h``) vengo usati più di frequente: 1248c2ecf20Sopenharmony_cipossono essere registrati dinamicamente (il che significa che potete averne 1258c2ecf20Sopenharmony_ciquanti ne volete), e garantiscono che un qualsiasi tasklet verrà eseguito 1268c2ecf20Sopenharmony_cisolo su un processore alla volta, sebbene diversi tasklet possono essere 1278c2ecf20Sopenharmony_cieseguiti simultaneamente. 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci.. warning:: 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci Il nome 'tasklet' è ingannevole: non hanno niente a che fare 1328c2ecf20Sopenharmony_ci con i 'processi' ('tasks'), e probabilmente hanno più a che vedere 1338c2ecf20Sopenharmony_ci con qualche pessima vodka che Alexey Kuznetsov si fece a quel tempo. 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ciPotete determinate se siete in un softirq (o tasklet) utilizzando la 1368c2ecf20Sopenharmony_cimacro :c:func:`in_softirq()` (``include/linux/preempt.h``). 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci.. warning:: 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci State attenti che questa macro ritornerà un falso positivo 1418c2ecf20Sopenharmony_ci se :ref:`botton half lock <it_local_bh_disable>` è bloccato. 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ciAlcune regole basilari 1448c2ecf20Sopenharmony_ci====================== 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ciNessuna protezione della memoria 1478c2ecf20Sopenharmony_ci Se corrompete la memoria, che sia in contesto utente o d'interruzione, 1488c2ecf20Sopenharmony_ci la macchina si pianterà. Siete sicuri che quello che volete fare 1498c2ecf20Sopenharmony_ci non possa essere fatto nello spazio utente? 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ciNessun numero in virgola mobile o MMX 1528c2ecf20Sopenharmony_ci Il contesto della FPU non è salvato; anche se siete in contesto utente 1538c2ecf20Sopenharmony_ci lo stato dell'FPU probabilmente non corrisponde a quello del processo 1548c2ecf20Sopenharmony_ci corrente: vi incasinerete con lo stato di qualche altro processo. Se 1558c2ecf20Sopenharmony_ci volete davvero usare la virgola mobile, allora dovrete salvare e recuperare 1568c2ecf20Sopenharmony_ci lo stato dell'FPU (ed evitare cambi di contesto). Generalmente è una 1578c2ecf20Sopenharmony_ci cattiva idea; usate l'aritmetica a virgola fissa. 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ciUn limite rigido dello stack 1608c2ecf20Sopenharmony_ci A seconda della configurazione del kernel lo stack è fra 3K e 6K per la 1618c2ecf20Sopenharmony_ci maggior parte delle architetture a 32-bit; è di 14K per la maggior 1628c2ecf20Sopenharmony_ci parte di quelle a 64-bit; e spesso è condiviso con le interruzioni, 1638c2ecf20Sopenharmony_ci per cui non si può usare. 1648c2ecf20Sopenharmony_ci Evitare profonde ricorsioni ad enormi array locali nello stack 1658c2ecf20Sopenharmony_ci (allocateli dinamicamente). 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ciIl kernel Linux è portabile 1688c2ecf20Sopenharmony_ci Quindi mantenetelo tale. Il vostro codice dovrebbe essere a 64-bit ed 1698c2ecf20Sopenharmony_ci indipendente dall'ordine dei byte (endianess) di un processore. Inoltre, 1708c2ecf20Sopenharmony_ci dovreste minimizzare il codice specifico per un processore; per esempio 1718c2ecf20Sopenharmony_ci il codice assembly dovrebbe essere incapsulato in modo pulito e minimizzato 1728c2ecf20Sopenharmony_ci per facilitarne la migrazione. Generalmente questo codice dovrebbe essere 1738c2ecf20Sopenharmony_ci limitato alla parte di kernel specifica per un'architettura. 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ciioctl: non scrivere nuove chiamate di sistema 1768c2ecf20Sopenharmony_ci============================================= 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ciUna chiamata di sistema, generalmente, è scritta così:: 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci asmlinkage long sys_mycall(int arg) 1818c2ecf20Sopenharmony_ci { 1828c2ecf20Sopenharmony_ci return 0; 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ciPrimo, nella maggior parte dei casi non volete creare nuove chiamate di 1868c2ecf20Sopenharmony_cisistema. 1878c2ecf20Sopenharmony_ciCreate un dispositivo a caratteri ed implementate l'appropriata chiamata ioctl. 1888c2ecf20Sopenharmony_ciQuesto meccanismo è molto più flessibile delle chiamate di sistema: esso non 1898c2ecf20Sopenharmony_cidev'essere dichiarato in tutte le architetture nei file 1908c2ecf20Sopenharmony_ci``include/asm/unistd.h`` e ``arch/kernel/entry.S``; inoltre, è improbabile 1918c2ecf20Sopenharmony_ciche questo venga accettato da Linus. 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ciSe tutto quello che il vostro codice fa è leggere o scrivere alcuni parametri, 1948c2ecf20Sopenharmony_ciconsiderate l'implementazione di un'interfaccia :c:func:`sysfs()`. 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ciAll'interno di una ioctl vi trovate nel contesto utente di un processo. Quando 1978c2ecf20Sopenharmony_ciavviene un errore dovete ritornare un valore negativo di errno (consultate 1988c2ecf20Sopenharmony_ci``include/uapi/asm-generic/errno-base.h``, 1998c2ecf20Sopenharmony_ci``include/uapi/asm-generic/errno.h`` e ``include/linux/errno.h``), altrimenti 2008c2ecf20Sopenharmony_ciritornate 0. 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ciDopo aver dormito dovreste verificare se ci sono stati dei segnali: il modo 2038c2ecf20Sopenharmony_ciUnix/Linux di gestire un segnale è di uscire temporaneamente dalla chiamata 2048c2ecf20Sopenharmony_cidi sistema con l'errore ``-ERESTARTSYS``. La chiamata di sistema ritornerà 2058c2ecf20Sopenharmony_cial contesto utente, eseguirà il gestore del segnale e poi la vostra chiamata 2068c2ecf20Sopenharmony_cidi sistema riprenderà (a meno che l'utente non l'abbia disabilitata). Quindi, 2078c2ecf20Sopenharmony_cidovreste essere pronti per continuare l'esecuzione, per esempio nel mezzo 2088c2ecf20Sopenharmony_cidella manipolazione di una struttura dati. 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci:: 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci if (signal_pending(current)) 2138c2ecf20Sopenharmony_ci return -ERESTARTSYS; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ciSe dovete eseguire dei calcoli molto lunghi: pensate allo spazio utente. 2168c2ecf20Sopenharmony_ciSe **davvero** volete farlo nel kernel ricordatevi di verificare periodicamente 2178c2ecf20Sopenharmony_cise dovete *lasciare* il processore (ricordatevi che, per ogni processore, c'è 2188c2ecf20Sopenharmony_ciun sistema multi-processo senza diritto di prelazione). 2198c2ecf20Sopenharmony_ciEsempio:: 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci cond_resched(); /* Will sleep */ 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ciUna breve nota sulla progettazione delle interfacce: il motto dei sistemi 2248c2ecf20Sopenharmony_ciUNIX è "fornite meccanismi e non politiche" 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ciLa ricetta per uno stallo 2278c2ecf20Sopenharmony_ci========================= 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ciNon è permesso invocare una procedura che potrebbe dormire, fanno eccezione 2308c2ecf20Sopenharmony_cii seguenti casi: 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci- Siete in un contesto utente. 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci- Non trattenete alcun spinlock. 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci- Avete abilitato le interruzioni (in realtà, Andy Kleen dice che 2378c2ecf20Sopenharmony_ci lo schedulatore le abiliterà per voi, ma probabilmente questo non è quello 2388c2ecf20Sopenharmony_ci che volete). 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ciDa tener presente che alcune funzioni potrebbero dormire implicitamente: 2418c2ecf20Sopenharmony_cile più comuni sono quelle per l'accesso allo spazio utente (\*_user) e 2428c2ecf20Sopenharmony_ciquelle per l'allocazione della memoria senza l'opzione ``GFP_ATOMIC`` 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ciDovreste sempre compilare il kernel con l'opzione ``CONFIG_DEBUG_ATOMIC_SLEEP`` 2458c2ecf20Sopenharmony_ciattiva, questa vi avviserà se infrangete una di queste regole. 2468c2ecf20Sopenharmony_ciSe **infrangete** le regole, allora potreste bloccare il vostro scatolotto. 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ciVeramente. 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ciAlcune delle procedure più comuni 2518c2ecf20Sopenharmony_ci================================= 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci:c:func:`printk()` 2548c2ecf20Sopenharmony_ci------------------ 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ciDefinita in ``include/linux/printk.h`` 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci:c:func:`printk()` fornisce messaggi alla console, dmesg, e al demone syslog. 2598c2ecf20Sopenharmony_ciEssa è utile per il debugging o per la notifica di errori; può essere 2608c2ecf20Sopenharmony_ciutilizzata anche all'interno del contesto d'interruzione, ma usatela con 2618c2ecf20Sopenharmony_cicautela: una macchina che ha la propria console inondata da messaggi diventa 2628c2ecf20Sopenharmony_ciinutilizzabile. La funzione utilizza un formato stringa quasi compatibile con 2638c2ecf20Sopenharmony_cila printf ANSI C, e la concatenazione di una stringa C come primo argomento 2648c2ecf20Sopenharmony_ciper indicare la "priorità":: 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci printk(KERN_INFO "i = %u\n", i); 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ciConsultate ``include/linux/kern_levels.h`` per gli altri valori ``KERN_``; 2698c2ecf20Sopenharmony_ciquesti sono interpretati da syslog come livelli. Un caso speciale: 2708c2ecf20Sopenharmony_ciper stampare un indirizzo IP usate:: 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci __be32 ipaddress; 2738c2ecf20Sopenharmony_ci printk(KERN_INFO "my ip: %pI4\n", &ipaddress); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci:c:func:`printk()` utilizza un buffer interno di 1K e non s'accorge di 2778c2ecf20Sopenharmony_cieventuali sforamenti. Accertatevi che vi basti. 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci.. note:: 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci Saprete di essere un vero hacker del kernel quando inizierete a digitare 2828c2ecf20Sopenharmony_ci nei vostri programmi utenti le printf come se fossero printk :) 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci.. note:: 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci Un'altra nota a parte: la versione originale di Unix 6 aveva un commento 2878c2ecf20Sopenharmony_ci sopra alla funzione printf: "Printf non dovrebbe essere usata per il 2888c2ecf20Sopenharmony_ci chiacchiericcio". Dovreste seguire questo consiglio. 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci:c:func:`copy_to_user()` / :c:func:`copy_from_user()` / :c:func:`get_user()` / :c:func:`put_user()` 2918c2ecf20Sopenharmony_ci--------------------------------------------------------------------------------------------------- 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ciDefinite in ``include/linux/uaccess.h`` / ``asm/uaccess.h`` 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci**[DORMONO]** 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci:c:func:`put_user()` e :c:func:`get_user()` sono usate per ricevere ed 2988c2ecf20Sopenharmony_ciimpostare singoli valori (come int, char, o long) da e verso lo spazio utente. 2998c2ecf20Sopenharmony_ciUn puntatore nello spazio utente non dovrebbe mai essere dereferenziato: i dati 3008c2ecf20Sopenharmony_cidovrebbero essere copiati usando suddette procedure. Entrambe ritornano 3018c2ecf20Sopenharmony_ci``-EFAULT`` oppure 0. 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci:c:func:`copy_to_user()` e :c:func:`copy_from_user()` sono più generiche: 3048c2ecf20Sopenharmony_ciesse copiano una quantità arbitraria di dati da e verso lo spazio utente. 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci.. warning:: 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci Al contrario di:c:func:`put_user()` e :c:func:`get_user()`, queste 3098c2ecf20Sopenharmony_ci funzioni ritornano la quantità di dati copiati (0 è comunque un successo). 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci[Sì, questa stupida interfaccia mi imbarazza. La battaglia torna in auge anno 3128c2ecf20Sopenharmony_cidopo anno. --RR] 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ciLe funzioni potrebbero dormire implicitamente. Queste non dovrebbero mai essere 3158c2ecf20Sopenharmony_ciinvocate fuori dal contesto utente (non ha senso), con le interruzioni 3168c2ecf20Sopenharmony_cidisabilitate, o con uno spinlock trattenuto. 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci:c:func:`kmalloc()`/:c:func:`kfree()` 3198c2ecf20Sopenharmony_ci------------------------------------- 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ciDefinite in ``include/linux/slab.h`` 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci**[POTREBBERO DORMIRE: LEGGI SOTTO]** 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ciQueste procedure sono utilizzate per la richiesta dinamica di un puntatore ad 3268c2ecf20Sopenharmony_ciun pezzo di memoria allineato, esattamente come malloc e free nello spazio 3278c2ecf20Sopenharmony_ciutente, ma :c:func:`kmalloc()` ha un argomento aggiuntivo per indicare alcune 3288c2ecf20Sopenharmony_ciopzioni. Le opzioni più importanti sono: 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci``GFP_KERNEL`` 3318c2ecf20Sopenharmony_ci Potrebbe dormire per librarare della memoria. L'opzione fornisce il modo 3328c2ecf20Sopenharmony_ci più affidabile per allocare memoria, ma il suo uso è strettamente limitato 3338c2ecf20Sopenharmony_ci allo spazio utente. 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci``GFP_ATOMIC`` 3368c2ecf20Sopenharmony_ci Non dorme. Meno affidabile di ``GFP_KERNEL``, ma può essere usata in un 3378c2ecf20Sopenharmony_ci contesto d'interruzione. Dovreste avere **davvero** una buona strategia 3388c2ecf20Sopenharmony_ci per la gestione degli errori in caso di mancanza di memoria. 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci``GFP_DMA`` 3418c2ecf20Sopenharmony_ci Alloca memoria per il DMA sul bus ISA nello spazio d'indirizzamento 3428c2ecf20Sopenharmony_ci inferiore ai 16MB. Se non sapete cos'è allora non vi serve. 3438c2ecf20Sopenharmony_ci Molto inaffidabile. 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ciSe vedete un messaggio d'avviso per una funzione dormiente che viene chiamata 3468c2ecf20Sopenharmony_cida un contesto errato, allora probabilmente avete usato una funzione 3478c2ecf20Sopenharmony_cid'allocazione dormiente da un contesto d'interruzione senza ``GFP_ATOMIC``. 3488c2ecf20Sopenharmony_ciDovreste correggerlo. Sbrigatevi, non cincischiate. 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ciSe allocate almeno ``PAGE_SIZE``(``asm/page.h`` o ``asm/page_types.h``) byte, 3518c2ecf20Sopenharmony_ciconsiderate l'uso di :c:func:`__get_free_pages()` (``include/linux/gfp.h``). 3528c2ecf20Sopenharmony_ciAccetta un argomento che definisce l'ordine (0 per per la dimensione di una 3538c2ecf20Sopenharmony_cipagine, 1 per una doppia pagina, 2 per quattro pagine, eccetra) e le stesse 3548c2ecf20Sopenharmony_ciopzioni d'allocazione viste precedentemente. 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ciSe state allocando un numero di byte notevolemnte superiore ad una pagina 3578c2ecf20Sopenharmony_cipotete usare :c:func:`vmalloc()`. Essa allocherà memoria virtuale all'interno 3588c2ecf20Sopenharmony_cidello spazio kernel. Questo è un blocco di memoria fisica non contiguo, ma 3598c2ecf20Sopenharmony_cila MMU vi darà l'impressione che lo sia (quindi, sarà contiguo solo dal punto 3608c2ecf20Sopenharmony_cidi vista dei processori, non dal punto di vista dei driver dei dispositivi 3618c2ecf20Sopenharmony_ciesterni). 3628c2ecf20Sopenharmony_ciSe per qualche strana ragione avete davvero bisogno di una grossa quantità di 3638c2ecf20Sopenharmony_cimemoria fisica contigua, avete un problema: Linux non ha un buon supporto per 3648c2ecf20Sopenharmony_ciquesto caso d'uso perché, dopo un po' di tempo, la frammentazione della memoria 3658c2ecf20Sopenharmony_cirende l'operazione difficile. Il modo migliore per allocare un simile blocco 3668c2ecf20Sopenharmony_ciall'inizio dell'avvio del sistema è attraverso la procedura 3678c2ecf20Sopenharmony_ci:c:func:`alloc_bootmem()`. 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ciPrima di inventare la vostra cache per gli oggetti più usati, considerate 3708c2ecf20Sopenharmony_cil'uso di una cache slab disponibile in ``include/linux/slab.h``. 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci:c:func:`current()` 3738c2ecf20Sopenharmony_ci------------------- 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ciDefinita in ``include/asm/current.h`` 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ciQuesta variabile globale (in realtà una macro) contiene un puntatore alla 3788c2ecf20Sopenharmony_cistruttura del processo corrente, quindi è valido solo dal contesto utente. 3798c2ecf20Sopenharmony_ciPer esempio, quando un processo esegue una chiamata di sistema, questo 3808c2ecf20Sopenharmony_cipunterà alla struttura dati del processo chiamate. 3818c2ecf20Sopenharmony_ciNel contesto d'interruzione in suo valore **non è NULL**. 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci:c:func:`mdelay()`/:c:func:`udelay()` 3848c2ecf20Sopenharmony_ci------------------------------------- 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ciDefinite in ``include/asm/delay.h`` / ``include/linux/delay.h`` 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ciLe funzioni :c:func:`udelay()` e :c:func:`ndelay()` possono essere utilizzate 3898c2ecf20Sopenharmony_ciper brevi pause. Non usate grandi valori perché rischiate d'avere un 3908c2ecf20Sopenharmony_cioverflow - in questo contesto la funzione :c:func:`mdelay()` è utile, 3918c2ecf20Sopenharmony_cioppure considerate :c:func:`msleep()`. 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci:c:func:`cpu_to_be32()`/:c:func:`be32_to_cpu()`/:c:func:`cpu_to_le32()`/:c:func:`le32_to_cpu()` 3948c2ecf20Sopenharmony_ci----------------------------------------------------------------------------------------------- 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ciDefinite in ``include/asm/byteorder.h`` 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ciLa famiglia di funzioni :c:func:`cpu_to_be32()` (dove "32" può essere 3998c2ecf20Sopenharmony_cisostituito da 64 o 16, e "be" con "le") forniscono un modo generico 4008c2ecf20Sopenharmony_ciper fare conversioni sull'ordine dei byte (endianess): esse ritornano 4018c2ecf20Sopenharmony_ciil valore convertito. Tutte le varianti supportano anche il processo inverso: 4028c2ecf20Sopenharmony_ci:c:func:`be32_to_cpu()`, eccetera. 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ciQueste funzioni hanno principalmente due varianti: la variante per 4058c2ecf20Sopenharmony_cipuntatori, come :c:func:`cpu_to_be32p()`, che prende un puntatore 4068c2ecf20Sopenharmony_ciad un tipo, e ritorna il valore convertito. L'altra variante per 4078c2ecf20Sopenharmony_cila famiglia di conversioni "in-situ", come :c:func:`cpu_to_be32s()`, 4088c2ecf20Sopenharmony_ciche convertono il valore puntato da un puntatore, e ritornano void. 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci:c:func:`local_irq_save()`/:c:func:`local_irq_restore()` 4118c2ecf20Sopenharmony_ci-------------------------------------------------------- 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ciDefinite in ``include/linux/irqflags.h`` 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ciQueste funzioni abilitano e disabilitano le interruzioni hardware 4168c2ecf20Sopenharmony_cisul processore locale. Entrambe sono rientranti; esse salvano lo stato 4178c2ecf20Sopenharmony_ciprecedente nel proprio argomento ``unsigned long flags``. Se sapete 4188c2ecf20Sopenharmony_ciche le interruzioni sono abilite, potete semplicemente utilizzare 4198c2ecf20Sopenharmony_ci:c:func:`local_irq_disable()` e :c:func:`local_irq_enable()`. 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci.. _it_local_bh_disable: 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci:c:func:`local_bh_disable()`/:c:func:`local_bh_enable()` 4248c2ecf20Sopenharmony_ci-------------------------------------------------------- 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ciDefinite in ``include/linux/bottom_half.h`` 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ciQueste funzioni abilitano e disabilitano le interruzioni software 4308c2ecf20Sopenharmony_cisul processore locale. Entrambe sono rientranti; se le interruzioni 4318c2ecf20Sopenharmony_cisoftware erano già state disabilitate in precedenza, rimarranno 4328c2ecf20Sopenharmony_cidisabilitate anche dopo aver invocato questa coppia di funzioni. 4338c2ecf20Sopenharmony_ciLo scopo è di prevenire l'esecuzione di softirq e tasklet sul processore 4348c2ecf20Sopenharmony_ciattuale. 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci:c:func:`smp_processor_id()` 4378c2ecf20Sopenharmony_ci---------------------------- 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ciDefinita in ``include/linux/smp.h`` 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci:c:func:`get_cpu()` nega il diritto di prelazione (quindi non potete essere 4428c2ecf20Sopenharmony_cispostati su un altro processore all'improvviso) e ritorna il numero 4438c2ecf20Sopenharmony_cidel processore attuale, fra 0 e ``NR_CPUS``. Da notare che non è detto 4448c2ecf20Sopenharmony_ciche la numerazione dei processori sia continua. Quando avete terminato, 4458c2ecf20Sopenharmony_ciritornate allo stato precedente con :c:func:`put_cpu()`. 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ciSe sapete che non dovete essere interrotti da altri processi (per esempio, 4488c2ecf20Sopenharmony_cise siete in un contesto d'interruzione, o il diritto di prelazione 4498c2ecf20Sopenharmony_ciè disabilitato) potete utilizzare smp_processor_id(). 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci``__init``/``__exit``/``__initdata`` 4538c2ecf20Sopenharmony_ci------------------------------------ 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ciDefinite in ``include/linux/init.h`` 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ciDopo l'avvio, il kernel libera una sezione speciale; le funzioni marcate 4588c2ecf20Sopenharmony_cicon ``__init`` e le strutture dati marcate con ``__initdata`` vengono 4598c2ecf20Sopenharmony_cieliminate dopo il completamento dell'avvio: in modo simile i moduli eliminano 4608c2ecf20Sopenharmony_ciquesta memoria dopo l'inizializzazione. ``__exit`` viene utilizzato per 4618c2ecf20Sopenharmony_cidichiarare che una funzione verrà utilizzata solo in fase di rimozione: 4628c2ecf20Sopenharmony_cila detta funzione verrà eliminata quando il file che la contiene non è 4638c2ecf20Sopenharmony_cicompilato come modulo. Guardate l'header file per informazioni. Da notare che 4648c2ecf20Sopenharmony_cinon ha senso avere una funzione marcata come ``__init`` e al tempo stesso 4658c2ecf20Sopenharmony_ciesportata ai moduli utilizzando :c:func:`EXPORT_SYMBOL()` o 4668c2ecf20Sopenharmony_ci:c:func:`EXPORT_SYMBOL_GPL()` - non funzionerà. 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci:c:func:`__initcall()`/:c:func:`module_init()` 4708c2ecf20Sopenharmony_ci---------------------------------------------- 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ciDefinite in ``include/linux/init.h`` / ``include/linux/module.h`` 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ciMolte parti del kernel funzionano bene come moduli (componenti del kernel 4758c2ecf20Sopenharmony_cicaricabili dinamicamente). L'utilizzo delle macro :c:func:`module_init()` 4768c2ecf20Sopenharmony_cie :c:func:`module_exit()` semplifica la scrittura di codice che può funzionare 4778c2ecf20Sopenharmony_cisia come modulo, sia come parte del kernel, senza l'ausilio di #ifdef. 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ciLa macro :c:func:`module_init()` definisce quale funzione dev'essere 4808c2ecf20Sopenharmony_cichiamata quando il modulo viene inserito (se il file è stato compilato come 4818c2ecf20Sopenharmony_citale), o in fase di avvio : se il file non è stato compilato come modulo la 4828c2ecf20Sopenharmony_cimacro :c:func:`module_init()` diventa equivalente a :c:func:`__initcall()`, 4838c2ecf20Sopenharmony_cila quale, tramite qualche magia del linker, s'assicura che la funzione venga 4848c2ecf20Sopenharmony_cichiamata durante l'avvio. 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ciLa funzione può ritornare un numero d'errore negativo per scatenare un 4878c2ecf20Sopenharmony_cifallimento del caricamento (sfortunatamente, questo non ha effetto se il 4888c2ecf20Sopenharmony_cimodulo è compilato come parte integrante del kernel). Questa funzione è chiamata 4898c2ecf20Sopenharmony_ciin contesto utente con le interruzioni abilitate, quindi potrebbe dormire. 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci:c:func:`module_exit()` 4938c2ecf20Sopenharmony_ci----------------------- 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ciDefinita in ``include/linux/module.h`` 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ciQuesta macro definisce la funzione che dev'essere chiamata al momento della 4998c2ecf20Sopenharmony_cirimozione (o mai, nel caso in cui il file sia parte integrante del kernel). 5008c2ecf20Sopenharmony_ciEssa verrà chiamata solo quando il contatore d'uso del modulo raggiunge lo 5018c2ecf20Sopenharmony_cizero. Questa funzione può anche dormire, ma non può fallire: tutto dev'essere 5028c2ecf20Sopenharmony_ciripulito prima che la funzione ritorni. 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ciDa notare che questa macro è opzionale: se non presente, il modulo non sarà 5058c2ecf20Sopenharmony_ciremovibile (a meno che non usiate 'rmmod -f' ). 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci:c:func:`try_module_get()`/:c:func:`module_put()` 5098c2ecf20Sopenharmony_ci------------------------------------------------- 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ciDefinite in ``include/linux/module.h`` 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ciQueste funzioni maneggiano il contatore d'uso del modulo per proteggerlo dalla 5148c2ecf20Sopenharmony_cirimozione (in aggiunta, un modulo non può essere rimosso se un altro modulo 5158c2ecf20Sopenharmony_ciutilizzo uno dei sui simboli esportati: vedere di seguito). Prima di eseguire 5168c2ecf20Sopenharmony_cicodice del modulo, dovreste chiamare :c:func:`try_module_get()` su quel modulo: 5178c2ecf20Sopenharmony_cise fallisce significa che il modulo è stato rimosso e dovete agire come se 5188c2ecf20Sopenharmony_cinon fosse presente. Altrimenti, potete accedere al modulo in sicurezza, e 5198c2ecf20Sopenharmony_cichiamare :c:func:`module_put()` quando avete finito. 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ciLa maggior parte delle strutture registrabili hanno un campo owner 5228c2ecf20Sopenharmony_ci(proprietario), come nella struttura 5238c2ecf20Sopenharmony_ci:c:type:`struct file_operations <file_operations>`. 5248c2ecf20Sopenharmony_ciImpostate questo campo al valore della macro ``THIS_MODULE``. 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ciCode d'attesa ``include/linux/wait.h`` 5288c2ecf20Sopenharmony_ci====================================== 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci**[DORMONO]** 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ciUna coda d'attesa è usata per aspettare che qualcuno vi attivi quando una 5338c2ecf20Sopenharmony_cicerta condizione s'avvera. Per evitare corse critiche, devono essere usate 5348c2ecf20Sopenharmony_cicon cautela. Dichiarate una :c:type:`wait_queue_head_t`, e poi i processi 5358c2ecf20Sopenharmony_ciche vogliono attendere il verificarsi di quella condizione dichiareranno 5368c2ecf20Sopenharmony_ciuna :c:type:`wait_queue_entry_t` facendo riferimento a loro stessi, poi 5378c2ecf20Sopenharmony_cimetteranno questa in coda. 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ciDichiarazione 5408c2ecf20Sopenharmony_ci------------- 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ciPotere dichiarare una ``wait_queue_head_t`` utilizzando la macro 5438c2ecf20Sopenharmony_ci:c:func:`DECLARE_WAIT_QUEUE_HEAD()` oppure utilizzando la procedura 5448c2ecf20Sopenharmony_ci:c:func:`init_waitqueue_head()` nel vostro codice d'inizializzazione. 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ciAccodamento 5478c2ecf20Sopenharmony_ci----------- 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ciMettersi in una coda d'attesa è piuttosto complesso, perché dovete 5508c2ecf20Sopenharmony_cimettervi in coda prima di verificare la condizione. Esiste una macro 5518c2ecf20Sopenharmony_cia questo scopo: :c:func:`wait_event_interruptible()` (``include/linux/wait.h``). 5528c2ecf20Sopenharmony_ciIl primo argomento è la testa della coda d'attesa, e il secondo è 5538c2ecf20Sopenharmony_ciun'espressione che dev'essere valutata; la macro ritorna 0 quando questa 5548c2ecf20Sopenharmony_ciespressione è vera, altrimenti ``-ERESTARTSYS`` se è stato ricevuto un segnale. 5558c2ecf20Sopenharmony_ciLa versione :c:func:`wait_event()` ignora i segnali. 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ciSvegliare una procedura in coda 5588c2ecf20Sopenharmony_ci------------------------------- 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ciChiamate :c:func:`wake_up()` (``include/linux/wait.h``); questa attiverà tutti 5618c2ecf20Sopenharmony_cii processi in coda. Ad eccezione se uno di questi è impostato come 5628c2ecf20Sopenharmony_ci``TASK_EXCLUSIVE``, in questo caso i rimanenti non verranno svegliati. 5638c2ecf20Sopenharmony_ciNello stesso header file esistono altre varianti di questa funzione. 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ciOperazioni atomiche 5668c2ecf20Sopenharmony_ci=================== 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ciCerte operazioni sono garantite come atomiche su tutte le piattaforme. 5698c2ecf20Sopenharmony_ciIl primo gruppo di operazioni utilizza :c:type:`atomic_t` 5708c2ecf20Sopenharmony_ci(``include/asm/atomic.h``); questo contiene un intero con segno (minimo 32bit), 5718c2ecf20Sopenharmony_cie dovete utilizzare queste funzione per modificare o leggere variabili di tipo 5728c2ecf20Sopenharmony_ci:c:type:`atomic_t`. :c:func:`atomic_read()` e :c:func:`atomic_set()` leggono ed 5738c2ecf20Sopenharmony_ciimpostano il contatore, :c:func:`atomic_add()`, :c:func:`atomic_sub()`, 5748c2ecf20Sopenharmony_ci:c:func:`atomic_inc()`, :c:func:`atomic_dec()`, e 5758c2ecf20Sopenharmony_ci:c:func:`atomic_dec_and_test()` (ritorna vero se raggiunge zero dopo essere 5768c2ecf20Sopenharmony_cistata decrementata). 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ciSì. Ritorna vero (ovvero != 0) se la variabile atomica è zero. 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ciDa notare che queste funzioni sono più lente rispetto alla normale aritmetica, 5818c2ecf20Sopenharmony_cie quindi non dovrebbero essere usate a sproposito. 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ciIl secondo gruppo di operazioni atomiche sono definite in 5848c2ecf20Sopenharmony_ci``include/linux/bitops.h`` ed agiscono sui bit d'una variabile di tipo 5858c2ecf20Sopenharmony_ci``unsigned long``. Queste operazioni prendono come argomento un puntatore 5868c2ecf20Sopenharmony_cialla variabile, e un numero di bit dove 0 è quello meno significativo. 5878c2ecf20Sopenharmony_ci:c:func:`set_bit()`, :c:func:`clear_bit()` e :c:func:`change_bit()` 5888c2ecf20Sopenharmony_ciimpostano, cancellano, ed invertono il bit indicato. 5898c2ecf20Sopenharmony_ci:c:func:`test_and_set_bit()`, :c:func:`test_and_clear_bit()` e 5908c2ecf20Sopenharmony_ci:c:func:`test_and_change_bit()` fanno la stessa cosa, ad eccezione che 5918c2ecf20Sopenharmony_ciritornano vero se il bit era impostato; queste sono particolarmente 5928c2ecf20Sopenharmony_ciutili quando si vuole impostare atomicamente dei flag. 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ciCon queste operazioni è possibile utilizzare indici di bit che eccedono 5958c2ecf20Sopenharmony_ciil valore ``BITS_PER_LONG``. Il comportamento è strano sulle piattaforme 5968c2ecf20Sopenharmony_cibig-endian quindi è meglio evitarlo. 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ciSimboli 5998c2ecf20Sopenharmony_ci======= 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ciAll'interno del kernel, si seguono le normali regole del linker (ovvero, 6028c2ecf20Sopenharmony_cia meno che un simbolo non venga dichiarato con visibilita limitata ad un 6038c2ecf20Sopenharmony_cifile con la parola chiave ``static``, esso può essere utilizzato in qualsiasi 6048c2ecf20Sopenharmony_ciparte del kernel). Nonostante ciò, per i moduli, esiste una tabella dei 6058c2ecf20Sopenharmony_cisimboli esportati che limita i punti di accesso al kernel. Anche i moduli 6068c2ecf20Sopenharmony_cipossono esportare simboli. 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci:c:func:`EXPORT_SYMBOL()` 6098c2ecf20Sopenharmony_ci------------------------- 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ciDefinita in ``include/linux/export.h`` 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ciQuesto è il classico metodo per esportare un simbolo: i moduli caricati 6148c2ecf20Sopenharmony_cidinamicamente potranno utilizzare normalmente il simbolo. 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci:c:func:`EXPORT_SYMBOL_GPL()` 6178c2ecf20Sopenharmony_ci----------------------------- 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ciDefinita in ``include/linux/export.h`` 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ciEssa è simile a :c:func:`EXPORT_SYMBOL()` ad eccezione del fatto che i 6228c2ecf20Sopenharmony_cisimboli esportati con :c:func:`EXPORT_SYMBOL_GPL()` possono essere 6238c2ecf20Sopenharmony_ciutilizzati solo dai moduli che hanno dichiarato una licenza compatibile 6248c2ecf20Sopenharmony_cicon la GPL attraverso :c:func:`MODULE_LICENSE()`. Questo implica che la 6258c2ecf20Sopenharmony_cifunzione esportata è considerata interna, e non una vera e propria interfaccia. 6268c2ecf20Sopenharmony_ciAlcuni manutentori e sviluppatori potrebbero comunque richiedere 6278c2ecf20Sopenharmony_ci:c:func:`EXPORT_SYMBOL_GPL()` quando si aggiungono nuove funzionalità o 6288c2ecf20Sopenharmony_ciinterfacce. 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci:c:func:`EXPORT_SYMBOL_NS()` 6318c2ecf20Sopenharmony_ci---------------------------- 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ciDefinita in ``include/linux/export.h`` 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ciQuesta è una variate di `EXPORT_SYMBOL()` che permette di specificare uno 6368c2ecf20Sopenharmony_cispazio dei nomi. Lo spazio dei nomi è documentato in 6378c2ecf20Sopenharmony_ci:doc:`../core-api/symbol-namespaces` 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci:c:func:`EXPORT_SYMBOL_NS_GPL()` 6408c2ecf20Sopenharmony_ci-------------------------------- 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ciDefinita in ``include/linux/export.h`` 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ciQuesta è una variate di `EXPORT_SYMBOL_GPL()` che permette di specificare uno 6458c2ecf20Sopenharmony_cispazio dei nomi. Lo spazio dei nomi è documentato in 6468c2ecf20Sopenharmony_ci:doc:`../core-api/symbol-namespaces` 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ciProcedure e convenzioni 6498c2ecf20Sopenharmony_ci======================= 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ciListe doppiamente concatenate ``include/linux/list.h`` 6528c2ecf20Sopenharmony_ci------------------------------------------------------ 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ciUn tempo negli header del kernel c'erano tre gruppi di funzioni per 6558c2ecf20Sopenharmony_cile liste concatenate, ma questa è stata la vincente. Se non avete particolari 6568c2ecf20Sopenharmony_cinecessità per una semplice lista concatenata, allora questa è una buona scelta. 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ciIn particolare, :c:func:`list_for_each_entry()` è utile. 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ciConvenzione dei valori di ritorno 6618c2ecf20Sopenharmony_ci--------------------------------- 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ciPer codice chiamato in contesto utente, è molto comune sfidare le convenzioni 6648c2ecf20Sopenharmony_ciC e ritornare 0 in caso di successo, ed un codice di errore negativo 6658c2ecf20Sopenharmony_ci(eg. ``-EFAULT``) nei casi fallimentari. Questo potrebbe essere controintuitivo 6668c2ecf20Sopenharmony_cia prima vista, ma è abbastanza diffuso nel kernel. 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ciUtilizzate :c:func:`ERR_PTR()` (``include/linux/err.h``) per codificare 6698c2ecf20Sopenharmony_ciun numero d'errore negativo in un puntatore, e :c:func:`IS_ERR()` e 6708c2ecf20Sopenharmony_ci:c:func:`PTR_ERR()` per recuperarlo di nuovo: così si evita d'avere un 6718c2ecf20Sopenharmony_cipuntatore dedicato per il numero d'errore. Da brividi, ma in senso positivo. 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ciRompere la compilazione 6748c2ecf20Sopenharmony_ci----------------------- 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ciLinus e gli altri sviluppatori a volte cambiano i nomi delle funzioni e 6778c2ecf20Sopenharmony_cidelle strutture nei kernel in sviluppo; questo non è solo per tenere 6788c2ecf20Sopenharmony_citutti sulle spine: questo riflette cambiamenti fondamentati (eg. la funzione 6798c2ecf20Sopenharmony_cinon può più essere chiamata con le funzioni attive, o fa controlli aggiuntivi, 6808c2ecf20Sopenharmony_cio non fa più controlli che venivano fatti in precedenza). Solitamente a questo 6818c2ecf20Sopenharmony_cis'accompagna un'adeguata e completa nota sulla lista di discussone 6828c2ecf20Sopenharmony_cilinux-kernel; cercate negli archivi. 6838c2ecf20Sopenharmony_ciSolitamente eseguire una semplice sostituzione su tutto un file rendere 6848c2ecf20Sopenharmony_cile cose **peggiori**. 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ciInizializzazione dei campi d'una struttura 6878c2ecf20Sopenharmony_ci------------------------------------------ 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ciIl metodo preferito per l'inizializzazione delle strutture è quello 6908c2ecf20Sopenharmony_cidi utilizzare gli inizializzatori designati, come definiti nello 6918c2ecf20Sopenharmony_cistandard ISO C99, eg:: 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci static struct block_device_operations opt_fops = { 6948c2ecf20Sopenharmony_ci .open = opt_open, 6958c2ecf20Sopenharmony_ci .release = opt_release, 6968c2ecf20Sopenharmony_ci .ioctl = opt_ioctl, 6978c2ecf20Sopenharmony_ci .check_media_change = opt_media_change, 6988c2ecf20Sopenharmony_ci }; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ciQuesto rende più facile la ricerca con grep, e rende più chiaro quale campo 7018c2ecf20Sopenharmony_civiene impostato. Dovreste fare così perché si mostra meglio. 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ciEstensioni GNU 7048c2ecf20Sopenharmony_ci-------------- 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ciLe estensioni GNU sono esplicitamente permesse nel kernel Linux. Da notare 7078c2ecf20Sopenharmony_ciche alcune delle più complesse non sono ben supportate, per via dello scarso 7088c2ecf20Sopenharmony_cisviluppo, ma le seguenti sono da considerarsi la norma (per maggiori dettagli, 7098c2ecf20Sopenharmony_cileggete la sezione "C Extensions" nella pagina info di GCC - Sì, davvero 7108c2ecf20Sopenharmony_cila pagina info, la pagina man è solo un breve riassunto delle cose nella 7118c2ecf20Sopenharmony_cipagina info). 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci- Funzioni inline 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci- Istruzioni in espressioni (ie. il costrutto ({ and }) ). 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci- Dichiarate attributi di una funzione / variabile / tipo 7188c2ecf20Sopenharmony_ci (__attribute__) 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci- typeof 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci- Array con lunghezza zero 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci- Macro varargs 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci- Aritmentica sui puntatori void 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci- Inizializzatori non costanti 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci- Istruzioni assembler (non al di fuori di 'arch/' e 'include/asm/') 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci- Nomi delle funzioni come stringhe (__func__). 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci- __builtin_constant_p() 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ciSiate sospettosi quando utilizzate long long nel kernel, il codice generato 7378c2ecf20Sopenharmony_cida gcc è orribile ed anche peggio: le divisioni e le moltiplicazioni non 7388c2ecf20Sopenharmony_cifunzionano sulle piattaforme i386 perché le rispettive funzioni di runtime 7398c2ecf20Sopenharmony_cidi GCC non sono incluse nell'ambiente del kernel. 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ciC++ 7428c2ecf20Sopenharmony_ci--- 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ciSolitamente utilizzare il C++ nel kernel è una cattiva idea perché 7458c2ecf20Sopenharmony_ciil kernel non fornisce il necessario ambiente di runtime e gli header file 7468c2ecf20Sopenharmony_cinon sono stati verificati. Rimane comunque possibile, ma non consigliato. 7478c2ecf20Sopenharmony_ciSe davvero volete usarlo, almeno evitate le eccezioni. 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ciNUMif 7508c2ecf20Sopenharmony_ci----- 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ciViene generalmente considerato più pulito l'uso delle macro negli header file 7538c2ecf20Sopenharmony_ci(o all'inizio dei file .c) per astrarre funzioni piuttosto che utlizzare 7548c2ecf20Sopenharmony_cil'istruzione di pre-processore \`#if' all'interno del codice sorgente. 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ciMettere le vostre cose nel kernel 7578c2ecf20Sopenharmony_ci================================= 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ciAl fine d'avere le vostre cose in ordine per l'inclusione ufficiale, o 7608c2ecf20Sopenharmony_cianche per avere patch pulite, c'è del lavoro amministrativo da fare: 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci- Trovare di chi è lo stagno in cui state pisciando. Guardare in cima 7638c2ecf20Sopenharmony_ci ai file sorgenti, all'interno del file ``MAINTAINERS``, ed alla fine 7648c2ecf20Sopenharmony_ci di tutti nel file ``CREDITS``. Dovreste coordinarvi con queste persone 7658c2ecf20Sopenharmony_ci per evitare di duplicare gli sforzi, o provare qualcosa che è già stato 7668c2ecf20Sopenharmony_ci rigettato. 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci Assicuratevi di mettere il vostro nome ed indirizzo email in cima a 7698c2ecf20Sopenharmony_ci tutti i file che create o che mangeggiate significativamente. Questo è 7708c2ecf20Sopenharmony_ci il primo posto dove le persone guarderanno quando troveranno un baco, 7718c2ecf20Sopenharmony_ci o quando **loro** vorranno fare una modifica. 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci- Solitamente vorrete un'opzione di configurazione per la vostra modifica 7748c2ecf20Sopenharmony_ci al kernel. Modificate ``Kconfig`` nella cartella giusta. Il linguaggio 7758c2ecf20Sopenharmony_ci Config è facile con copia ed incolla, e c'è una completa documentazione 7768c2ecf20Sopenharmony_ci nel file ``Documentation/kbuild/kconfig-language.rst``. 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci Nella descrizione della vostra opzione, assicuratevi di parlare sia agli 7798c2ecf20Sopenharmony_ci utenti esperti sia agli utente che non sanno nulla del vostro lavoro. 7808c2ecf20Sopenharmony_ci Menzionate qui le incompatibilità ed i problemi. Chiaramente la 7818c2ecf20Sopenharmony_ci descrizione deve terminare con “if in doubt, say N” (se siete in dubbio, 7828c2ecf20Sopenharmony_ci dite N) (oppure, occasionalmente, \`Y'); questo è per le persone che non 7838c2ecf20Sopenharmony_ci hanno idea di che cosa voi stiate parlando. 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci- Modificate il file ``Makefile``: le variabili CONFIG sono esportate qui, 7868c2ecf20Sopenharmony_ci quindi potete solitamente aggiungere una riga come la seguete 7878c2ecf20Sopenharmony_ci "obj-$(CONFIG_xxx) += xxx.o". La sintassi è documentata nel file 7888c2ecf20Sopenharmony_ci ``Documentation/kbuild/makefiles.rst``. 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci- Aggiungete voi stessi in ``CREDITS`` se avete fatto qualcosa di notevole, 7918c2ecf20Sopenharmony_ci solitamente qualcosa che supera il singolo file (comunque il vostro nome 7928c2ecf20Sopenharmony_ci dovrebbe essere all'inizio dei file sorgenti). ``MAINTAINERS`` significa 7938c2ecf20Sopenharmony_ci che volete essere consultati quando vengono fatte delle modifiche ad un 7948c2ecf20Sopenharmony_ci sottosistema, e quando ci sono dei bachi; questo implica molto di più 7958c2ecf20Sopenharmony_ci di un semplice impegno su una parte del codice. 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci- Infine, non dimenticatevi di leggere 7988c2ecf20Sopenharmony_ci ``Documentation/process/submitting-patches.rst`` e possibilmente anche 7998c2ecf20Sopenharmony_ci ``Documentation/process/submitting-drivers.rst``. 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ciTrucchetti del kernel 8028c2ecf20Sopenharmony_ci===================== 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ciDopo una rapida occhiata al codice, questi sono i preferiti. Sentitevi liberi 8058c2ecf20Sopenharmony_cidi aggiungerne altri. 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci``arch/x86/include/asm/delay.h``:: 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci #define ndelay(n) (__builtin_constant_p(n) ? \ 8108c2ecf20Sopenharmony_ci ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \ 8118c2ecf20Sopenharmony_ci __ndelay(n)) 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci``include/linux/fs.h``:: 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci /* 8178c2ecf20Sopenharmony_ci * Kernel pointers have redundant information, so we can use a 8188c2ecf20Sopenharmony_ci * scheme where we can return either an error code or a dentry 8198c2ecf20Sopenharmony_ci * pointer with the same return value. 8208c2ecf20Sopenharmony_ci * 8218c2ecf20Sopenharmony_ci * This should be a per-architecture thing, to allow different 8228c2ecf20Sopenharmony_ci * error and pointer decisions. 8238c2ecf20Sopenharmony_ci */ 8248c2ecf20Sopenharmony_ci #define ERR_PTR(err) ((void *)((long)(err))) 8258c2ecf20Sopenharmony_ci #define PTR_ERR(ptr) ((long)(ptr)) 8268c2ecf20Sopenharmony_ci #define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000)) 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci``arch/x86/include/asm/uaccess_32.h:``:: 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci #define copy_to_user(to,from,n) \ 8318c2ecf20Sopenharmony_ci (__builtin_constant_p(n) ? \ 8328c2ecf20Sopenharmony_ci __constant_copy_to_user((to),(from),(n)) : \ 8338c2ecf20Sopenharmony_ci __generic_copy_to_user((to),(from),(n))) 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci``arch/sparc/kernel/head.S:``:: 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci /* 8398c2ecf20Sopenharmony_ci * Sun people can't spell worth damn. "compatability" indeed. 8408c2ecf20Sopenharmony_ci * At least we *know* we can't spell, and use a spell-checker. 8418c2ecf20Sopenharmony_ci */ 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci /* Uh, actually Linus it is I who cannot spell. Too much murky 8448c2ecf20Sopenharmony_ci * Sparc assembly will do this to ya. 8458c2ecf20Sopenharmony_ci */ 8468c2ecf20Sopenharmony_ci C_LABEL(cputypvar): 8478c2ecf20Sopenharmony_ci .asciz "compatibility" 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci /* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. */ 8508c2ecf20Sopenharmony_ci .align 4 8518c2ecf20Sopenharmony_ci C_LABEL(cputypvar_sun4m): 8528c2ecf20Sopenharmony_ci .asciz "compatible" 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci``arch/sparc/lib/checksum.S:``:: 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci /* Sun, you just can't beat me, you just can't. Stop trying, 8588c2ecf20Sopenharmony_ci * give up. I'm serious, I am going to kick the living shit 8598c2ecf20Sopenharmony_ci * out of you, game over, lights out. 8608c2ecf20Sopenharmony_ci */ 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ciRingraziamenti 8648c2ecf20Sopenharmony_ci============== 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ciRingrazio Andi Kleen per le sue idee, le risposte alle mie domande, 8678c2ecf20Sopenharmony_cile correzioni dei miei errori, l'aggiunta di contenuti, eccetera. 8688c2ecf20Sopenharmony_ciPhilipp Rumpf per l'ortografia e per aver reso più chiaro il testo, e 8698c2ecf20Sopenharmony_ciper alcuni eccellenti punti tutt'altro che ovvi. Werner Almesberger 8708c2ecf20Sopenharmony_ciper avermi fornito un ottimo riassunto di :c:func:`disable_irq()`, 8718c2ecf20Sopenharmony_cie Jes Sorensen e Andrea Arcangeli per le precisazioni. Michael Elizabeth 8728c2ecf20Sopenharmony_ciChastain per aver verificato ed aggiunto la sezione configurazione. 8738c2ecf20Sopenharmony_ciTelsa Gwynne per avermi insegnato DocBook. 874