Wenn Sie den Anweisungszeiger (= Programmzähler) im Linux-Kerneltreiber erhalten möchten, verwenden Sie das in linux / kernel.h definierte Makro _THIS_IP_
.
Die Definition ist wie folgt.
#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })
In der Vergangenheit hat jede Architektur ihre eigene "current_text_addr ()" definiert, aber es scheint, dass sie alle um v4.20 abgeschafft und vereinheitlicht wurden, um "THIS_IP" in linux / kernel.h zu verwenden. ist.
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v5.6-rc2&id=de0d22e50cd3d57277f073ccf65d57aa519d6888
Wenn Sie sich den Patch zu diesem Zeitpunkt ansehen, ist es interessant zu sehen, wie der Assembler jeder Architektur den Programmzähler erhält. Wie für jeden, der einen Assembler geschrieben hat, offensichtlich ist, unterscheidet sich das Register, das den Programmzähler des Prozessors enthält, je nach Architektur. Es erscheint daher sinnvoll, für jede Architektur eine separate Implementierung zu haben. Warum wurde es also zu einem Makro vereinheitlicht?
Zunächst konnte ich das Makro überhaupt nicht verstehen, also googelte ich es und ein sanfter älterer Bruder erklärte es mit Stapelüberlauf. Wie erwartet.
https://stackoverflow.com/questions/13902431/this-ip-macro-in-linux-kernel
Zusammenfassend,
__label__ __here;
ist eine Deklaration des lokalen Labelnamens__here:
ist das lokale Label&& __here;
ist die Adresse des oben genannten lokalen Labels (in vorzeichenlosen langen Typ umgewandelt)Es scheint, dass. Es ist schwer zu verstehen, ob in Klammern () nur eine Zeile steht. Wenn Sie also einen Zeilenumbruch einfügen,
{
__label__ __here;
__here:
(unsigned long)&&__here;
}
Die erste Zeile ist die Deklaration des lokalen Labelnamens und die zweite Zeile ist das Label. Das lokale Label scheint in GCC verwendbar zu sein. https://gcc.gnu.org/onlinedocs/gcc-5.2.0/gcc/Local-Labels.html
Es ist eine Bezeichnung, auf die nur innerhalb eines Blocks verwiesen werden kann.
Das '&&' in der dritten Zeile ist ein spezieller Operator zur Angabe der Adresse des Etiketts (Referenz: https://docs.oracle.com/cd/E19205-01/821-0386/bjabt/index.html).
An der Position, an der dieses Makro eingebettet ist, wird __here
als lokales Label in den Block eingefügt, und das Abrufen der Adresse dieses Labels ist die aktuelle Programmposition (= Programmzähler) am Ende.
Da die aktuelle Position des Programms nur in C-Sprache ausgedrückt werden kann, ohne sich auf den Assembler zu verlassen, ist es daher möglich, sie auch im Kernel zu einem "THIS_IP" -Makro zu vereinheitlichen. (Außerdem sollte gcc, solange es verwendet wird, auf verschiedene Umgebungen portierbar sein, nicht auf Linux.)
Das Problem ist darüber draußen. Ich weiß es ehrlich gesagt nicht. Normalerweise kann die Blockanweisung {} nicht als Ausdruck verwendet werden. Wenn Sie als Test den folgenden Code schreiben, wird als Test ein Kompilierungsfehler angezeigt.
int i = {1;};
Wenn Sie die block-Anweisung jedoch in Klammern () einschließen, wird sie aus irgendeinem Grund kompiliert.
int i = ({1;});
Zu diesem Zeitpunkt ist der Wert des Ausdrucks in Klammern () der Wert, wenn der am Ende der Anweisung block {} geschriebene Ausdruck ausgewertet wird. Wenn ich versuche, den folgenden Code mit gcc zu kompilieren und auszuführen, wird der Wert (= 5) des Ausdrucks d am Ende der Blockanweisung auf der Konsole angezeigt.
#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;
}
Wie ist das grammatikalisch? .. ..
Wie oben erwähnt, beschäftige ich mich seit mehr als 10 Jahren mit der C-Sprache, habe sie jedoch aufgrund der Ohnmacht, die ich noch nicht kenne oder grammatikalisch nicht lese, als Memorandum zusammengefasst. ... Ich werde mein Bestes geben.
Aber ich denke ** C Sprache ist nicht schön **. Weil '&&', müssen Sie mich die ganze Zeit als Binäroperator getroffen haben ...? (Ist '&&' auch eine Erweiterung von GCC? Https://gcc.gnu.org/onlinedocs/gcc-5.2.0/gcc/Labels-as-Values.html#Labels-as-Values)
Recommended Posts