免费注册 查看新帖 |

Chinaunix

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

mmap 映射匿名页面时 MAP_SHRED 与 MAP_PRIVATE 为什么实现机制不同 [复制链接]

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-02-14 16:35 |只看该作者 |倒序浏览
本帖最后由 zylthinking 于 2012-02-14 16:38 编辑

看代码是发现 MAP_SHARED, -1 这个组合的实现和 MAP_PRIVATE, -1  这个组合不同, 但我相不明白到底为什么有这个不同。
我查看了 2.6 的代码, 发现和我所看的 2.4 代码大体一致, 帖个 2.4 的上来:


        if ((vma->vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE &&
            !(flags & MAP_NORESERVE)                                 &&
            !vm_enough_memory(len >> PAGE_SHIFT))
                goto free_vma;

        if (file) {
                if (vma->vm_flags & VM_DENYWRITE) {
                        error = deny_write_access(file);
                        if (error)
                                goto free_vma;
                        correct_wcount = 1;
                }
                vma->vm_file = file;
                get_file(file);
                error = file->f_op->mmap(file, vma);
                if (error)
                        goto unmap_and_free_vma;
        } else if (flags & MAP_SHARED) {
                error = shmem_zero_setup(vma);
                if (error)
                        goto free_vma;
        }


int shmem_zero_setup(struct vm_area_struct *vma)
{
        struct file *file;
        loff_t size = vma->vm_end - vma->vm_start;
        
        file = shmem_file_setup("dev/zero", size);
        if (IS_ERR(file))
                return PTR_ERR(file);

        if (vma->vm_file)
                fput (vma->vm_file);
        vma->vm_file = file;
        vma->vm_ops = &shmem_shared_vm_ops;
        return 0;
}

按照实现, 我尝试使用 shm_open 去尝试打开 dev/zero, 发觉不行, 仔细想想, 原来是 dev/zero 保证了内核会去找 dev 目录下的 zero 文件, 而不是名称为 dev/zero 的文件
因此, 到现在还在疑惑我, 内核这么实现, 到底是想为什么操作提供便利

还有几个小问题还没来得及想:
1。 shmem_zero_setup 创建的 file 何时释放
2。 为何 path_walk 能够忽略这些(很可能多余一个, 因为每个 mmap 都可能会创建一个新的) dev/zero 为名称的文件
有了解者, 请不吝赐教

论坛徽章:
0
2 [报告]
发表于 2012-02-15 15:25 |只看该作者
> 我尝试使用 shm_open 去尝试打开 dev/zero, 发觉不行
这是啥意思,我看的是2.6.34的代码,shm_open是ipc里的静态函数啊。

> shmem_zero_setup 创建的 file 何时释放
这个应该跟普通文件的处理一样吧,创建的时候有一个引用计数,引用计数减为0就释放了,内核里调shmem_zero_setup的地方应该不多,一个典型就是mmap的时候,那在munmap的时候就会减少这个引用计数吧。

> 为何 path_walk 能够忽略这些(很可能多余一个, 因为每个 mmap 都可能会创建一个新的) dev/zero 为名称的文件
没太看懂这个问题,看了下shmem_zero_setup的相关代码,也感觉很奇怪,这里的"dev/zero"似乎只是一个字符串,跟/dev下面的zero文件好像没关系,在tmpfs文件系统的根挂载目录下申请名为"dev/zero"的dentry,而且在该挂载目录下可能有多个同名的dentry,不太明白。
至于为什么匿名共享跟匿名私有映射有这样的实现区别,我想可能匿名共享如果要实现进程间的通信,其地址空间映射到同一物理内存上的实现必须要有一个文件载体吧,因为不需要该文件具有普通文件的特性,所以在tmpfs下申请一个特殊的文件即可。


还有很多不明白的地方,等高手!

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
3 [报告]
发表于 2012-02-15 15:45 |只看该作者
1. 我说的是用户层库函数 shm_open, 其实就是一个 open() 的包装
2. 已经想通了, 当时晕头了
3. 也是我晕头了, path_walk 肯定会忽略, 因为它本来就是一个寻找特定路径的文件的函数, 只要不是期待的文件, 一律忽略; 我实际想知道的是用户层的 readdir 是不是做了什么手脚故意忽略这些文件, 否则, ls /dev/shm/ 下应该会列出多个名叫 dev/zero 的文件

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
4 [报告]
发表于 2012-02-15 15:50 |只看该作者
allen303allen 发表于 2012-02-15 15:25
至于为什么匿名共享跟匿名私有映射有这样的实现区别,我想可能匿名共享如果要实现进程间的通信,其地址空间映射到同一物理内存上的实现必须要有一个文件载体吧
这是啥意思,我看的是2.6.34的代码,shm_open是ipc ...


不需要, 只要是匿名页面就行, 比如 malloc 出的页面均可潜在可被共享, 之所以不被共享, 其实是 vma->vm_flags 中的 VM_SHARED 标志的功劳;
但在这里, 其实 VM_SHARED 是被设置上的, 那么, 就算相应页面不和 shmfs 相关联, 同样会在 fork 后被共享,
因此, 才感觉非要和 shmfs 做一个关联, 又没有任何可被察觉的好处, 有些疑惑

论坛徽章:
0
5 [报告]
发表于 2012-02-15 16:37 |只看该作者
> 我实际想知道的是用户层的 readdir 是不是做了什么手脚故意忽略这些文件, 否则, ls /dev/shm/ 下应该会列出多个名叫 dev/zero 的文件
那您认为/dev/shm/下面没有列出dev/zero文件的原因是什么呢?
我注意到shmem_file_setup中对inode的申请及初始化比较特殊,比如dev参数为0,可能是这样决定了tmpfs下的文件只驻留内存的特性。

> 不需要, 只要是匿名页面就行, 比如 malloc 出的页面均可潜在可被共享, 之所以不被共享, 其实是 vma->vm_flags 中的 VM_SHARED 标志的功劳;
> 但在这里, 其实 VM_SHARED 是被设置上的, 那么, 就算相应页面不和 shmfs 相关联, 同样会在 fork 后被共享,
> 因此, 才感觉非要和 shmfs 做一个关联, 又没有任何可被察觉的好处, 有些疑惑
这里的匿名页面除了上面提到的通过匿名共享映射时创建的tmpfs下的临时文件对应的页面,还有其他的什么情况呢?
内存映射的共享应该只跟mmap时的file参数和共享标志位有关吧,你的描述看得我有点蒙,可能你关注了一些用户态的东西,而我只考虑内核部分。

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
6 [报告]
发表于 2012-02-15 16:55 |只看该作者
readdir 我还没看呢, 说不出来
tmpfs 也好, shmfs 也罢, 包括 devfs,  只存在与内存是因为 address_space readpage, writepage 做了相应的逻辑, 并没有去真正读写磁盘上的文件; 就算读写了, 其实也是 swap 中的页面

我的意思是, 任何页面, 只要和 vma 关联上, 而 vma->vm_flags & VM_SHARED != 0  的情况下, 经历 fork后都能保证父子进程共享该页面; 而不会出现 COW 情况;如果 malloc 的 vma 存在 VM_SHARED 标志, 那么也会共享; 但我不是说 malloc 的会有 MAP_SHARED 情况, 只是打个比方。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP