qchero 发表于 2014-05-16 20:31

如何将进程内一个地址范围内对应的页面清零

本帖最后由 qchero 于 2014-05-16 20:32 编辑

比如进程中有一个vma,我想将地址段的对应页表中页面的内容清零,但是保留原来的映射。
即不修改页表,不删除或添加映射,只修改页框中的数据为全零。

内核中有相应的api可以用吗?

谢谢~!

l4rmbr 发表于 2014-05-16 20:52

本帖最后由 l4rmbr 于 2014-05-16 20:53 编辑

回复 1# qchero


    clear_page(void *kaddr)

参数是个线性地址,该函数把PAGE_SIZE大小的页面清零。

如果是一个struct page*参数, 应该用kmap_atomic进行临时映射,再对映射后的地址进行调用该函数。

另,如果你是MAP_ANONYMOUS映射的话,那么内核保证page fault的时候,把页也清零的, 所以没必要自己去做。

qchero 发表于 2014-05-16 22:14

回复 2# l4rmbr


    谢谢回答!
但是还有个问题,就是我要改的内核版本是3.10.12的X86_64版本
好像没有clear_page(void *kaddr)这个函数了,只有clear_page(struct page*)。
那我想从虚拟地址去将页面清零的话,只能follow_page再clear_page了吗?

第一个问题是follow_page找到的page*还要通过kmap_atomic临时映射才能作为clear_page的参数吗?
第二个问题是我这样私自将页面清零会不会造成高速缓存不同步?

谢谢~!

l4rmbr 发表于 2014-05-16 23:08

本帖最后由 l4rmbr 于 2014-05-17 00:35 编辑

qchero 发表于 2014-05-16 22:14 static/image/common/back.gif
回复 2# l4rmbr





我指的是最新版的内核,里面有这个函数。我懒,所以没去查你这个版本有没有这个函数。
另外,我重新看了下代码,你的情况**最好**使用的是这个接口:

clear_user_highpage(struct page *page, unsigned long vaddr)

别给名字骗了,无论是否高端内存,这个函数都能正确运行。

两个参数任有一个,可得另一个。

struct *page   --->   vaddr:

      vaddr =page_address(page)

vaddr   --->   struct *page:

       int write = 1;/* 或0.1表示你会写该页, 0表示你只读该页 */
       strcut *page;
       int ret;
       ret = get_user_pages_fast(vaddr, 1,write,&page);
       if (ret != 1) {
               // 获取失败,进行错误清理操作, 具体自己去看这个函数的文档
       }

其实有更底层些的接口,但鉴于你可能是要用于模块中,这些接口都是有导出的,可以在模块中安全使用。


对于第二个问题,我的看法是不会。
      

qchero 发表于 2014-05-17 11:12

回复 4# l4rmbr


    谢谢这么详细的回答!
其实我要做的是把munmap的匿名映射空间回收,然后下次mmap的时候如果合适再返回给进程,这样就节省了重新映射页表的开销。
但是如果不对这块内存清零的话,就可能会有问题,因为libc里默认mmap到的空间都是全0的。

所以我是直接在内核代码里改的,主要是mm/mmap.c的代码,你说的更底层些的接口还有更合适的吗?

l4rmbr 发表于 2014-05-18 00:45

qchero 发表于 2014-05-17 11:12 static/image/common/back.gif
回复 4# l4rmbr




你顺着这些接口看下去,就能看到更底层的接口了。至于你说的解决问题的方法,得仔细研究下代码才敢做答,不敢瞎说了。如果你研究出来,欢迎来分享下
页: [1]
查看完整版本: 如何将进程内一个地址范围内对应的页面清零