linux charger - Quelle est la différence de section du noyau?





un module (2)


Cela signifie qu'une fonction qui se trouve dans une section avec une durée de vie donnée fait référence à quelque chose qui se trouve dans une section avec une durée de vie différente.

Lorsque le noyau binaire est lié, différentes parties du code et des données sont divisées en différentes sections. Certaines de ces sections restent chargées en permanence, mais d'autres sont supprimées dès qu'elles ne sont plus nécessaires (les choses qui ne sont requises que pendant le démarrage peuvent être libérées une fois le démarrage terminé - cela économise de la mémoire).

Si une fonction qui se trouve dans une section de longue durée fait référence à des données dans l'une des sections jetables, il y a un problème: elle peut essayer d'accéder à ces données lorsqu'elle a déjà été libérée, entraînant toutes sortes de problèmes d'exécution.

Ce n'est pas un avertissement que vous allez corriger vous-même, à moins que vous n'ayez écrit ce code ou que vous le connaissiez très bien. Il est corrigé en annotant correctement la fonction (ou les données auxquelles elle fait référence) afin qu'elle se place dans la bonne section. La bonne correction ne peut être déterminée qu'avec une connaissance détaillée de cette partie du noyau.

Pour obtenir la liste de ces sections et annotations, reportez-vous à l'en include/linux/init.h tête include/linux/init.h arborescence source du noyau:

/* These macros are used to mark some functions or 
 * initialized data (doesn't apply to uninitialized data)
 * as `initialization' functions. The kernel can take this
 * as hint that the function is used only during the initialization
 * phase and free up used memory resources after
 *
 * Usage:
 * For functions:
 * 
 * You should add __init immediately before the function name, like:
 *
 * static void __init initme(int x, int y)
 * {
 *    extern int z; z = x * y;
 * }
 *
 * If the function has a prototype somewhere, you can also add
 * __init between closing brace of the prototype and semicolon:
 *
 * extern int initialize_foobar_device(int, int, int) __init;
 *
 * For initialized data:
 * You should insert __initdata between the variable name and equal
 * sign followed by value, e.g.:
 *
 * static int init_variable __initdata = 0;
 * static const char linux_logo[] __initconst = { 0x32, 0x36, ... };
 *
 * Don't forget to initialize data not at file scope, i.e. within a function,
 * as gcc otherwise puts the data into the bss section and not into the init
 * section.
 * 
 * Also note, that this data cannot be "const".
 */

/* These are for everybody (although not all archs will actually
   discard it in modules) */
#define __init      __section(.init.text) __cold notrace
#define __initdata  __section(.init.data)
#define __initconst __section(.init.rodata)
#define __exitdata  __section(.exit.data)
#define __exit_call __used __section(.exitcall.exit)

D'autres suivent, avec plus de commentaires et d'explications.

Voir aussi le texte d'aide pour le symbole CONFIG_DEBUG_SECTION_MISMATCH :

L'analyse de la discordance de section vérifie s'il y a des
références d'une section à une autre section.
Linux va pendant le lien ou pendant l'exécution déposez quelques sections
et toute utilisation de code / données précédemment dans ces sections
résultat le plus probable dans un oups.
Dans le code, les fonctions et les variables sont annotées avec
__init, __devinit etc. (voir la liste complète dans include / linux / init.h)
ce qui entraîne le placement du code / des données dans des sections spécifiques.
L'analyse de discordance de section est toujours effectuée après une analyse complète
la construction du noyau mais en activant cette option sera en plus
fais ce qui suit:

  • Ajouter l'option -fno-inline-functions-called-une fois à gcc
    Lors de l'insertion d'une fonction annotée __init dans un non-init
    fonction nous perdrions l'information de la section et donc
    l'analyse n'attraperait pas la référence illégale.
    Cette option dit à gcc de moins en moins mais aussi
    entraîner un noyau plus grand.
  • Exécutez l'analyse de discordance de section pour chaque module / built-in.o
    Lorsque nous exécutons l'analyse de discordance de section sur vmlinux.o nous
    perdre des informations utiles sur l'endroit où la discordance était
    introduit.
    Exécution de l'analyse pour chaque fichier module / built-in.o
    dira où la discordance se produit beaucoup plus près de la
    la source. L'inconvénient est que nous signalerons le même
    discordance au moins deux fois.
  • Activer les rapports verbeux de modpost pour aider à résoudre
    les discordances de section signalées.

Lors de la compilation d'un module du noyau, j'ai reçu un message d'avertissement avec une note pour ajouter une option de compilation, CONFIG_DEBUG_SECTION_MISMATCH = y . Il me donne plus d'informations détaillées sur le problème:

WARNING: \**\*path to module\***(.text+0x8d2): Section mismatch in reference from the function Pch_Spi_Enable_Bios_Wr() to the variable .devinit.data:ich9_pci_tbl.22939
The function Pch_Spi_Enable_Bios_Wr() references
the variable __devinitdata ich9_pci_tbl.22939.
This is often because Pch_Spi_Enable_Bios_Wr lacks a __devinitdata
annotation or the annotation of ich9_pci_tbl.22939 is wrong.

Je n'ai pas pu trouver exactement ce qu'est la non-concordance des sections du noyau , sans parler de la façon de le réparer.




En Python, la définition de package est très simple. Comme Java, la structure hiérarchique et la structure de répertoires sont les mêmes. Mais vous devez avoir __init__.py dans un paquet. Je vais expliquer le fichier __init__.py avec l'exemple ci-dessous:

package_x/
|--  __init__.py
|--    subPackage_a/
|------  __init__.py
|------  module_m1.py
|--    subPackage_b/
|------  __init__.py
|------  module_n1.py
|------  module_n2.py
|------  module_n3.py

__init__.py peut être vide, tant qu'il existe. Cela indique que le répertoire doit être considéré comme un paquet. Bien sûr, __init__.py peut également définir le contenu approprié.

Si nous ajoutons une fonction dans module_n1:

def function_X():
    print "function_X in module_n1"
    return

Après l'exécution:

>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()

function_X in module_n1 

Ensuite, nous avons suivi le paquet de la hiérarchie et appelé la fonction module_n1. Nous pouvons utiliser __init__.py dans subPackage_b comme ceci:

__all__ = ['module_n2', 'module_n3']

Après l'exécution:

>>>from package_x.subPackage_b import * 
>>>module_n1.function_X()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named module_n1

Par conséquent, en utilisant * importing, le module package est soumis au contenu __init__.py .





linux module linux-kernel kernel