【问题标题】:Is there a thread-based mprotect?是否有基于线程的 mprotect?
【发布时间】:2013-08-26 05:29:33
【问题描述】:

mprotect() 用于保护内存页面,例如,使页面只读。它为整个进程设置了这种保护,也就是说,如果一个页面是只读的,则没有线程可以写入该页面。有没有办法为不同的线程以不同的方式保护页面?例如,1个线程可以写入页面P,而我程序中的所有其他线程只能从P读取。

【问题讨论】:

  • 操作系统内存安全处于进程级别。
  • mprotect 不能这样做。线程必须锁定他们想要持有的东西。您在线程中保护整个页面的动机是什么?你不能用锁(例如,当一个线程拥有写锁,而其他人都可以读)?
  • 即使面对应用程序错误,我也想保护这些区域,这就是为什么锁是不够的。是的,我知道mprotect 不是正确的方法,所以我想知道是否有任何方法可以实现。

标签: linux multithreading memory memory-management


【解决方案1】:

对于较新的 Intel CPU,您可以使用内存保护密钥 [1] 为进程中每个线程的不同访问设置。在 Linux 上,运行 lscpu 并检查 pkuospke 标志。

手册页 [2] 上的示例有点过时,因为不再需要手动调用相应的系统调用。相反,glibc 提供了以下 API 调用:

  • pkey_alloc() 分配一个新的密钥(16 个可用)
  • pkey_set() 设置给定密钥的权限
  • pkey_mprotect() 将密钥应用于给定的内存区域
  • pkey_free() 释放密钥

由于维护每个保护密钥的权限位的寄存器是线程本地的,因此每个线程可以有不同的保护设置。保护键设置只能进一步锁定通用设置,不影响指令获取。

[1]https://www.kernel.org/doc/Documentation/x86/protection-keys.txt

[2]http://man7.org/linux/man-pages/man7/pkeys.7.html

【讨论】:

    【解决方案2】:

    如果您在“克隆”系统调用中使用 CLONE_VM 标志创建线程(这就是您通常所说的线程),那么 MMU 设置与父线程的设置相同。

    这意味着两个线程都可以进行写访问。

    如果你不使用 CLONE_VM 标志,那么两个线程根本就没有共享内存!

    (pthread_create() 在内部设置 CLONE_VM 标志)。

    你可以做你想做的事——但这会很困难:

    使用共享内存函数(例如 shmget())而不是标准函数(例如 malloc())分配所有内存块。

    如果创建了新线程,请直接使用“clone()”而不是“pthread_create()”,但未设置 CLONE_VM 标志。

    共享内存在线程之间共享,由“正常”内存分配函数(例如 malloc())创建的线程不在线程之间共享。 mmap() 映射内存也是如此。

    当创建一个新线程时,这些内存块(由 malloc 或 mmap 创建)被复制,以便两个线程在同一地址拥有自己的内存块副本。如果一个线程写入此地址,则另一个线程将看不到更改。

    分配更多的“共享”内存相当棘手。如果只应该在分配线程和尚未创建的子线程之间共享内存,这很容易。在已经运行的线程之间或在不同的已运行线程的(间接)子线程之间共享内存是很困难的。

    线程没有共享堆栈内存,因此它们无法访问彼此的堆栈。

    默认情况下不共享全局变量和“静态”变量 - 要使它们在线程之间“共享”,需要进行一些棘手的编程。

    【讨论】:

    • 这是一个有趣的想法。如何让线程对共享数据拥有不同的权限?每个线程是否可以使用不同的PROT_ 标志在共享内存上调用mprotect()
    • 这实际上不太可能。 CLONE_SIGHAND 需要 CLONE_VM,CLONE_THREAD (linux.die.net/man/2/clone) 需要 CLONE_SIGHAND。因此,为了不共享内存映射,新线程必须是它自己的进程。如果您愿意为线程使用进程,那么这可以正常工作,但您不需要为此使用 clone()。
    • 是的 - 线程将是单独的进程。但是使用 fork() 系统调用将不起作用(因为那时不会共享内存)因此 clone() 将是唯一能够创建“类似线程”进程的系统调用。
    猜你喜欢
    • 2017-09-29
    • 2016-02-09
    • 2020-01-18
    • 2011-10-16
    • 2021-09-07
    • 2010-09-11
    • 1970-01-01
    • 1970-01-01
    • 2011-01-11
    相关资源
    最近更新 更多