Gut, auf den Ratschlag von MarkR hin habe ich es versucht, durch das Pagemap- und Kpageflags-Interface zu gehen. Unten ein schneller Test, um zu überprüfen, ob eine Seite im Speicher als 'SWAPBACKED', wie es genannt wird, ist. Ein Problem bleibt natürlich, nämlich das Problem, dass kpageflags nur dem Root zugänglich ist.
int main(int argc, char* argv[])
{
unsigned long long pagesize=getpagesize();
assert(pagesize>0);
int pagecount=4;
int filesize=pagesize*pagecount;
int fd=open("test.dat", O_RDWR);
if (fd<=0)
{
fd=open("test.dat", O_CREAT|O_RDWR,S_IRUSR|S_IWUSR);
printf("Erstellte Testdatei test.dat\n");
}
assert(fd);
int err=ftruncate(fd,filesize);
assert(!err);
char* M=(char*)mmap(NULL, filesize, PROT_READ|PROT_WRITE, MAP_PRIVATE,fd,0);
assert(M!=(char*)-1);
assert(M);
printf("Private Zuordnung erfolgreich erstellt\n");
Das Test-Setup enthält 4 Seiten. Seite 0 und 2 sind dirty
strcpy(M,"Ich fühle mich so schmutzig\n");
strcpy(M+pagesize*2,"Christus auf Krücken\n");
Seite 3 wurde gelesen.
char t=M[pagesize*3];
Seite 1 wird nicht zugegriffen
Die Pagemap-Datei ordnet den virtuellen Speicherprozess den tatsächlichen Seiten zu, die dann später aus der globalen kpageflags-Datei abgerufen werden können. Lesen Sie die Datei /usr/src/linux/Documentation/vm/pagemap.txt
int mapfd=open("/proc/self/pagemap",O_RDONLY);
assert(mapfd>0);
unsigned long long target=((unsigned long)(void*)M)/pagesize;
err=lseek64(mapfd, target*8, SEEK_SET);
assert(err==target*8);
assert(sizeof(long long)==8);
Hier lesen wir die Rahmennummern für jede unserer virtuellen Seiten
unsigned long long page2pfn[pagecount];
err=read(mapfd,page2pfn,sizeof(long long)*pagecount);
if (err<0)
perror("Lesen der Pagemap");
if(err!=pagecount*8)
printf("Konnte nur %d Bytes lesen\n",err);
Jetzt werden wir für jede virtuelle Seite die tatsächlichen Seitenflags lesen
int pageflags=open("/proc/kpageflags",O_RDONLY);
assert(pageflags>0);
for(int i = 0 ; i < pagecount; i++)
{
unsigned long long v2a=page2pfn[i];
printf("Seite: %d, Flagge %llx\n",i,page2pfn[i]);
if(v2a&0x8000000000000000LL) // Ist die virtuelle Seite vorhanden ?
{
unsigned long long pfn=v2a&0x3fffffffffffffLL;
err=lseek64(pageflags,pfn*8,SEEK_SET);
assert(err==pfn*8);
unsigned long long pf;
err=read(pageflags,&pf,8);
assert(err==8);
printf("Seitenflags sind %llx mit SWAPBACKED: %d\n",pf,(pf>>14)&1);
}
}
}
Alles in allem bin ich mit diesem Ansatz nicht besonders zufrieden, da er den Zugriff auf eine Datei erfordert, auf die wir im Allgemeinen nicht zugreifen können, und er ist verdammt kompliziert (wie wäre es mit einem einfachen Kernelaufruf zur Abrufung der Seitenflags ?).