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

bar*_*sju 3 c mmap pthreads

我试图监视我的线程的堆栈使用情况.要做到这一点,我需要知道线程堆栈的地址,我发现这样做的唯一方法是使用设置堆栈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);
Run Code Online (Sandbox Code Playgroud)

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

第二个问题,这个内存会在线程死亡时自动释放吗?如果您不确定,有没有办法找出它是否已被释放?

R..*_*R.. 7

"监视器"是什么意思?如果您只是想确保不会浪费太多空间来堆栈(这会阻止您在32位系统或具有低ram +交换的系统上拥有大量线程),您应该只使用该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_setstacksize.pthread_attr_setstack应该只用于你现在可能正在做的开发时间的黑客攻击.