免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 952 | 回复: 7

[内核入门] 进程内核空间映射同步疑问? [复制链接]

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2016-07-08 21:00:1415-16赛季CBA联赛之同曦
日期:2017-02-15 14:26:1515-16赛季CBA联赛之佛山
日期:2017-02-20 14:19:2615-16赛季CBA联赛之青岛
日期:2017-05-07 16:49:1115-16赛季CBA联赛之广夏
日期:2017-07-30 09:13:1215-16赛季CBA联赛之广东
日期:2018-07-05 22:34:3615-16赛季CBA联赛之江苏
日期:2018-09-03 12:10:2115-16赛季CBA联赛之上海
日期:2018-09-25 03:49:2215-16赛季CBA联赛之广东
日期:2018-09-25 04:09:12
发表于 2016-02-03 23:34 |显示全部楼层
内存分配的本质(malloc()/kmalloc()),就是选一段空闲的虚拟地址和物理地址,并在该进程的地址映射表里建立它们之间的映射关系吧?

按我自己的理解,malloc()从0~3G选择虚拟地址(映射关系不固定),kmalloc()从3G~4G选择虚拟地址(映射关系固定),物理地址都可以从0~4G选择。

疑问:
进程A调用fork()创建了进程B,由于进程B的地址映射表直接从进程A复制过来,所以刚开始它们地址映射表记录的映射关系一模一样。
现在假设:由进程A切换到进程B执行,并且进程B通过系统调用进入内核态,执行了kmalloc()。这时,进程B的地址映射表里,比如添加了3.5G~3.6G虚拟地址到0.5G~0.6G物理地址的映射,然而进程A的地址映射表还是原来那样,所以,如果进程A进入内核态执行了kmalloc(),会不会认为3.5G~3.6G这块空间还没被使用,然后也分配了这块空间,并写入数据覆盖了进程B的数据?

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2016-07-08 21:00:1415-16赛季CBA联赛之同曦
日期:2017-02-15 14:26:1515-16赛季CBA联赛之佛山
日期:2017-02-20 14:19:2615-16赛季CBA联赛之青岛
日期:2017-05-07 16:49:1115-16赛季CBA联赛之广夏
日期:2017-07-30 09:13:1215-16赛季CBA联赛之广东
日期:2018-07-05 22:34:3615-16赛季CBA联赛之江苏
日期:2018-09-03 12:10:2115-16赛季CBA联赛之上海
日期:2018-09-25 03:49:2215-16赛季CBA联赛之广东
日期:2018-09-25 04:09:12
发表于 2016-02-04 00:03 |显示全部楼层
本帖最后由 _nosay 于 2016-02-04 00:18 编辑

回复 1# _nosay

PGD表有1个页面大小,后面的1/4部分,用于指向记录内核空间地址映射的PT,是不是每个进程PGD的这1/4部分都相同,即它们使用同样一组PT,这样某个进程改了映射关系,其它进程也能“看得见”?

mem_map[]对物理页面的管理,可以看出来物理页面是否已经在使用。


   

论坛徽章:
9
程序设计版块每日发帖之星
日期:2016-02-11 06:20:00程序设计版块每日发帖之星
日期:2016-02-14 06:20:00程序设计版块每日发帖之星
日期:2016-02-14 06:20:0015-16赛季CBA联赛之吉林
日期:2016-03-23 17:25:0015-16赛季CBA联赛之浙江
日期:2016-04-01 08:25:0615-16赛季CBA联赛之山西
日期:2016-04-01 10:09:1915-16赛季CBA联赛之广夏
日期:2016-06-03 15:58:212016科比退役纪念章
日期:2016-07-28 17:42:5215-16赛季CBA联赛之广东
日期:2017-02-20 23:32:43
发表于 2016-02-04 09:32 |显示全部楼层
HI:
     1.内存分配中 malloc 和 kmalloc 负责的层次不同,malloc 是 GLIB 层,属于用户空间内存分配,kmalloc 属于 Kernel 层,属于内核空间内存分配.
         kmalloc 的分配只与要分配的大小有关,它根据分配的大小来选择分配器,
     2. 如果 size 比较大,其从 Buddy 内存管理器里面分配内存.如果 size 不大,就从 SLUB 或者 SLAB 分配器里面分配内存.
         kmalloc 分配的内存都是物理内存,这些物理内存与虚拟地址一一对应,其映射关系也是一一对应的.
     3. malloc 属于用户空间的内存分配,由于它和内核之间还存在一个 GLIB 层,Glib 层有自己的内存管理.
         举个例子,malloc 在用户空间分配一部分内存之后,如果不对这部分内存进行写操作的话,这段虚拟地址是不进行映射的.
     4. 当用户对 malloc 分配的空间进行写操作,MMU 就会查找该虚拟地址对应的物理地址,这里就涉及查表,后面会讲.如果虚拟地址没有对应的物理地址,
         那么内核就发生缺页错误,之后就会建立虚拟地址和物理地址的映射.
     5. 由于使用 malloc 是从堆里面分配内存,这段内存建立映射的时候使用匿名映射.匿名映射内容很复杂,这里不做解释.
     6. 回到 4 中所讲的,如果对 malloc 分配的空间进行写操作,且虚拟地址有对应的物理地址,那么内核就查表.其代码流程如下:
          unsigned long addr = xxx; /* 已知的虚拟地址 */
          pgd_t *pgd;
          pmd_t *pmd;
          pte_t *pte;
          struct page *page;
          unsigned long phys_addr;


          pgd = pgd_offset(current->mm,addr);
          pmd = pmd_offset(pgd,addr);
          pte = pte_offset_map(pmd,pte);
          page = pte_page(pte);
          phys_addr = page_address(page);

          这样就可以通过虚拟地址找到物理地址.
         7. 用户空间的使用虚拟地址 0 ~ 3G,内核空间使用 3G ~ 4G 虚拟地址. kmalloc 的物理地址可要根据 GFP 标志来确认.
              如果 GFP_KERNL 的话,那么是从低端物理内存分配,如果是 GFP_HIGHMEM 的话,那么从高端物理内存分配.
         8. A -> fork() -> B 之后,B 进程的内存空间,即 task_struct 成员 mm. mm 属于 struct mm_struct ,这个结构负责管理进程的内存信息.
             内核在使用 fork 创建新的进程时候,进程 mm_struct 对应的内核部分映射是相同的,但用户空间的映射是进程自己独占的,
             也就是说对于任何进程来说,它们看到的内核空间都是相同的,但各自的 0 ~ 3G 空间,它们只能看到自己一个进程在独占这 0 ~ 3 G 的内存.
             也就只有 B 进入内核态修改了 3G ~ 4G 的地址, A 程序才知道.
         9. PGD 页表有 4 个页面大小,为 16K 大小,起始的虚拟地址为 swapper_pg_dir.PGD 全局页表只有物理地址对应的部分才被写值.
             PGD 后 1/4 是对应内核空间,但不代表后 1/4 的 PGD 表都被有对应的 PTE 页表.后面 1/$ 的 PGD 对所有的进程来说都是相同的.
         a. mem_map 负责将物理内存按 struct page 大小从低地址到高地址紧密排列在一起,形成一个数组.
             对应物理页面是否使用,要通过 struct page 的 _mapcount 和 _count 两个成员来判断.
  

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2016-07-08 21:00:1415-16赛季CBA联赛之同曦
日期:2017-02-15 14:26:1515-16赛季CBA联赛之佛山
日期:2017-02-20 14:19:2615-16赛季CBA联赛之青岛
日期:2017-05-07 16:49:1115-16赛季CBA联赛之广夏
日期:2017-07-30 09:13:1215-16赛季CBA联赛之广东
日期:2018-07-05 22:34:3615-16赛季CBA联赛之江苏
日期:2018-09-03 12:10:2115-16赛季CBA联赛之上海
日期:2018-09-25 03:49:2215-16赛季CBA联赛之广东
日期:2018-09-25 04:09:12
发表于 2016-02-04 11:11 |显示全部楼层
Buddy_Zhang1 发表于 2016-02-04 09:32
HI:
     1.内存分配中 malloc 和 kmalloc 负责的层次不同,malloc 是 GLIB 层,属于用户空间内存分配,kmall ...


感谢你回答的这么详细
我的问题主要对应于你回答的第8点中,要每个进程对内核空间的映射相同,其实有2种方法:①它们使用同一份PT;②它们使用不同的PT,但PT内容一样。

相当于,如果把PT当作一个变量,大家都用个指针指向这个变量,还是每个人自己有个这样的变量,只是保证内容一致?
如果每个人自己有一个“变量”,那其实就跟“私有”的味道一样了,它使用了公共的内核空间,其他人却“看不见”,所以想确认一下内核是不是用的方法①?

论坛徽章:
9
程序设计版块每日发帖之星
日期:2016-02-11 06:20:00程序设计版块每日发帖之星
日期:2016-02-14 06:20:00程序设计版块每日发帖之星
日期:2016-02-14 06:20:0015-16赛季CBA联赛之吉林
日期:2016-03-23 17:25:0015-16赛季CBA联赛之浙江
日期:2016-04-01 08:25:0615-16赛季CBA联赛之山西
日期:2016-04-01 10:09:1915-16赛季CBA联赛之广夏
日期:2016-06-03 15:58:212016科比退役纪念章
日期:2016-07-28 17:42:5215-16赛季CBA联赛之广东
日期:2017-02-20 23:32:43
发表于 2016-02-04 11:30 |显示全部楼层
回复 4# _nosay


    HI:
         内核在启动阶段会初始化一个全局的 struct mm_struct 结构体 init_mm,这个结构体其中的成员 pgd 就是指向 PGD 页表的.
         新的进程创建自己的页表的时候都是直接复制 init_mm->pgd 的全局页表,然后进程根据自己的映射只修改全局页表的 0 ~ 3G 部分,3G ~ 4G 部分保持和 init_mm->pgd 的一样.
         这样的结构就是所有进程的 struct mm_struct 的 pgd 对应的内核部分都是相同的.

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2016-07-08 21:00:1415-16赛季CBA联赛之同曦
日期:2017-02-15 14:26:1515-16赛季CBA联赛之佛山
日期:2017-02-20 14:19:2615-16赛季CBA联赛之青岛
日期:2017-05-07 16:49:1115-16赛季CBA联赛之广夏
日期:2017-07-30 09:13:1215-16赛季CBA联赛之广东
日期:2018-07-05 22:34:3615-16赛季CBA联赛之江苏
日期:2018-09-03 12:10:2115-16赛季CBA联赛之上海
日期:2018-09-25 03:49:2215-16赛季CBA联赛之广东
日期:2018-09-25 04:09:12
发表于 2016-02-04 11:35 |显示全部楼层
Buddy_Zhang1 发表于 2016-02-04 11:30
回复 4# _nosay


好的,太感谢了

论坛徽章:
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
发表于 2016-02-04 11:37 |显示全部楼层
由于页表是分级的,实际是方法1和方法2的混合体。

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2016-07-08 21:00:1415-16赛季CBA联赛之同曦
日期:2017-02-15 14:26:1515-16赛季CBA联赛之佛山
日期:2017-02-20 14:19:2615-16赛季CBA联赛之青岛
日期:2017-05-07 16:49:1115-16赛季CBA联赛之广夏
日期:2017-07-30 09:13:1215-16赛季CBA联赛之广东
日期:2018-07-05 22:34:3615-16赛季CBA联赛之江苏
日期:2018-09-03 12:10:2115-16赛季CBA联赛之上海
日期:2018-09-25 03:49:2215-16赛季CBA联赛之广东
日期:2018-09-25 04:09:12
发表于 2016-02-04 11:39 |显示全部楼层
本帖最后由 _nosay 于 2016-08-10 14:17 编辑

回复 7# nswcfd

每个目录表有1024个目录项,其中1/4指向用于内核空间映射的页表,即映射完整的内核空间需要256个页表,共占1MB内存。这1MB内存自内核启动后,就一直在吧?即使某个页表的表项全部为0,它所占的内存也不会释放,目录项也继续指向它。

用于内核空间映射的页表,不像用于用户空间映射的页表那样,页表项全为0时就释放,用于内核空间映射的目录表也是始终都有指向,是这样吧?


   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

DTCC2020中国数据库技术大会

【架构革新 高效可控】2020年12月21日-23日第十一届中国数据库技术大会将在北京隆重召开。

大会设置2大主会场,20+技术专场,将邀请超百位行业专家,重点围绕数据架构、AI与大数据、传统企业数据库实践和国产开源数据库等内容展开分享和探讨,为广大数据领域从业人士提供一场年度盛会和交流平台。

http://dtcc.it168.com


大会官网>>
  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP