gpt4 book ai didi

c - 如何为 pthread 堆栈正确分配内存

转载 作者:太空狗 更新时间:2023-10-29 16:02:44 25 4
gpt4 key购买 nike

我正在尝试监控线程的堆栈使用情况。为此,我需要知道线程堆栈的地址,我找到的唯一方法是使用 pthread_attr_setstack() 设置堆栈。

我目前正在使用 mmap 分配内存:

   pthread_attr_t ptAttr;
pthread_t pth;
pthread_attr_init(&ptAttr);
void *stack = mmap(NULL, stksize, PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_SHARED, -1, 0);
pthread_attr_setstack(&ptAttr, stack, stksize);
pthread_create(&pth,&ptAttr,threadFunc,&info);

那么第一个问题,这是使用 mmap 分配内存的好方法吗?标志是否正确?我应该改用 malloc 吗?这将在没有虚拟/交换内存的低资源设备上运行。

第二个问题,这个内存会不会在线程死掉的时候自动释放?如果您不确定,有没有办法查明它是否已发布?

最佳答案

“监控”是什么意思?如果您只是想确保不会为堆栈浪费太多空间(这会阻止您在 32 位系统或具有低 ram+swap 的系统上拥有大量线程),您应该简单地使用 pthread_attr_setstacksize 函数而不是 pthread_attr_setstack。这样你就不用负责自己分配栈了。如果您担心线程会在堆栈上一次分配多个页面,您也可以选择使用 pthread_attr_setguardsize 来确保更大的保护页面区域作为保护,但请注意这会消耗你的虚拟地址空间。

如果您真的想测量 堆栈使用情况,pthread_attr_setstack 可能是正确的工具,但它一点也不简单。我将使用 mmap 分配内存,并将其设置为只读。然后安装一个 SIGSEGV 处理程序来 mprotect 可写的错误页面,增加一个计数器,然后返回。这将为您提供线程接触的实际页面数。由于信号处理程序将在故障线程中运行(这是有保证的,因为它是一个同步信号),您可以将计数保存在线程本地存储变量中以在多个线程上执行计数。

不过,在调用 pthread_create 之前,您实际上可能需要使最后一两页可写,因为第一次写尝试可能会从父线程发生,并且您可能不希望信号如果您尝试将结果存储在线程本地存储中,则处理程序在那里运行。

要在最后访问您的具体问题:

  1. 您不需要 MAP_SHARED。该标志用于将在进程之间共享的内存。它可能不会对你的情况造成伤害,但它具有误导性。使用 MAP_PRIVATE

  2. 内存不会被释放,而且正式地说,永远不会被释放。 POSIX 非常明确地指出,重用或释放给线程的堆栈是未定义的行为,因为您无法可靠地确定生命周期(即使在 pthread_join 返回之后,从概念上讲,线程可能仍在执行它的最后几条指令退出,因此仍然接触堆栈,并且它有可能无限期地保持停滞状态)。我相信这在 glibc/NPTL 上是不可能的,因为它们在线程退出时使用内核生成的 futex 唤醒事件以原子方式在线程退出时发出 pthread_join 信号,但是NPTL 可能会像这样缓存和重用您捐赠给线程的堆栈(因为无论如何您都不允许自己重用/释放它们)。为确保您必须检查来源。因此,我建议在生产代码中完全不要使用pthread_attr_setstack。使用 pthread_attr_setstacksizepthread_attr_setstack 应该仅用于开发时的 hack,就像您现在可能正在做的那样。

关于c - 如何为 pthread 堆栈正确分配内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10334248/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com