免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4058 | 回复: 14
打印 上一主题 下一主题

[内存管理] vmalloc时会不会page fault? [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-11-24 15:24 |只看该作者 |倒序浏览
本帖最后由 mrpre 于 2016-12-02 10:39 编辑

最近在学习内存相关的知识,疑问颇多。

教科书上对虚拟地址到物理地址的映射说是通过MMU进行转换的,为了提高性能同时也使用了TLB。
     疑问来了
     (1)是不是CPU所有要访问的地址都需要经过MMU转换?之所以这么问,是因为我再看MIPS体系结构时,说到MIPS将地址空间分为好几个部分,
            一部分需要映射,一部分直接减去page_offset得到物理地址。MMU会判断当前处理的地址属于不同部分进行不同的操作吗?既然所有地址都会进行
            转换,那么内核中virt_to_phys宏岂不是没必要(驱动程序需要?我没接触过),说明时候需要。
      

不是很理解进程的内核页表共享原理;
系统启动时,init_mm 中的页目录初始化时都是invalid_pmd_table,
即 pgd[0] = pgd[1] = ..... = invalid_pmd_table。

如果进程A创建了地址:0xc0000000,那么pgd[0]由于是invalid_pmd_table,进程A肯定会创建pud/pmd;
此时进程B fork了,拷贝init_mm的页目录, 进程B自然能访问进程A创建的0xc0000000。
但是进程B此时创建了地址0xcffff000,显然会在 pgd[x](x>0)处创建自己的pud/pmd,然后进程B能够访问自己的0xcffff000。
但是由于进程A的pgd[x]处是invalid_pmd_table(因为进程A拷贝的是原始的init_mm),他会创建自己的pud/pmd,两者就不能共享0xcffff000,我的推算不对吗?即一个进程在内核态vmalloc时获取到的内存,另一个进程在其内核态无法读取?
不说两个进程的例子了,说简单点,一个进程创建了,然后执行系统调用,在内核态调用vmalloc,vmalloc函数只是更新了init_mm,并未更新进程mm->pgd。请问是如何也目录是何时被更新的?


================================================



=
找到了,build_tlb_refill_handler函数中,根据不同类型cpu设置tlb/mmu查找的方式。
build_get_pgd_vmalloc64
类型是default的cpu且是mips64 ,vmalloc使用的就是swapper_pg_dir当做页目录,不是使用进程的页目录。

结贴。

论坛徽章:
0
2 [报告]
发表于 2016-11-25 10:38 |只看该作者
尝试回一下, mips不太清楚,以arm为例子:
1:是,virt_to_phys是用于内核地址空间通过物理地址快速计算虚拟地址,之所以可以这样计算是因为在内核地址空间物理地址和虚拟地址之间就是按照这种方式map的,其相关页目录表和页表也是是按这种方式在操作系统启动时就设置好的。
2:vmalloc执行中已经分配好page,并设置好了相关的页目录表和页表,因此不会发生page fault。内核中使用vmalloc分配的内存不能使用virt_to_phys或phys_to_virt进行虚实地址转化。

论坛徽章:
0
3 [报告]
发表于 2016-11-25 10:49 |只看该作者
另外,就32位arm而言,内核地址空间也分为好几部分,其中从0xc0000000起大概将近890M是使用上述1的方式直接map的,剩余部分地址空间用于vmalloc, pkmap, fixmap等。

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
4 [报告]
发表于 2016-11-25 12:05 |只看该作者
vmalloc调用的时候,只是初始化了init_mm的页表,而不是当前进程(或者后续使用进程)的页表。

论坛徽章:
0
5 [报告]
发表于 2016-11-25 13:32 |只看该作者
init_mm内核空间页表和其他所有进程在内核空间的页表是相同的

论坛徽章:
0
6 [报告]
发表于 2016-11-25 13:38 |只看该作者
看pgd_alloc函数

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
7 [报告]
发表于 2016-11-25 15:00 |只看该作者
回复 2# futex

谢谢回复;
“vmalloc执行中已经分配好page,并设置好了相关的页目录表和页表,因此不会发生page fault”
我看代码,确实vmalloc时设置好了页目录,我的问题是,因为所有地址都需要经过MMU,MMU是硬件吧,他会去读 init_mm ?
那不同的进程都有不同的页目录,MMU怎么区分要去读哪个页目录,难道是判断当前处于用户态,则读当前进程的页目录,处于内核态则读init_mm ?






论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
8 [报告]
发表于 2016-11-25 15:16 |只看该作者
回复 5# futex

还有一个疑问;正如您所说,所有的基础页表的后半部分拷贝自init_mm
mips:
                init = pgd_offset(&init_mm, 0UL);
                pgd_init((unsigned long)ret);
                memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
                       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));


x86:
                clone_pgd_range(pgd + KERNEL_PGD_BOUNDARY,
                                swapper_pg_dir + KERNEL_PGD_BOUNDARY,
                                KERNEL_PGD_PTRS);


有个问题,一个进程A新建时,自己的页目录拷贝自当前的init_mm,那后续如果init_mm被修改(比如进程B通过系统调用在内核态使用了vmallc新开辟了某块内存,更新了init_mm页目录,并且写了数据),由于进程A的内核部分页目录并未被修改,岂不是无法完成内核态的内存共享?

论坛徽章:
0
9 [报告]
发表于 2016-11-25 15:20 |只看该作者
本帖最后由 futex 于 2016-11-25 15:22 编辑

进程切换时如果需要切换内存则将新进程mm中页目录地址放在一个特定的寄存器中, 因此该寄存器内容总是保存当前进程mm的页目录表地址, 这样mmu就能根据该地址利用页表完成虚拟地址到物理地址的转换。

论坛徽章:
0
10 [报告]
发表于 2016-11-25 15:37 |只看该作者
vmallc不会更新init_mm内核地址空间页目录表,只会更新内核地址空间页表,而内核地址空间页表是所有进程mm共享的(pgd_alloc中只复制了页目录表而未复制页表),因此不存在你说的问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP