2017-05-01 2 views
0

cette question provient de la lecture du noyau, plus précisément des macros de trace. J'y suis arrivé quand j'étudiais comment les modules du noyau exécutaient les fichiers binaires, elf et scripts (fs/exec.c).Qu'advient-il des paramètres inutilisés dans la macro?

Pour une raison quelconque, je ne me souviens pas de ce qui est arrivé au fichier tracepoint.h, où la macro TRACE_EVENT, entre autres, est définie. J'utilise trace_event comme exemple car l'exemple de trace dans le noyau utilise cette macro. L'exemple a cette utilisation de la macro

TRACE_EVENT(foo_bar, 

    TP_PROTO(const char *foo, int bar, const int *lst, 
     const char *string, const struct cpumask *mask), 

    TP_ARGS(foo, bar, lst, string, mask), 

    TP_STRUCT__entry(
     __array( char, foo, 10  ) 
     __field( int, bar  ) 
     __dynamic_array(int, list, __length_of(lst)) 
     __string( str, string   ) 
     __bitmask( cpus, num_possible_cpus()) 
    ), 

    TP_fast_assign(
     strlcpy(__entry->foo, foo, 10); 
     __entry->bar = bar; 
     memcpy(__get_dynamic_array(list), lst, 
       __length_of(lst) * sizeof(int)); 
     __assign_str(str, string); 
     __assign_bitmask(cpus, cpumask_bits(mask), num_possible_cpus()); 
    ), 

    TP_printk("foo %s %d %s %s %s %s (%s)", __entry->foo, __entry->bar, 
/* 
* Notice here the use of some helper functions. This includes: 
* 
* __print_symbolic(variable, { value, "string" }, ...), 
* 
* The variable is tested against each value of the { } pair. If 
* the variable matches one of the values, then it will print the 
* string in that pair. If non are matched, it returns a string 
* version of the number (if __entry->bar == 7 then "7" is returned). 
*/ 
      __print_symbolic(__entry->bar, 
        { 0, "zero" }, 
        { TRACE_SAMPLE_FOO, "TWO" }, 
        { TRACE_SAMPLE_BAR, "FOUR" }, 
        { TRACE_SAMPLE_ZOO, "EIGHT" }, 
        { 10, "TEN" } 
      ), 

/* 
* __print_flags(variable, "delim", { value, "flag" }, ...), 
* 
* This is similar to __print_symbolic, except that it tests the bits 
* of the value. If ((FLAG & variable) == FLAG) then the string is 
* printed. If more than one flag matches, then each one that does is 
* also printed with delim in between them. 
* If not all bits are accounted for, then the not found bits will be 
* added in hex format: 0x506 will show BIT2|BIT4|0x500 
*/ 
      __print_flags(__entry->bar, "|", 
       { 1, "BIT1" }, 
       { 2, "BIT2" }, 
       { 4, "BIT3" }, 
       { 8, "BIT4" } 
      ), 
/* 
* __print_array(array, len, element_size) 
* 
* This prints out the array that is defined by __array in a nice format. 
*/ 
      __print_array(__get_dynamic_array(list), 
       __get_dynamic_array_len(list)/sizeof(int), 
       sizeof(int)), 
      __get_str(str), __get_bitmask(cpus)) 
); 

Alors, naturellement, après cela, je Wentto la définition de TRACE_EVENT et a trouvé cette

#define TRACE_EVENT(name, proto, args, struct, assign, print) \ DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))

Comme vous pouvez le voir, la macro trace_event n'utilise pas le paramètre print (ou argument?), ainsi que les paramètres struct et assign.

Il est très clairement indiqué que la macro en a besoin, mais au-dessous de tout, elle appelle simplement la macro declare_trace qui n'en a pas besoin. Comme pour le reste de la suite de la macro expansion je suis d'accord, rien d'inattendu, mais cet usage particulier de la macro me dérange. Est-ce que tous les autres domaines servent à quelque chose ou sont-ils simplement ... là sans aucune raison d'exister?

+0

Rien n'arrive aux arguments inutilisés; ils sont ignorés. Généralement, il existe (ou parfois une fois) des implémentations alternatives de la macro qui utilisent les arguments supplémentaires. Si les arguments supplémentaires ne sont définitivement jamais nécessaires, vous pouvez utiliser '0' ou' (void) 0' ou une valeur d'espace réservé pour les arguments inutilisés lorsque vous appelez la macro. –

+0

Je le pensais. J'étais sûr que je devenais fou, pourquoi avoir 3 paramètres inutilisés? Je croyais avoir oublié quelque chose. Ils prennent vraiment bien soin de ces paramètres donc ils doivent être utilisés quelque part, ou alors j'ai pensé – morcillo

+0

Le système de trace est une sorte de magie cpp sombre, jetez un oeil à http://lxr.free-electrons.com/ident?i = TRACE_EVENT et notez qu'il est redéfini. Vous devrez probablement creuser plus profondément dans les documents pour comprendre comment cela fonctionne. – pvg

Répondre

1

Comme correctement points @pvg, linux/tracepoint.h est juste la pointe de l'iceberg des points de trace. Cet en-tête seulement déclare les fonctions et les types appropriés. C'est pourquoi il ne gère pas certains arguments pour TRACE_EVENT.

Mais l'en-tête avec les définitions de trace est traité deux fois (ou plusieurs fois) et la prochaine fois tous les arguments à TRACE_EVENT sont gérés.

En savoir plus sur les points de trace dans le noyau Linux voir Documentation/trace/tracepoints.txt.