Si vous voulez obtenir le pointeur d'instruction (= compteur de programme) dans le pilote du noyau Linux, utilisez la macro _THIS_IP_
définie dans linux / kernel.h.
La définition est la suivante.
#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })
Dans le passé, chaque architecture définissait son propre current_text_addr ()
, mais il semble qu'ils aient tous été abolis autour de la v4.20 et unifiés pour utiliser _THIS_IP_
dans linux / kernel.h. est.
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v5.6-rc2&id=de0d22e50cd3d57277f073ccf65d57aa519d6888
En regardant le patch à ce stade, il est intéressant de voir comment obtenir le compteur de programme par l'assembleur de chaque architecture. Comme il est évident pour quiconque a écrit un assembleur, le registre qui contient le compteur de programme du processeur diffère selon l'architecture. Il semble donc raisonnable d'avoir une implémentation distincte pour chaque architecture. Alors pourquoi a-t-il été unifié en une seule macro?
Tout d'abord, je ne comprenais pas du tout la macro, alors je l'ai googlé et un gentil frère aîné l'a expliqué avec un débordement de pile. Comme prévu.
https://stackoverflow.com/questions/13902431/this-ip-macro-in-linux-kernel
En résumé,
__label__ __here;
est une déclaration du nom de l'étiquette locale__here:
est l'étiquette locale&& __here;
est l'adresse de l'étiquette locale ci-dessus (transtypée en type long non signé)Il paraît que. Il est difficile de comprendre s'il n'y a qu'une seule ligne entre parenthèses (), donc si vous insérez un saut de ligne,
{
__label__ __here;
__here:
(unsigned long)&&__here;
}
La première ligne est la déclaration du nom de l'étiquette locale et la deuxième ligne est l'étiquette. Le label local semble être utilisable dans GCC. https://gcc.gnu.org/onlinedocs/gcc-5.2.0/gcc/Local-Labels.html
C'est une étiquette qui ne peut être référencée que dans un bloc.
Le '&&' sur la troisième ligne est un opérateur spécial pour indiquer l'adresse de l'étiquette (référence: https://docs.oracle.com/cd/E19205-01/821-0386/bjabt/index.html)
À la position où cette macro est intégrée, «__here» est collé comme étiquette locale dans le bloc, et obtenir l'adresse de cette étiquette est la position actuelle du programme (= compteur de programme) à la fin.
Par conséquent, étant donné que la position actuelle du programme ne peut être exprimée qu'en langage C sans dépendre de l'assembleur, il est possible de l'unifier en une macro _THIS_IP_
même dans le noyau. (De plus, tant que gcc est utilisé, il doit être portable dans divers environnements, sans se limiter à Linux.)
Le problème est à propos de cela à l'extérieur. Honnêtement, je ne sais pas. Normalement, l'instruction de bloc {} ne peut pas être utilisée comme expression. À titre de test, si vous écrivez le code suivant, vous obtiendrez une erreur de compilation.
int i = {1;};
Cependant, si vous mettez l'instruction block entre parenthèses (), elle se compilera pour une raison quelconque.
int i = ({1;});
À ce stade, la valeur de l'expression entre parenthèses () est la valeur lorsque l'expression écrite à la fin de l'instruction block {} est évaluée. Lorsque j'essaye de compiler le code suivant avec gcc et de l'exécuter, la valeur (= 5) de l'expression d à la fin de l'instruction de bloc est affichée sur la console.
#include <stdio.h>
int main(void)
{
int a = ({
int a = 2;
int b = 3;
int c = 4;
int d = 5;
a;
b;
c;
d;
});
printf("%d\n", a);
return 0;
}
Comment est-ce grammaticalement? .. ..
Comme mentionné ci-dessus, je travaille avec le langage C depuis plus de 10 ans, mais je l'ai résumé sous forme de mémorandum à cause de l'impuissance que je ne connais toujours pas ou ne lis pas grammaticalement. ... je vais me consacrer.
Mais je pense que ** le langage C n'est pas beau **. Parce que '&&', vous deviez me fréquenter en tant qu'opérateur binaire tout le temps ...? (Est-ce que '&&' est également une extension de GCC? Https://gcc.gnu.org/onlinedocs/gcc-5.2.0/gcc/Labels-as-Values.html#Labels-as-Values)
Recommended Posts