zoukankan      html  css  js  c++  java
  • linux do_mmap

    do_mmap 函数自己本身并不真做 mmap, 它基本上只是检查参数, 准备必要的数据结构; 但这也不是没有可说的, 事实上, glibc 函数 mmap 的需要注意的点, 再这个函数里面还真有几个。

    先看 mmap 原型

    void* mmap(void* addr, sie_t length, int prot, int flags, int fd, offset_t offset)

    参数含义可以 man, 不多说, 单看几个 prot | flags 偏门组合:

    1. PROT_READ | MAP_SHARED

    这意思是, 我只读, 但别人的写得给我看到;

    那么这个和 PROT_READ | MAP_PRIVATE 有区别吗?先从字面意思理解 PROT_READ | MAP_PRIVATE, 似乎是说, 我只读, 别人写的也别给我看到; 但实际上并非如此, 任意的写, PROT_READ | MAP_PRIVATE 还是能看到, 只要写的那方别是 COW 就成。 其实似乎 PROT_READ | MAP_PRIVATE 这个组合似乎不是没意义, 至少可以用来做某具体时间文件内容的 snapshot; 但事实现在就是如此。

    虽然没区别, 但这两个组合一旦再于  MAP_ANONYMOUS 或 fd  组合起来, 就有点其他问题了;

    单说 fd, 忽略 MAP_ANONYMOUS, 因为这两个其实表达一个意思; 虽然优先起作用的是 MAP_ANONYMOUS, 但 fd 写起来简单。

    fd != -1, 说明有 backup storage,  fd == -1, 说明是再 shm 文件系统分配的一个叫做 dev/zero 的文件, 这个文件系统挂在 /dev/shm 目录下, 但这个文件 ls 这些命令是看不到的, 涉及到 readdir 实现及 vfs 逻辑, 不说。

    fd != -1 的情况下, 似乎本方永远不会 COW, 因为 read 嘛, 永远不会写, 不管 MAP_PRIVATE, 还是 MAP_SHARED。

    然而, do_mmap 的实现中存在这这样一个逻辑, 就是如果 fd 是以 read 方式打开的, 则更改 MAP_SHARED 为 MAP_PRIVATE。 为啥?

    因为一个特殊情况, 在调试器中加断点, 由于代码是以 read 方式打开的, 以 MAP_SHARED 方式映射的, 如何处理? 一个是不允许加, 因为是 MAP_SHARED 嘛, 一旦加了, 就真的写入磁盘了, 这个跟 read only 的打开方式矛盾, 也情理之中不允许。 另一个办法是允许加, 但如何避免将这个断点写入磁盘呢, 采取的措施就是将 MAP_SHARED 改成 MAP_PRIVATE。 就像 map 的时候本来就是 MAP_PRIVATE 方式 map 的一样。 但还是有问题, 加完断点后, 这个被修改的页面就 COW 了, 这个页面被其他的人修改了怎么办, 因为 MAP_SHARED 语意是要求看到其他方的修改的。 这里没有处理措施, linus 原话:

    “  so it's clearly not "correct" either, but it's certainly a million times better than writing out breakpoints to shared files..”。

    fd == -1 的情况呢? 自然之前的问题都可以解决了, 本来就是 PRIVATE 语意嘛; 看不到是自然的, 被修改后 COW 也是自然的;

    2。 再看 MAP_SHARED | PROT_WRITE 与 MAP_PRIVATE | PROT_WRITE

    这个没什么可说, MAP_SHARED | PROT_WRITE 允许写, 并被更新到磁盘, 只要 fd 是以可写方式打开的, 如果fd 不可写, 则 mmap 会失败;

    整体看起来有点古怪的是,  MAP_SHARED | PROT_READ 可以映射 read only 的 fd, 然后 mmap 还允许它写(通过将MAP_SHARED 改成 MAP_PRIVATE);  MAP_SHARED | PROT_WRITE 却没有这样的待遇, 并不能通过自动降到 MAP_PRIVATE 而在 read only 的 fd  上映射, 唯一原因, 只不过这里很显然是不合理的组合, 而上面那个是没办法了, 只能开后门来支持调试器。

    MAP_PRIVATE | PROT_WRITE 允许写,不更新到磁盘。然而 fd 则又需要注意, 不管它是不是以可写方式打开的, 都允许写, 这个似乎又有点和 fd open 时的语意冲突; 但现实就是这样的。

  • 相关阅读:
    Leetcode 242.有效的字母异位词 By Python
    Leetcode 344.反转字符串 By Python
    Leetcode 217.存在重复元素 By Python
    js 动态加载select触发事件
    MUI 里js动态添加数字输入框后,增加、减少按钮无效
    【 jquery 】常用
    MySql 常用语句
    CSS 选择器 知识点
    HTML 符号实体
    log4net 配置
  • 原文地址:https://www.cnblogs.com/zylthinking/p/2854612.html
Copyright © 2011-2022 走看看