linux – 如何知道写时复制页面是否是实际的副本?
发布时间:2020-12-13 18:48:29 所属栏目:Linux 来源:网络整理
导读:当我使用mmap创建写时复制映射(MAP_PRIVATE)时,只要我写入特定地址,就会复制此映射的某些页面.在我的程序中的某个点,我想弄清楚哪些页面实际上已被复制.有一个名为’mincore’的调用,但它只报告页面是否在内存中,这与正在复制的页面不同. 有没有办法弄清楚哪
当我使用mmap创建写时复制映射(MAP_PRIVATE)时,只要我写入特定地址,就会复制此映射的某些页面.在我的程序中的某个点,我想弄清楚哪些页面实际上已被复制.有一个名为’mincore’的调用,但它只报告页面是否在内存中,这与正在复制的页面不同.
有没有办法弄清楚哪些页面被复制了? 解决方法
很好,按照
MarkR的建议,我给了它一个镜头来浏览页面地图和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 testfilen"); } 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 mappingn"); 测试设置包含4页.第0页和第2页很脏 strcpy(M,"I feel so dirtyn"); strcpy(M+pagesize*2,"Christ on crutchesn"); 第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 bytesn",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 %llxn",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: %dn",pf,(pf>>14)&1); } } } 总而言之,我对这种方法并不是特别满意,因为它需要访问我们通常无法访问的文件,而且它很复杂(如何通过简单的内核调用来检索页面标记?). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |