Ich schrieb Programme, um die Zeit von Seitenfehlern in einem Linux-System zu zählen. Genauer gesagt, der Zeitkern führt die Funktion __do_page_fault
aus.
Und irgendwie schrieb ich zwei globale Variablen, genannt pfcount_at_beg
und pfcount_at_end
, die einmal erhöhen, wenn die Funktion __do_page_fault
an verschiedenen Stellen der Funktion ausgeführt wird.Verwirrendes Ergebnis vom Zählen von Seitenfehlern in Linux
Zur Veranschaulichung, geht die modifizierte Funktion als:
unsigned long pfcount_at_beg = 0;
unsigned long pfcount_at_end = 0;
static void __kprobes
__do_page_fault(...)
{
struct vm_area_sruct *vma;
... // VARIABLES DEFINITION
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
pfcount_at_beg++; // I add THIS
...
...
// ORIGINAL CODE OF THE FUNCTION
...
pfcount_at_end++; // I add THIS
}
ich, dass der Wert von pfcount_at_end erwartet ist kleiner als der Wert von pfcount_at_beg.
Weil ich denke, jedes Mal, wenn Kernel die Anweisungen des Codes pfcount_at_end++
ausführt, muss es pfcount_at_beg++
ausgeführt haben (Jede Funktion beginnt ganz am Anfang des Codes).
Auf der anderen Seite gibt es viele bedingte return
zwischen diesen beiden Codezeilen.
Das Ergebnis ergibt sich jedoch entgegengesetzt. Der Wert pfcount_at_end
ist größer als der Wert pfcount_at_beg
.
Ich verwende printk
, um diese Kernelvariablen über eine selbst definierte syscall
zu drucken. Und ich schrieb das Benutzerlevelprogramm, um die system call
anzurufen.
Hier ist meine einfache syscall
und User-Level-Programm:
// syscall
asmlinkage int sys_mysyscall(void)
{
printk(KERN_INFO "total pf_at_beg%lu\ntotal pf_at_end%lu\n", pfcount_at_beg, pfcount_at_end)
return 0;
}
// user-level program
#include<linux/unistd.h>
#include<sys/syscall.h>
#define __NR_mysyscall 223
int main()
{
syscall(__NR_mysyscall);
return 0;
}
Gibt es jemand, der genau weiß, was während dies geschehen?
Gerade jetzt habe ich den Code geändert, um pfcount_at_beg
und pfcount_at_end
static
zu machen. Das Ergebnis hat sich jedoch nicht geändert, d. H. Der Wert pfcount_at_end
ist größer als der Wert pfcount_at_beg
. So möglicherweise könnte es durch atomare Operation von Inkrement verursacht werden. Wäre es besser, wenn ich Lese-Schreib-Sperre verwende?
Ich denke, dass die wahrscheinlichste Möglichkeit hier ist, dass Sie einen Fehler in Ihrem 'syscall'- oder Benutzerlevel-Programm haben und dass Sie die Variablen dort durcheinander bringen. Eine andere Sache, die Sie in Betracht ziehen sollten, ist, ob Sie auf die beiden Variablen atomar zugreifen und ob nicht, ob zwischenzeitlich Seitenfehler vorliegen. – Graeme
@Graeme Ich habe mein 'syscall'-Programm und das Benutzerlevel-Programm in der Frage hinzugefügt. Sie sind relativ einfach, weil es eine Übung war, um zu erfahren, wie 'syscall' implementiert wird. –
Ist das der echte Syscall-Code? Dem printk fehlen die tatsächlichen zu druckenden Werte. –