Comment obtenir le pointeur d'instruction (= compteur de programme) dans le noyau Linux

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; })

Une brève histoire du pointeur d'instruction dans le noyau Linux

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?

Quelle est cette 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é,

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.)

Et les salopes que je ne comprends pas le langage C

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

Comment obtenir le pointeur d'instruction (= compteur de programme) dans le noyau Linux
Comment obtenir les résultats de l'identifiant dans Celery
Comment obtenir de l'aide dans un shell interactif
Comment obtenir les fichiers dans le dossier [Python]
Comment obtenir le nom de la variable lui-même en python
Comment obtenir plusieurs objets de modèle au hasard dans Django
Comment faire reconnaître Yubico Yubikey par Manjaro Linux
Comment autoriser les utilisateurs nologin à se connecter sous Linux
[Linux] Comment mettre votre IP dans une variable
Comment obtenir des histogrammes RVB et HSV avec OpenCV
linux / c> lien> Obtenir le résultat de l'exécution de la commande shell dans le programme C> On m'a appris à utiliser popen ()
Comment estimer la densité du noyau
Comment se débarrasser des pictogrammes personnalisés du serveur dans message.content
[Go language] Comment obtenir l'entrée du terminal en temps réel
Linux: Comment récupérer si 'grub_file_filters' n'est pas trouvé dans grub rescue
[Linux] [C / C ++] Résumé de la façon d'obtenir pid, ppid, tid
J'ai essayé "Comment obtenir une méthode décorée en Python"
Comment obtenir la dernière (dernière) valeur d'une liste en Python
Comment obtenir toutes les clés et valeurs du dictionnaire
Comment obtenir une liste d'exceptions intégrées pour python
Comment développer en Python
Comment obtenir un aperçu de vos données dans Pandas
[Shell] Comment obtenir la branche distante par défaut avec Git
Comment démarrer la première projection
Comment afficher une colonne de fichiers spécifiée sous Linux (awk)
Comment obtenir toutes les valeurs possibles dans une expression régulière
Comment obtenir le pilote d'imprimante pour Oki Mac sous Linux
Comment obtenir une chaîne à partir d'un argument de ligne de commande en python
Comment obtenir tout le trafic via VPN avec OpenVPN sous Linux
Comment obtenir les coordonnées de sommet d'une entité dans ArcPy
Obtenez l'adresse IPv4 attribuée à l'interface réseau dans le code (Linux)
[Python] Comment faire PCA avec Python
Comment utiliser les classes dans Theano
Comment écrire sobrement avec des pandas
Comment collecter des images en Python
Comment mettre à jour Spyder dans Anaconda
Comment utiliser SQLite en Python
Comment installer VMware-Tools sur Linux
Comment obtenir la version Python
Comment installer MBDyn (Linux Ubuntu)
Comment convertir 0,5 en 1056964608 en un seul coup
Comment démarrer avec Scrapy
Comment démarrer avec Python
[Linux] [module du noyau] Créer kthread dans le module du noyau
Comment refléter CSS dans Django
Comment démarrer avec Django
Comment tuer des processus en vrac
Comment utiliser Mysql avec python
Comment envelopper C en Python
Comment utiliser ChemSpider en Python
Comment utiliser PubChem avec Python
Comment vérifier la version du système d'exploitation Linux
Comment exécuter du code TensorFlow 1.0 en 2.0
Comment gérer le japonais avec Python
Comment se connecter à Docker + NGINX
Comment appeler PyTorch dans Julia
Comment résoudre l'erreur "Aucun noyau de grammaire Python trouvé" dans Atom