162306a36Sopenharmony_ci.. include:: ../disclaimer-ita.rst 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci.. note:: Per leggere la documentazione originale in inglese: 462306a36Sopenharmony_ci :ref:`Documentation/kernel-hacking/hacking.rst <kernel_hacking_hack>` 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci:Original: :ref:`Documentation/kernel-hacking/hacking.rst <kernel_hacking_hack>` 762306a36Sopenharmony_ci:Translator: Federico Vaga <federico.vaga@vaga.pv.it> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci.. _it_kernel_hacking_hack: 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci================================================= 1262306a36Sopenharmony_ciL'inaffidabile guida all'hacking del kernel Linux 1362306a36Sopenharmony_ci================================================= 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci:Author: Rusty Russell 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ciIntroduzione 1862306a36Sopenharmony_ci============ 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ciBenvenuto, gentile lettore, alla notevole ed inaffidabile guida all'hacking 2162306a36Sopenharmony_cidel kernel Linux ad opera di Rusty. Questo documento descrive le procedure 2262306a36Sopenharmony_cipiù usate ed i concetti necessari per scrivere codice per il kernel: lo scopo 2362306a36Sopenharmony_ciè di fornire ai programmatori C più esperti un manuale di base per sviluppo. 2462306a36Sopenharmony_ciEviterò dettagli implementativi: per questo abbiamo il codice, 2562306a36Sopenharmony_cied ignorerò intere parti di alcune procedure. 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ciPrima di leggere questa guida, sappiate che non ho mai voluto scriverla, 2862306a36Sopenharmony_ciessendo esageratamente sotto qualificato, ma ho sempre voluto leggere 2962306a36Sopenharmony_ciqualcosa di simile, e quindi questa era l'unica via. Spero che possa 3062306a36Sopenharmony_cicrescere e diventare un compendio di buone pratiche, punti di partenza 3162306a36Sopenharmony_cie generiche informazioni. 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ciGli attori 3462306a36Sopenharmony_ci========== 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ciIn qualsiasi momento ognuna delle CPU di un sistema può essere: 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci- non associata ad alcun processo, servendo un'interruzione hardware; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci- non associata ad alcun processo, servendo un softirq o tasklet; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci- in esecuzione nello spazio kernel, associata ad un processo 4362306a36Sopenharmony_ci (contesto utente); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci- in esecuzione di un processo nello spazio utente; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ciEsiste un ordine fra questi casi. Gli ultimi due possono avvicendarsi (preempt) 4862306a36Sopenharmony_cil'un l'altro, ma a parte questo esiste una gerarchia rigida: ognuno di questi 4962306a36Sopenharmony_cipuò avvicendarsi solo ad uno di quelli sottostanti. Per esempio, mentre un 5062306a36Sopenharmony_cisoftirq è in esecuzione su d'una CPU, nessun altro softirq può avvicendarsi 5162306a36Sopenharmony_cinell'esecuzione, ma un'interruzione hardware può. Ciò nonostante, le altre CPU 5262306a36Sopenharmony_cidel sistema operano indipendentemente. 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ciPiù avanti vedremo alcuni modi in cui dal contesto utente è possibile bloccare 5562306a36Sopenharmony_cile interruzioni, così da impedirne davvero il diritto di prelazione. 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ciContesto utente 5862306a36Sopenharmony_ci--------------- 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ciCi si trova nel contesto utente quando si arriva da una chiamata di sistema 6162306a36Sopenharmony_ciod altre eccezioni: come nello spazio utente, altre procedure più importanti, 6262306a36Sopenharmony_cio le interruzioni, possono far valere il proprio diritto di prelazione sul 6362306a36Sopenharmony_civostro processo. Potete sospendere l'esecuzione chiamando :c:func:`schedule()`. 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci.. note:: 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci Si è sempre in contesto utente quando un modulo viene caricato o rimosso, 6862306a36Sopenharmony_ci e durante le operazioni nello strato dei dispositivi a blocchi 6962306a36Sopenharmony_ci (*block layer*). 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ciNel contesto utente, il puntatore ``current`` (il quale indica il processo al 7262306a36Sopenharmony_cimomento in esecuzione) è valido, e :c:func:`in_interrupt()` 7362306a36Sopenharmony_ci(``include/linux/preempt.h``) è falsa. 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci.. warning:: 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci Attenzione che se avete la prelazione o i softirq disabilitati (vedere 7862306a36Sopenharmony_ci di seguito), :c:func:`in_interrupt()` ritornerà un falso positivo. 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ciInterruzioni hardware (Hard IRQs) 8162306a36Sopenharmony_ci--------------------------------- 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ciTemporizzatori, schede di rete e tastiere sono esempi di vero hardware 8462306a36Sopenharmony_ciche possono produrre interruzioni in un qualsiasi momento. Il kernel esegue 8562306a36Sopenharmony_cii gestori d'interruzione che prestano un servizio all'hardware. Il kernel 8662306a36Sopenharmony_cigarantisce che questi gestori non vengano mai interrotti: se una stessa 8762306a36Sopenharmony_ciinterruzione arriva, questa verrà accodata (o scartata). 8862306a36Sopenharmony_ciDato che durante la loro esecuzione le interruzioni vengono disabilitate, 8962306a36Sopenharmony_cii gestori d'interruzioni devono essere veloci: spesso si limitano 9062306a36Sopenharmony_ciesclusivamente a notificare la presa in carico dell'interruzione, 9162306a36Sopenharmony_ciprogrammare una 'interruzione software' per l'esecuzione e quindi terminare. 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ciPotete dire d'essere in una interruzione hardware perché in_hardirq() 9462306a36Sopenharmony_ciritorna vero. 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci.. warning:: 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci Attenzione, questa ritornerà un falso positivo se le interruzioni 9962306a36Sopenharmony_ci sono disabilitate (vedere di seguito). 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ciContesto d'interruzione software: softirq e tasklet 10262306a36Sopenharmony_ci--------------------------------------------------- 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ciQuando una chiamata di sistema sta per tornare allo spazio utente, 10562306a36Sopenharmony_cioppure un gestore d'interruzioni termina, qualsiasi 'interruzione software' 10662306a36Sopenharmony_cimarcata come pendente (solitamente da un'interruzione hardware) viene 10762306a36Sopenharmony_cieseguita (``kernel/softirq.c``). 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ciLa maggior parte del lavoro utile alla gestione di un'interruzione avviene qui. 11062306a36Sopenharmony_ciAll'inizio della transizione ai sistemi multiprocessore, c'erano solo i 11162306a36Sopenharmony_cicosiddetti 'bottom half' (BH), i quali non traevano alcun vantaggio da questi 11262306a36Sopenharmony_cisistemi. Non appena abbandonammo i computer raffazzonati con fiammiferi e 11362306a36Sopenharmony_cicicche, abbandonammo anche questa limitazione e migrammo alle interruzioni 11462306a36Sopenharmony_cisoftware 'softirqs'. 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ciIl file ``include/linux/interrupt.h`` elenca i differenti tipi di 'softirq'. 11762306a36Sopenharmony_ciUn tipo di softirq molto importante è il timer (``include/linux/timer.h``): 11862306a36Sopenharmony_cipotete programmarlo per far si che esegua funzioni dopo un determinato 11962306a36Sopenharmony_ciperiodo di tempo. 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ciDato che i softirq possono essere eseguiti simultaneamente su più di un 12262306a36Sopenharmony_ciprocessore, spesso diventa estenuante l'averci a che fare. Per questa ragione, 12362306a36Sopenharmony_cii tasklet (``include/linux/interrupt.h``) vengo usati più di frequente: 12462306a36Sopenharmony_cipossono essere registrati dinamicamente (il che significa che potete averne 12562306a36Sopenharmony_ciquanti ne volete), e garantiscono che un qualsiasi tasklet verrà eseguito 12662306a36Sopenharmony_cisolo su un processore alla volta, sebbene diversi tasklet possono essere 12762306a36Sopenharmony_cieseguiti simultaneamente. 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci.. warning:: 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci Il nome 'tasklet' è ingannevole: non hanno niente a che fare 13262306a36Sopenharmony_ci con i 'processi' ('tasks'). 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ciPotete determinate se siete in un softirq (o tasklet) utilizzando la 13562306a36Sopenharmony_cimacro :c:func:`in_softirq()` (``include/linux/preempt.h``). 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci.. warning:: 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci State attenti che questa macro ritornerà un falso positivo 14062306a36Sopenharmony_ci se :ref:`bottom half lock <it_local_bh_disable>` è bloccato. 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ciAlcune regole basilari 14362306a36Sopenharmony_ci====================== 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ciNessuna protezione della memoria 14662306a36Sopenharmony_ci Se corrompete la memoria, che sia in contesto utente o d'interruzione, 14762306a36Sopenharmony_ci la macchina si pianterà. Siete sicuri che quello che volete fare 14862306a36Sopenharmony_ci non possa essere fatto nello spazio utente? 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ciNessun numero in virgola mobile o MMX 15162306a36Sopenharmony_ci Il contesto della FPU non è salvato; anche se siete in contesto utente 15262306a36Sopenharmony_ci lo stato dell'FPU probabilmente non corrisponde a quello del processo 15362306a36Sopenharmony_ci corrente: vi incasinerete con lo stato di qualche altro processo. Se 15462306a36Sopenharmony_ci volete davvero usare la virgola mobile, allora dovrete salvare e recuperare 15562306a36Sopenharmony_ci lo stato dell'FPU (ed evitare cambi di contesto). Generalmente è una 15662306a36Sopenharmony_ci cattiva idea; usate l'aritmetica a virgola fissa. 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ciUn limite rigido dello stack 15962306a36Sopenharmony_ci A seconda della configurazione del kernel lo stack è fra 3K e 6K per la 16062306a36Sopenharmony_ci maggior parte delle architetture a 32-bit; è di 14K per la maggior 16162306a36Sopenharmony_ci parte di quelle a 64-bit; e spesso è condiviso con le interruzioni, 16262306a36Sopenharmony_ci per cui non si può usare. 16362306a36Sopenharmony_ci Evitare profonde ricorsioni ad enormi array locali nello stack 16462306a36Sopenharmony_ci (allocateli dinamicamente). 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ciIl kernel Linux è portabile 16762306a36Sopenharmony_ci Quindi mantenetelo tale. Il vostro codice dovrebbe essere a 64-bit ed 16862306a36Sopenharmony_ci indipendente dall'ordine dei byte (endianess) di un processore. Inoltre, 16962306a36Sopenharmony_ci dovreste minimizzare il codice specifico per un processore; per esempio 17062306a36Sopenharmony_ci il codice assembly dovrebbe essere incapsulato in modo pulito e minimizzato 17162306a36Sopenharmony_ci per facilitarne la migrazione. Generalmente questo codice dovrebbe essere 17262306a36Sopenharmony_ci limitato alla parte di kernel specifica per un'architettura. 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ciioctl: non scrivere nuove chiamate di sistema 17562306a36Sopenharmony_ci============================================= 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ciUna chiamata di sistema, generalmente, è scritta così:: 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci asmlinkage long sys_mycall(int arg) 18062306a36Sopenharmony_ci { 18162306a36Sopenharmony_ci return 0; 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ciPrimo, nella maggior parte dei casi non volete creare nuove chiamate di 18562306a36Sopenharmony_cisistema. 18662306a36Sopenharmony_ciCreate un dispositivo a caratteri ed implementate l'appropriata chiamata ioctl. 18762306a36Sopenharmony_ciQuesto meccanismo è molto più flessibile delle chiamate di sistema: esso non 18862306a36Sopenharmony_cidev'essere dichiarato in tutte le architetture nei file 18962306a36Sopenharmony_ci``include/asm/unistd.h`` e ``arch/kernel/entry.S``; inoltre, è improbabile 19062306a36Sopenharmony_ciche questo venga accettato da Linus. 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ciSe tutto quello che il vostro codice fa è leggere o scrivere alcuni parametri, 19362306a36Sopenharmony_ciconsiderate l'implementazione di un'interfaccia :c:func:`sysfs()`. 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ciAll'interno di una ioctl vi trovate nel contesto utente di un processo. Quando 19662306a36Sopenharmony_ciavviene un errore dovete ritornare un valore negativo di errno (consultate 19762306a36Sopenharmony_ci``include/uapi/asm-generic/errno-base.h``, 19862306a36Sopenharmony_ci``include/uapi/asm-generic/errno.h`` e ``include/linux/errno.h``), altrimenti 19962306a36Sopenharmony_ciritornate 0. 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ciDopo aver dormito dovreste verificare se ci sono stati dei segnali: il modo 20262306a36Sopenharmony_ciUnix/Linux di gestire un segnale è di uscire temporaneamente dalla chiamata 20362306a36Sopenharmony_cidi sistema con l'errore ``-ERESTARTSYS``. La chiamata di sistema ritornerà 20462306a36Sopenharmony_cial contesto utente, eseguirà il gestore del segnale e poi la vostra chiamata 20562306a36Sopenharmony_cidi sistema riprenderà (a meno che l'utente non l'abbia disabilitata). Quindi, 20662306a36Sopenharmony_cidovreste essere pronti per continuare l'esecuzione, per esempio nel mezzo 20762306a36Sopenharmony_cidella manipolazione di una struttura dati. 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci:: 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci if (signal_pending(current)) 21262306a36Sopenharmony_ci return -ERESTARTSYS; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ciSe dovete eseguire dei calcoli molto lunghi: pensate allo spazio utente. 21562306a36Sopenharmony_ciSe **davvero** volete farlo nel kernel ricordatevi di verificare periodicamente 21662306a36Sopenharmony_cise dovete *lasciare* il processore (ricordatevi che, per ogni processore, c'è 21762306a36Sopenharmony_ciun sistema multi-processo senza diritto di prelazione). 21862306a36Sopenharmony_ciEsempio:: 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci cond_resched(); /* Will sleep */ 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ciUna breve nota sulla progettazione delle interfacce: il motto dei sistemi 22362306a36Sopenharmony_ciUNIX è "fornite meccanismi e non politiche" 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ciLa ricetta per uno stallo 22662306a36Sopenharmony_ci========================= 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ciNon è permesso invocare una procedura che potrebbe dormire, fanno eccezione 22962306a36Sopenharmony_cii seguenti casi: 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci- Siete in un contesto utente. 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci- Non trattenete alcun spinlock. 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci- Avete abilitato le interruzioni (in realtà, Andy Kleen dice che 23662306a36Sopenharmony_ci lo schedulatore le abiliterà per voi, ma probabilmente questo non è quello 23762306a36Sopenharmony_ci che volete). 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ciDa tener presente che alcune funzioni potrebbero dormire implicitamente: 24062306a36Sopenharmony_cile più comuni sono quelle per l'accesso allo spazio utente (\*_user) e 24162306a36Sopenharmony_ciquelle per l'allocazione della memoria senza l'opzione ``GFP_ATOMIC`` 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ciDovreste sempre compilare il kernel con l'opzione ``CONFIG_DEBUG_ATOMIC_SLEEP`` 24462306a36Sopenharmony_ciattiva, questa vi avviserà se infrangete una di queste regole. 24562306a36Sopenharmony_ciSe **infrangete** le regole, allora potreste bloccare il vostro scatolotto. 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ciVeramente. 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ciAlcune delle procedure più comuni 25062306a36Sopenharmony_ci================================= 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci:c:func:`printk()` 25362306a36Sopenharmony_ci------------------ 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ciDefinita in ``include/linux/printk.h`` 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci:c:func:`printk()` fornisce messaggi alla console, dmesg, e al demone syslog. 25862306a36Sopenharmony_ciEssa è utile per il debugging o per la notifica di errori; può essere 25962306a36Sopenharmony_ciutilizzata anche all'interno del contesto d'interruzione, ma usatela con 26062306a36Sopenharmony_cicautela: una macchina che ha la propria console inondata da messaggi diventa 26162306a36Sopenharmony_ciinutilizzabile. La funzione utilizza un formato stringa quasi compatibile con 26262306a36Sopenharmony_cila printf ANSI C, e la concatenazione di una stringa C come primo argomento 26362306a36Sopenharmony_ciper indicare la "priorità":: 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci printk(KERN_INFO "i = %u\n", i); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ciConsultate ``include/linux/kern_levels.h`` per gli altri valori ``KERN_``; 26862306a36Sopenharmony_ciquesti sono interpretati da syslog come livelli. Un caso speciale: 26962306a36Sopenharmony_ciper stampare un indirizzo IP usate:: 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci __be32 ipaddress; 27262306a36Sopenharmony_ci printk(KERN_INFO "my ip: %pI4\n", &ipaddress); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci:c:func:`printk()` utilizza un buffer interno di 1K e non s'accorge di 27662306a36Sopenharmony_cieventuali sforamenti. Accertatevi che vi basti. 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci.. note:: 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci Saprete di essere un vero hacker del kernel quando inizierete a digitare 28162306a36Sopenharmony_ci nei vostri programmi utenti le printf come se fossero printk :) 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci.. note:: 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci Un'altra nota a parte: la versione originale di Unix 6 aveva un commento 28662306a36Sopenharmony_ci sopra alla funzione printf: "Printf non dovrebbe essere usata per il 28762306a36Sopenharmony_ci chiacchiericcio". Dovreste seguire questo consiglio. 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci:c:func:`copy_to_user()` / :c:func:`copy_from_user()` / :c:func:`get_user()` / :c:func:`put_user()` 29062306a36Sopenharmony_ci--------------------------------------------------------------------------------------------------- 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ciDefinite in ``include/linux/uaccess.h`` / ``asm/uaccess.h`` 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci**[DORMONO]** 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci:c:func:`put_user()` e :c:func:`get_user()` sono usate per ricevere ed 29762306a36Sopenharmony_ciimpostare singoli valori (come int, char, o long) da e verso lo spazio utente. 29862306a36Sopenharmony_ciUn puntatore nello spazio utente non dovrebbe mai essere dereferenziato: i dati 29962306a36Sopenharmony_cidovrebbero essere copiati usando suddette procedure. Entrambe ritornano 30062306a36Sopenharmony_ci``-EFAULT`` oppure 0. 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci:c:func:`copy_to_user()` e :c:func:`copy_from_user()` sono più generiche: 30362306a36Sopenharmony_ciesse copiano una quantità arbitraria di dati da e verso lo spazio utente. 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci.. warning:: 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci Al contrario di:c:func:`put_user()` e :c:func:`get_user()`, queste 30862306a36Sopenharmony_ci funzioni ritornano la quantità di dati copiati (0 è comunque un successo). 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci[Sì, questa interfaccia mi imbarazza. La battaglia torna in auge anno 31162306a36Sopenharmony_cidopo anno. --RR] 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ciLe funzioni potrebbero dormire implicitamente. Queste non dovrebbero mai essere 31462306a36Sopenharmony_ciinvocate fuori dal contesto utente (non ha senso), con le interruzioni 31562306a36Sopenharmony_cidisabilitate, o con uno spinlock trattenuto. 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci:c:func:`kmalloc()`/:c:func:`kfree()` 31862306a36Sopenharmony_ci------------------------------------- 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ciDefinite in ``include/linux/slab.h`` 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci**[POTREBBERO DORMIRE: LEGGI SOTTO]** 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ciQueste procedure sono utilizzate per la richiesta dinamica di un puntatore ad 32562306a36Sopenharmony_ciun pezzo di memoria allineato, esattamente come malloc e free nello spazio 32662306a36Sopenharmony_ciutente, ma :c:func:`kmalloc()` ha un argomento aggiuntivo per indicare alcune 32762306a36Sopenharmony_ciopzioni. Le opzioni più importanti sono: 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci``GFP_KERNEL`` 33062306a36Sopenharmony_ci Potrebbe dormire per librarare della memoria. L'opzione fornisce il modo 33162306a36Sopenharmony_ci più affidabile per allocare memoria, ma il suo uso è strettamente limitato 33262306a36Sopenharmony_ci allo spazio utente. 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci``GFP_ATOMIC`` 33562306a36Sopenharmony_ci Non dorme. Meno affidabile di ``GFP_KERNEL``, ma può essere usata in un 33662306a36Sopenharmony_ci contesto d'interruzione. Dovreste avere **davvero** una buona strategia 33762306a36Sopenharmony_ci per la gestione degli errori in caso di mancanza di memoria. 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci``GFP_DMA`` 34062306a36Sopenharmony_ci Alloca memoria per il DMA sul bus ISA nello spazio d'indirizzamento 34162306a36Sopenharmony_ci inferiore ai 16MB. Se non sapete cos'è allora non vi serve. 34262306a36Sopenharmony_ci Molto inaffidabile. 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ciSe vedete un messaggio d'avviso per una funzione dormiente che viene chiamata 34562306a36Sopenharmony_cida un contesto errato, allora probabilmente avete usato una funzione 34662306a36Sopenharmony_cid'allocazione dormiente da un contesto d'interruzione senza ``GFP_ATOMIC``. 34762306a36Sopenharmony_ciDovreste correggerlo. Sbrigatevi, non cincischiate. 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ciSe allocate almeno ``PAGE_SIZE``(``asm/page.h`` o ``asm/page_types.h``) byte, 35062306a36Sopenharmony_ciconsiderate l'uso di :c:func:`__get_free_pages()` (``include/linux/gfp.h``). 35162306a36Sopenharmony_ciAccetta un argomento che definisce l'ordine (0 per per la dimensione di una 35262306a36Sopenharmony_cipagine, 1 per una doppia pagina, 2 per quattro pagine, eccetra) e le stesse 35362306a36Sopenharmony_ciopzioni d'allocazione viste precedentemente. 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ciSe state allocando un numero di byte notevolemnte superiore ad una pagina 35662306a36Sopenharmony_cipotete usare :c:func:`vmalloc()`. Essa allocherà memoria virtuale all'interno 35762306a36Sopenharmony_cidello spazio kernel. Questo è un blocco di memoria fisica non contiguo, ma 35862306a36Sopenharmony_cila MMU vi darà l'impressione che lo sia (quindi, sarà contiguo solo dal punto 35962306a36Sopenharmony_cidi vista dei processori, non dal punto di vista dei driver dei dispositivi 36062306a36Sopenharmony_ciesterni). 36162306a36Sopenharmony_ciSe per qualche strana ragione avete davvero bisogno di una grossa quantità di 36262306a36Sopenharmony_cimemoria fisica contigua, avete un problema: Linux non ha un buon supporto per 36362306a36Sopenharmony_ciquesto caso d'uso perché, dopo un po' di tempo, la frammentazione della memoria 36462306a36Sopenharmony_cirende l'operazione difficile. Il modo migliore per allocare un simile blocco 36562306a36Sopenharmony_ciall'inizio dell'avvio del sistema è attraverso la procedura 36662306a36Sopenharmony_ci:c:func:`alloc_bootmem()`. 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ciPrima di inventare la vostra cache per gli oggetti più usati, considerate 36962306a36Sopenharmony_cil'uso di una cache slab disponibile in ``include/linux/slab.h``. 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci:c:macro:`current` 37262306a36Sopenharmony_ci------------------- 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ciDefinita in ``include/asm/current.h`` 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ciQuesta variabile globale (in realtà una macro) contiene un puntatore alla 37762306a36Sopenharmony_cistruttura del processo corrente, quindi è valido solo dal contesto utente. 37862306a36Sopenharmony_ciPer esempio, quando un processo esegue una chiamata di sistema, questo 37962306a36Sopenharmony_cipunterà alla struttura dati del processo chiamate. 38062306a36Sopenharmony_ciNel contesto d'interruzione in suo valore **non è NULL**. 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci:c:func:`mdelay()`/:c:func:`udelay()` 38362306a36Sopenharmony_ci------------------------------------- 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ciDefinite in ``include/asm/delay.h`` / ``include/linux/delay.h`` 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ciLe funzioni :c:func:`udelay()` e :c:func:`ndelay()` possono essere utilizzate 38862306a36Sopenharmony_ciper brevi pause. Non usate grandi valori perché rischiate d'avere un 38962306a36Sopenharmony_cioverflow - in questo contesto la funzione :c:func:`mdelay()` è utile, 39062306a36Sopenharmony_cioppure considerate :c:func:`msleep()`. 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci:c:func:`cpu_to_be32()`/:c:func:`be32_to_cpu()`/:c:func:`cpu_to_le32()`/:c:func:`le32_to_cpu()` 39362306a36Sopenharmony_ci----------------------------------------------------------------------------------------------- 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ciDefinite in ``include/asm/byteorder.h`` 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ciLa famiglia di funzioni :c:func:`cpu_to_be32()` (dove "32" può essere 39862306a36Sopenharmony_cisostituito da 64 o 16, e "be" con "le") forniscono un modo generico 39962306a36Sopenharmony_ciper fare conversioni sull'ordine dei byte (endianess): esse ritornano 40062306a36Sopenharmony_ciil valore convertito. Tutte le varianti supportano anche il processo inverso: 40162306a36Sopenharmony_ci:c:func:`be32_to_cpu()`, eccetera. 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ciQueste funzioni hanno principalmente due varianti: la variante per 40462306a36Sopenharmony_cipuntatori, come :c:func:`cpu_to_be32p()`, che prende un puntatore 40562306a36Sopenharmony_ciad un tipo, e ritorna il valore convertito. L'altra variante per 40662306a36Sopenharmony_cila famiglia di conversioni "in-situ", come :c:func:`cpu_to_be32s()`, 40762306a36Sopenharmony_ciche convertono il valore puntato da un puntatore, e ritornano void. 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci:c:func:`local_irq_save()`/:c:func:`local_irq_restore()` 41062306a36Sopenharmony_ci-------------------------------------------------------- 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ciDefinite in ``include/linux/irqflags.h`` 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ciQueste funzioni abilitano e disabilitano le interruzioni hardware 41562306a36Sopenharmony_cisul processore locale. Entrambe sono rientranti; esse salvano lo stato 41662306a36Sopenharmony_ciprecedente nel proprio argomento ``unsigned long flags``. Se sapete 41762306a36Sopenharmony_ciche le interruzioni sono abilite, potete semplicemente utilizzare 41862306a36Sopenharmony_ci:c:func:`local_irq_disable()` e :c:func:`local_irq_enable()`. 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci.. _it_local_bh_disable: 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci:c:func:`local_bh_disable()`/:c:func:`local_bh_enable()` 42362306a36Sopenharmony_ci-------------------------------------------------------- 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ciDefinite in ``include/linux/bottom_half.h`` 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ciQueste funzioni abilitano e disabilitano le interruzioni software 42962306a36Sopenharmony_cisul processore locale. Entrambe sono rientranti; se le interruzioni 43062306a36Sopenharmony_cisoftware erano già state disabilitate in precedenza, rimarranno 43162306a36Sopenharmony_cidisabilitate anche dopo aver invocato questa coppia di funzioni. 43262306a36Sopenharmony_ciLo scopo è di prevenire l'esecuzione di softirq e tasklet sul processore 43362306a36Sopenharmony_ciattuale. 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci:c:func:`smp_processor_id()` 43662306a36Sopenharmony_ci---------------------------- 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ciDefinita in ``include/linux/smp.h`` 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci:c:func:`get_cpu()` nega il diritto di prelazione (quindi non potete essere 44162306a36Sopenharmony_cispostati su un altro processore all'improvviso) e ritorna il numero 44262306a36Sopenharmony_cidel processore attuale, fra 0 e ``NR_CPUS``. Da notare che non è detto 44362306a36Sopenharmony_ciche la numerazione dei processori sia continua. Quando avete terminato, 44462306a36Sopenharmony_ciritornate allo stato precedente con :c:func:`put_cpu()`. 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ciSe sapete che non dovete essere interrotti da altri processi (per esempio, 44762306a36Sopenharmony_cise siete in un contesto d'interruzione, o il diritto di prelazione 44862306a36Sopenharmony_ciè disabilitato) potete utilizzare smp_processor_id(). 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci``__init``/``__exit``/``__initdata`` 45262306a36Sopenharmony_ci------------------------------------ 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ciDefinite in ``include/linux/init.h`` 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ciDopo l'avvio, il kernel libera una sezione speciale; le funzioni marcate 45762306a36Sopenharmony_cicon ``__init`` e le strutture dati marcate con ``__initdata`` vengono 45862306a36Sopenharmony_cieliminate dopo il completamento dell'avvio: in modo simile i moduli eliminano 45962306a36Sopenharmony_ciquesta memoria dopo l'inizializzazione. ``__exit`` viene utilizzato per 46062306a36Sopenharmony_cidichiarare che una funzione verrà utilizzata solo in fase di rimozione: 46162306a36Sopenharmony_cila detta funzione verrà eliminata quando il file che la contiene non è 46262306a36Sopenharmony_cicompilato come modulo. Guardate l'header file per informazioni. Da notare che 46362306a36Sopenharmony_cinon ha senso avere una funzione marcata come ``__init`` e al tempo stesso 46462306a36Sopenharmony_ciesportata ai moduli utilizzando :c:func:`EXPORT_SYMBOL()` o 46562306a36Sopenharmony_ci:c:func:`EXPORT_SYMBOL_GPL()` - non funzionerà. 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci:c:func:`__initcall()`/:c:func:`module_init()` 46962306a36Sopenharmony_ci---------------------------------------------- 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ciDefinite in ``include/linux/init.h`` / ``include/linux/module.h`` 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ciMolte parti del kernel funzionano bene come moduli (componenti del kernel 47462306a36Sopenharmony_cicaricabili dinamicamente). L'utilizzo delle macro :c:func:`module_init()` 47562306a36Sopenharmony_cie :c:func:`module_exit()` semplifica la scrittura di codice che può funzionare 47662306a36Sopenharmony_cisia come modulo, sia come parte del kernel, senza l'ausilio di #ifdef. 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ciLa macro :c:func:`module_init()` definisce quale funzione dev'essere 47962306a36Sopenharmony_cichiamata quando il modulo viene inserito (se il file è stato compilato come 48062306a36Sopenharmony_citale), o in fase di avvio : se il file non è stato compilato come modulo la 48162306a36Sopenharmony_cimacro :c:func:`module_init()` diventa equivalente a :c:func:`__initcall()`, 48262306a36Sopenharmony_cila quale, tramite qualche magia del linker, s'assicura che la funzione venga 48362306a36Sopenharmony_cichiamata durante l'avvio. 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ciLa funzione può ritornare un numero d'errore negativo per scatenare un 48662306a36Sopenharmony_cifallimento del caricamento (sfortunatamente, questo non ha effetto se il 48762306a36Sopenharmony_cimodulo è compilato come parte integrante del kernel). Questa funzione è chiamata 48862306a36Sopenharmony_ciin contesto utente con le interruzioni abilitate, quindi potrebbe dormire. 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci:c:func:`module_exit()` 49262306a36Sopenharmony_ci----------------------- 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ciDefinita in ``include/linux/module.h`` 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ciQuesta macro definisce la funzione che dev'essere chiamata al momento della 49862306a36Sopenharmony_cirimozione (o mai, nel caso in cui il file sia parte integrante del kernel). 49962306a36Sopenharmony_ciEssa verrà chiamata solo quando il contatore d'uso del modulo raggiunge lo 50062306a36Sopenharmony_cizero. Questa funzione può anche dormire, ma non può fallire: tutto dev'essere 50162306a36Sopenharmony_ciripulito prima che la funzione ritorni. 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ciDa notare che questa macro è opzionale: se non presente, il modulo non sarà 50462306a36Sopenharmony_ciremovibile (a meno che non usiate 'rmmod -f' ). 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci:c:func:`try_module_get()`/:c:func:`module_put()` 50862306a36Sopenharmony_ci------------------------------------------------- 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ciDefinite in ``include/linux/module.h`` 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ciQueste funzioni maneggiano il contatore d'uso del modulo per proteggerlo dalla 51362306a36Sopenharmony_cirimozione (in aggiunta, un modulo non può essere rimosso se un altro modulo 51462306a36Sopenharmony_ciutilizzo uno dei sui simboli esportati: vedere di seguito). Prima di eseguire 51562306a36Sopenharmony_cicodice del modulo, dovreste chiamare :c:func:`try_module_get()` su quel modulo: 51662306a36Sopenharmony_cise fallisce significa che il modulo è stato rimosso e dovete agire come se 51762306a36Sopenharmony_cinon fosse presente. Altrimenti, potete accedere al modulo in sicurezza, e 51862306a36Sopenharmony_cichiamare :c:func:`module_put()` quando avete finito. 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ciLa maggior parte delle strutture registrabili hanno un campo owner 52162306a36Sopenharmony_ci(proprietario), come nella struttura 52262306a36Sopenharmony_ci:c:type:`struct file_operations <file_operations>`. 52362306a36Sopenharmony_ciImpostate questo campo al valore della macro ``THIS_MODULE``. 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ciCode d'attesa ``include/linux/wait.h`` 52762306a36Sopenharmony_ci====================================== 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci**[DORMONO]** 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ciUna coda d'attesa è usata per aspettare che qualcuno vi attivi quando una 53262306a36Sopenharmony_cicerta condizione s'avvera. Per evitare corse critiche, devono essere usate 53362306a36Sopenharmony_cicon cautela. Dichiarate una :c:type:`wait_queue_head_t`, e poi i processi 53462306a36Sopenharmony_ciche vogliono attendere il verificarsi di quella condizione dichiareranno 53562306a36Sopenharmony_ciuna :c:type:`wait_queue_entry_t` facendo riferimento a loro stessi, poi 53662306a36Sopenharmony_cimetteranno questa in coda. 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ciDichiarazione 53962306a36Sopenharmony_ci------------- 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ciPotere dichiarare una ``wait_queue_head_t`` utilizzando la macro 54262306a36Sopenharmony_ci:c:func:`DECLARE_WAIT_QUEUE_HEAD()` oppure utilizzando la procedura 54362306a36Sopenharmony_ci:c:func:`init_waitqueue_head()` nel vostro codice d'inizializzazione. 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ciAccodamento 54662306a36Sopenharmony_ci----------- 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ciMettersi in una coda d'attesa è piuttosto complesso, perché dovete 54962306a36Sopenharmony_cimettervi in coda prima di verificare la condizione. Esiste una macro 55062306a36Sopenharmony_cia questo scopo: :c:func:`wait_event_interruptible()` (``include/linux/wait.h``). 55162306a36Sopenharmony_ciIl primo argomento è la testa della coda d'attesa, e il secondo è 55262306a36Sopenharmony_ciun'espressione che dev'essere valutata; la macro ritorna 0 quando questa 55362306a36Sopenharmony_ciespressione è vera, altrimenti ``-ERESTARTSYS`` se è stato ricevuto un segnale. 55462306a36Sopenharmony_ciLa versione :c:func:`wait_event()` ignora i segnali. 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ciSvegliare una procedura in coda 55762306a36Sopenharmony_ci------------------------------- 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ciChiamate :c:func:`wake_up()` (``include/linux/wait.h``); questa attiverà tutti 56062306a36Sopenharmony_cii processi in coda. Ad eccezione se uno di questi è impostato come 56162306a36Sopenharmony_ci``TASK_EXCLUSIVE``, in questo caso i rimanenti non verranno svegliati. 56262306a36Sopenharmony_ciNello stesso header file esistono altre varianti di questa funzione. 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ciOperazioni atomiche 56562306a36Sopenharmony_ci=================== 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ciCerte operazioni sono garantite come atomiche su tutte le piattaforme. 56862306a36Sopenharmony_ciIl primo gruppo di operazioni utilizza :c:type:`atomic_t` 56962306a36Sopenharmony_ci(``include/asm/atomic.h``); questo contiene un intero con segno (minimo 32bit), 57062306a36Sopenharmony_cie dovete utilizzare queste funzione per modificare o leggere variabili di tipo 57162306a36Sopenharmony_ci:c:type:`atomic_t`. :c:func:`atomic_read()` e :c:func:`atomic_set()` leggono ed 57262306a36Sopenharmony_ciimpostano il contatore, :c:func:`atomic_add()`, :c:func:`atomic_sub()`, 57362306a36Sopenharmony_ci:c:func:`atomic_inc()`, :c:func:`atomic_dec()`, e 57462306a36Sopenharmony_ci:c:func:`atomic_dec_and_test()` (ritorna vero se raggiunge zero dopo essere 57562306a36Sopenharmony_cistata decrementata). 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ciSì. Ritorna vero (ovvero != 0) se la variabile atomica è zero. 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ciDa notare che queste funzioni sono più lente rispetto alla normale aritmetica, 58062306a36Sopenharmony_cie quindi non dovrebbero essere usate a sproposito. 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ciIl secondo gruppo di operazioni atomiche sono definite in 58362306a36Sopenharmony_ci``include/linux/bitops.h`` ed agiscono sui bit d'una variabile di tipo 58462306a36Sopenharmony_ci``unsigned long``. Queste operazioni prendono come argomento un puntatore 58562306a36Sopenharmony_cialla variabile, e un numero di bit dove 0 è quello meno significativo. 58662306a36Sopenharmony_ci:c:func:`set_bit()`, :c:func:`clear_bit()` e :c:func:`change_bit()` 58762306a36Sopenharmony_ciimpostano, cancellano, ed invertono il bit indicato. 58862306a36Sopenharmony_ci:c:func:`test_and_set_bit()`, :c:func:`test_and_clear_bit()` e 58962306a36Sopenharmony_ci:c:func:`test_and_change_bit()` fanno la stessa cosa, ad eccezione che 59062306a36Sopenharmony_ciritornano vero se il bit era impostato; queste sono particolarmente 59162306a36Sopenharmony_ciutili quando si vuole impostare atomicamente dei flag. 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ciCon queste operazioni è possibile utilizzare indici di bit che eccedono 59462306a36Sopenharmony_ciil valore ``BITS_PER_LONG``. Il comportamento è strano sulle piattaforme 59562306a36Sopenharmony_cibig-endian quindi è meglio evitarlo. 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ciSimboli 59862306a36Sopenharmony_ci======= 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ciAll'interno del kernel, si seguono le normali regole del linker (ovvero, 60162306a36Sopenharmony_cia meno che un simbolo non venga dichiarato con visibilita limitata ad un 60262306a36Sopenharmony_cifile con la parola chiave ``static``, esso può essere utilizzato in qualsiasi 60362306a36Sopenharmony_ciparte del kernel). Nonostante ciò, per i moduli, esiste una tabella dei 60462306a36Sopenharmony_cisimboli esportati che limita i punti di accesso al kernel. Anche i moduli 60562306a36Sopenharmony_cipossono esportare simboli. 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci:c:func:`EXPORT_SYMBOL()` 60862306a36Sopenharmony_ci------------------------- 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ciDefinita in ``include/linux/export.h`` 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ciQuesto è il classico metodo per esportare un simbolo: i moduli caricati 61362306a36Sopenharmony_cidinamicamente potranno utilizzare normalmente il simbolo. 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci:c:func:`EXPORT_SYMBOL_GPL()` 61662306a36Sopenharmony_ci----------------------------- 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ciDefinita in ``include/linux/export.h`` 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ciEssa è simile a :c:func:`EXPORT_SYMBOL()` ad eccezione del fatto che i 62162306a36Sopenharmony_cisimboli esportati con :c:func:`EXPORT_SYMBOL_GPL()` possono essere 62262306a36Sopenharmony_ciutilizzati solo dai moduli che hanno dichiarato una licenza compatibile 62362306a36Sopenharmony_cicon la GPL attraverso :c:func:`MODULE_LICENSE()`. Questo implica che la 62462306a36Sopenharmony_cifunzione esportata è considerata interna, e non una vera e propria interfaccia. 62562306a36Sopenharmony_ciAlcuni manutentori e sviluppatori potrebbero comunque richiedere 62662306a36Sopenharmony_ci:c:func:`EXPORT_SYMBOL_GPL()` quando si aggiungono nuove funzionalità o 62762306a36Sopenharmony_ciinterfacce. 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci:c:func:`EXPORT_SYMBOL_NS()` 63062306a36Sopenharmony_ci---------------------------- 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ciDefinita in ``include/linux/export.h`` 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ciQuesta è una variate di `EXPORT_SYMBOL()` che permette di specificare uno 63562306a36Sopenharmony_cispazio dei nomi. Lo spazio dei nomi è documentato in 63662306a36Sopenharmony_ciDocumentation/translations/it_IT/core-api/symbol-namespaces.rst. 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci:c:func:`EXPORT_SYMBOL_NS_GPL()` 63962306a36Sopenharmony_ci-------------------------------- 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ciDefinita in ``include/linux/export.h`` 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ciQuesta è una variate di `EXPORT_SYMBOL_GPL()` che permette di specificare uno 64462306a36Sopenharmony_cispazio dei nomi. Lo spazio dei nomi è documentato in 64562306a36Sopenharmony_ciDocumentation/translations/it_IT/core-api/symbol-namespaces.rst. 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ciProcedure e convenzioni 64862306a36Sopenharmony_ci======================= 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ciListe doppiamente concatenate ``include/linux/list.h`` 65162306a36Sopenharmony_ci------------------------------------------------------ 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ciUn tempo negli header del kernel c'erano tre gruppi di funzioni per 65462306a36Sopenharmony_cile liste concatenate, ma questa è stata la vincente. Se non avete particolari 65562306a36Sopenharmony_cinecessità per una semplice lista concatenata, allora questa è una buona scelta. 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ciIn particolare, :c:func:`list_for_each_entry()` è utile. 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ciConvenzione dei valori di ritorno 66062306a36Sopenharmony_ci--------------------------------- 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ciPer codice chiamato in contesto utente, è molto comune sfidare le convenzioni 66362306a36Sopenharmony_ciC e ritornare 0 in caso di successo, ed un codice di errore negativo 66462306a36Sopenharmony_ci(eg. ``-EFAULT``) nei casi fallimentari. Questo potrebbe essere controintuitivo 66562306a36Sopenharmony_cia prima vista, ma è abbastanza diffuso nel kernel. 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ciUtilizzate :c:func:`ERR_PTR()` (``include/linux/err.h``) per codificare 66862306a36Sopenharmony_ciun numero d'errore negativo in un puntatore, e :c:func:`IS_ERR()` e 66962306a36Sopenharmony_ci:c:func:`PTR_ERR()` per recuperarlo di nuovo: così si evita d'avere un 67062306a36Sopenharmony_cipuntatore dedicato per il numero d'errore. Da brividi, ma in senso positivo. 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ciRompere la compilazione 67362306a36Sopenharmony_ci----------------------- 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ciLinus e gli altri sviluppatori a volte cambiano i nomi delle funzioni e 67662306a36Sopenharmony_cidelle strutture nei kernel in sviluppo; questo non è solo per tenere 67762306a36Sopenharmony_citutti sulle spine: questo riflette cambiamenti fondamentati (eg. la funzione 67862306a36Sopenharmony_cinon può più essere chiamata con le funzioni attive, o fa controlli aggiuntivi, 67962306a36Sopenharmony_cio non fa più controlli che venivano fatti in precedenza). Solitamente a questo 68062306a36Sopenharmony_cis'accompagna un'adeguata e completa nota sulla lista di discussone 68162306a36Sopenharmony_cipiù adatta; cercate negli archivi. Solitamente eseguire una semplice 68262306a36Sopenharmony_cisostituzione su tutto un file rendere le cose **peggiori**. 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ciInizializzazione dei campi d'una struttura 68562306a36Sopenharmony_ci------------------------------------------ 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ciIl metodo preferito per l'inizializzazione delle strutture è quello 68862306a36Sopenharmony_cidi utilizzare gli inizializzatori designati, come definiti nello 68962306a36Sopenharmony_cistandard ISO C99, eg:: 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci static struct block_device_operations opt_fops = { 69262306a36Sopenharmony_ci .open = opt_open, 69362306a36Sopenharmony_ci .release = opt_release, 69462306a36Sopenharmony_ci .ioctl = opt_ioctl, 69562306a36Sopenharmony_ci .check_media_change = opt_media_change, 69662306a36Sopenharmony_ci }; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ciQuesto rende più facile la ricerca con grep, e rende più chiaro quale campo 69962306a36Sopenharmony_civiene impostato. Dovreste fare così perché si mostra meglio. 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ciEstensioni GNU 70262306a36Sopenharmony_ci-------------- 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ciLe estensioni GNU sono esplicitamente permesse nel kernel Linux. Da notare 70562306a36Sopenharmony_ciche alcune delle più complesse non sono ben supportate, per via dello scarso 70662306a36Sopenharmony_cisviluppo, ma le seguenti sono da considerarsi la norma (per maggiori dettagli, 70762306a36Sopenharmony_cileggete la sezione "C Extensions" nella pagina info di GCC - Sì, davvero 70862306a36Sopenharmony_cila pagina info, la pagina man è solo un breve riassunto delle cose nella 70962306a36Sopenharmony_cipagina info). 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci- Funzioni inline 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci- Istruzioni in espressioni (ie. il costrutto ({ and }) ). 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci- Dichiarate attributi di una funzione / variabile / tipo 71662306a36Sopenharmony_ci (__attribute__) 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci- typeof 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci- Array con lunghezza zero 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci- Macro varargs 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci- Aritmentica sui puntatori void 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci- Inizializzatori non costanti 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci- Istruzioni assembler (non al di fuori di 'arch/' e 'include/asm/') 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci- Nomi delle funzioni come stringhe (__func__). 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci- __builtin_constant_p() 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ciSiate sospettosi quando utilizzate long long nel kernel, il codice generato 73562306a36Sopenharmony_cida gcc è orribile ed anche peggio: le divisioni e le moltiplicazioni non 73662306a36Sopenharmony_cifunzionano sulle piattaforme i386 perché le rispettive funzioni di runtime 73762306a36Sopenharmony_cidi GCC non sono incluse nell'ambiente del kernel. 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ciC++ 74062306a36Sopenharmony_ci--- 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ciSolitamente utilizzare il C++ nel kernel è una cattiva idea perché 74362306a36Sopenharmony_ciil kernel non fornisce il necessario ambiente di runtime e gli header file 74462306a36Sopenharmony_cinon sono stati verificati. Rimane comunque possibile, ma non consigliato. 74562306a36Sopenharmony_ciSe davvero volete usarlo, almeno evitate le eccezioni. 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ciNUMif 74862306a36Sopenharmony_ci----- 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ciViene generalmente considerato più pulito l'uso delle macro negli header file 75162306a36Sopenharmony_ci(o all'inizio dei file .c) per astrarre funzioni piuttosto che utlizzare 75262306a36Sopenharmony_cil'istruzione di pre-processore \`#if' all'interno del codice sorgente. 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ciMettere le vostre cose nel kernel 75562306a36Sopenharmony_ci================================= 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ciAl fine d'avere le vostre cose in ordine per l'inclusione ufficiale, o 75862306a36Sopenharmony_cianche per avere patch pulite, c'è del lavoro amministrativo da fare: 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci- Trovare chi è responsabile del codice che state modificando. Guardare in cima 76162306a36Sopenharmony_ci ai file sorgenti, all'interno del file ``MAINTAINERS``, ed alla fine 76262306a36Sopenharmony_ci di tutti nel file ``CREDITS``. Dovreste coordinarvi con queste persone 76362306a36Sopenharmony_ci per evitare di duplicare gli sforzi, o provare qualcosa che è già stato 76462306a36Sopenharmony_ci rigettato. 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci Assicuratevi di mettere il vostro nome ed indirizzo email in cima a 76762306a36Sopenharmony_ci tutti i file che create o che maneggiate significativamente. Questo è 76862306a36Sopenharmony_ci il primo posto dove le persone guarderanno quando troveranno un baco, 76962306a36Sopenharmony_ci o quando **loro** vorranno fare una modifica. 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci- Solitamente vorrete un'opzione di configurazione per la vostra modifica 77262306a36Sopenharmony_ci al kernel. Modificate ``Kconfig`` nella cartella giusta. Il linguaggio 77362306a36Sopenharmony_ci Config è facile con copia ed incolla, e c'è una completa documentazione 77462306a36Sopenharmony_ci nel file ``Documentation/kbuild/kconfig-language.rst``. 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci Nella descrizione della vostra opzione, assicuratevi di parlare sia agli 77762306a36Sopenharmony_ci utenti esperti sia agli utente che non sanno nulla del vostro lavoro. 77862306a36Sopenharmony_ci Menzionate qui le incompatibilità ed i problemi. Chiaramente la 77962306a36Sopenharmony_ci descrizione deve terminare con “if in doubt, say N” (se siete in dubbio, 78062306a36Sopenharmony_ci dite N) (oppure, occasionalmente, \`Y'); questo è per le persone che non 78162306a36Sopenharmony_ci hanno idea di che cosa voi stiate parlando. 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci- Modificate il file ``Makefile``: le variabili CONFIG sono esportate qui, 78462306a36Sopenharmony_ci quindi potete solitamente aggiungere una riga come la seguete 78562306a36Sopenharmony_ci "obj-$(CONFIG_xxx) += xxx.o". La sintassi è documentata nel file 78662306a36Sopenharmony_ci ``Documentation/kbuild/makefiles.rst``. 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci- Aggiungete voi stessi in ``CREDITS`` se credete di aver fatto qualcosa di 78962306a36Sopenharmony_ci notevole, solitamente qualcosa che supera il singolo file (comunque il vostro 79062306a36Sopenharmony_ci nome dovrebbe essere all'inizio dei file sorgenti). ``MAINTAINERS`` significa 79162306a36Sopenharmony_ci che volete essere consultati quando vengono fatte delle modifiche ad un 79262306a36Sopenharmony_ci sottosistema, e quando ci sono dei bachi; questo implica molto di più di un 79362306a36Sopenharmony_ci semplice impegno su una parte del codice. 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci- Infine, non dimenticatevi di leggere 79662306a36Sopenharmony_ci ``Documentation/process/submitting-patches.rst``. 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ciTrucchetti del kernel 79962306a36Sopenharmony_ci===================== 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ciDopo una rapida occhiata al codice, questi sono i preferiti. Sentitevi liberi 80262306a36Sopenharmony_cidi aggiungerne altri. 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci``arch/x86/include/asm/delay.h``:: 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci #define ndelay(n) (__builtin_constant_p(n) ? \ 80762306a36Sopenharmony_ci ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \ 80862306a36Sopenharmony_ci __ndelay(n)) 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci``include/linux/fs.h``:: 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci /* 81462306a36Sopenharmony_ci * Kernel pointers have redundant information, so we can use a 81562306a36Sopenharmony_ci * scheme where we can return either an error code or a dentry 81662306a36Sopenharmony_ci * pointer with the same return value. 81762306a36Sopenharmony_ci * 81862306a36Sopenharmony_ci * This should be a per-architecture thing, to allow different 81962306a36Sopenharmony_ci * error and pointer decisions. 82062306a36Sopenharmony_ci */ 82162306a36Sopenharmony_ci #define ERR_PTR(err) ((void *)((long)(err))) 82262306a36Sopenharmony_ci #define PTR_ERR(ptr) ((long)(ptr)) 82362306a36Sopenharmony_ci #define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000)) 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci``arch/x86/include/asm/uaccess_32.h:``:: 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci #define copy_to_user(to,from,n) \ 82862306a36Sopenharmony_ci (__builtin_constant_p(n) ? \ 82962306a36Sopenharmony_ci __constant_copy_to_user((to),(from),(n)) : \ 83062306a36Sopenharmony_ci __generic_copy_to_user((to),(from),(n))) 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci``arch/sparc/kernel/head.S:``:: 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci /* 83662306a36Sopenharmony_ci * Sun people can't spell worth damn. "compatability" indeed. 83762306a36Sopenharmony_ci * At least we *know* we can't spell, and use a spell-checker. 83862306a36Sopenharmony_ci */ 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci /* Uh, actually Linus it is I who cannot spell. Too much murky 84162306a36Sopenharmony_ci * Sparc assembly will do this to ya. 84262306a36Sopenharmony_ci */ 84362306a36Sopenharmony_ci C_LABEL(cputypvar): 84462306a36Sopenharmony_ci .asciz "compatibility" 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci /* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. */ 84762306a36Sopenharmony_ci .align 4 84862306a36Sopenharmony_ci C_LABEL(cputypvar_sun4m): 84962306a36Sopenharmony_ci .asciz "compatible" 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci``arch/sparc/lib/checksum.S:``:: 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci /* Sun, you just can't beat me, you just can't. Stop trying, 85562306a36Sopenharmony_ci * give up. I'm serious, I am going to kick the living shit 85662306a36Sopenharmony_ci * out of you, game over, lights out. 85762306a36Sopenharmony_ci */ 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ciRingraziamenti 86162306a36Sopenharmony_ci============== 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ciRingrazio Andi Kleen per le sue idee, le risposte alle mie domande, 86462306a36Sopenharmony_cile correzioni dei miei errori, l'aggiunta di contenuti, eccetera. 86562306a36Sopenharmony_ciPhilipp Rumpf per l'ortografia e per aver reso più chiaro il testo, e 86662306a36Sopenharmony_ciper alcuni eccellenti punti tutt'altro che ovvi. Werner Almesberger 86762306a36Sopenharmony_ciper avermi fornito un ottimo riassunto di :c:func:`disable_irq()`, 86862306a36Sopenharmony_cie Jes Sorensen e Andrea Arcangeli per le precisazioni. Michael Elizabeth 86962306a36Sopenharmony_ciChastain per aver verificato ed aggiunto la sezione configurazione. 87062306a36Sopenharmony_ciTelsa Gwynne per avermi insegnato DocBook. 871