Хорошо, следуя совету MarkR , я попробовал пройти через интерфейс pagemap и kpageflags.Ниже приведен быстрый тест, чтобы проверить, находится ли страница в памяти «SWAPBACKED», как она называется.Конечно, остается одна проблема, которая заключается в том, что kpageflags доступен только для root.
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("Created test.dat testfile\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("Successfully create private mapping\n");
Тестовая установка содержит 4 страницы.страницы 0 и 2 грязные
strcpy(M,"I feel so dirty\n");
strcpy(M+pagesize*2,"Christ on crutches\n");
страница 3 считана с.
char t=M[pagesize*3];
страница 1 не будет доступна
Файл карты страницы отображает процесс, еговиртуальной памяти на реальные страницы, которые затем могут быть извлечены из глобального файла kpageflags позже. Прочтите файл /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);
Здесь мы читаем номера фреймов страниц для каждой из наших виртуальных страниц
unsigned long long page2pfn[pagecount];
err=read(mapfd,page2pfn,sizeof(long long)*pagecount);
if (err<0)
perror("Reading pagemap");
if(err!=pagecount*8)
printf("Could only read %d bytes\n",err);
Теперь мы собираемся прочитать для каждого виртуального фрейма фактические флаги страниц
int pageflags=open("/proc/kpageflags",O_RDONLY);
assert(pageflags>0);
for(int i = 0 ; i < pagecount; i++)
{
unsigned long long v2a=page2pfn[i];
printf("Page: %d, flag %llx\n",i,page2pfn[i]);
if(v2a&0x8000000000000000LL) // Is the virtual page present ?
{
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("pageflags are %llx with SWAPBACKED: %d\n",pf,(pf>>14)&1);
}
}
}
В общем, я не особенно доволен этим подходом, так как он требует доступа к файлу, который мы ввообще не может получить доступ, и это чертовски сложно (как насчет простого вызова ядра для извлечения флагов страницы?).