我试图了解在具有gcc的Linux x86_64系统上,堆栈分配和对齐方式如何与pthread一起使用,以及系统在堆栈上存储哪些数据。我知道您可以使用pthread_attr_setstack配置堆栈内存。我已经在执行以下操作的测试程序中完成了此操作:

1)递归调用自身并更新在堆栈上分配的未初始化数组

2)打印出第一个数组元素,最后一个元素和rsp的值

由此,我可以观察到rsp如何递增(在我的测试程序中,我注意到编译器内联了一些递归调用)。我还能够看到添加TLS内存(带有__thread变量)会导致rsp的第一个值降低。因此,似乎TLS变量分配在堆栈的顶部。

但是,我不确定还有什么。在我看来,堆栈的第一页是以某种方式为系统保留的,因为我分配的堆栈变量都没有以该区域结尾。即使我不使用任何__thread变量,我实例化的变量似乎也不会分配在第一页中(我将堆栈内存设置为页面对齐)。

所以我的问题是:除了TLS数据和堆栈变量外,pthread堆栈上还有什么(如果有的话)?

最佳答案

在Linux NPTL上:

堆栈的最顶部包含TCB。这也称为struct pthreadpthread_t。由于所有怪异的glibc系统特定的定义,这有点毛茸茸,但基本上它包含以下内容:

  • TLS header (此部分不包括实际的TLS值)
  • 各种标志
  • 跟踪缓存堆栈的链接列表
  • TID(和堆栈使用中标志)
  • PID
  • 健壮的互斥锁跟踪信息
  • pthread_cleanup并堆栈展开信息
  • 取消状态
  • 甚至更多标志
  • pthread_setspecific使用的一定数量的TLS插槽-如果超过此数量,其余的插槽将分配在堆
  • 各种锁
  • pthread_join的跟踪信息
  • 线程的返回值
  • 调度策略(来自线程属性)
  • 启动例程和线程参数
  • 堆栈大小跟踪数据

  • 在新线程实际开始运行之前,这主要是在pthread_create中初始化的(如果您正在eglibc源代码中,则是__pthread_create_2_1中的nptl/pthread_create.c)。

    TCB下方是静态分配的__thread变量-或至少链接程序在启动时可以识别的变量。动态链接器在链接器映射中初始化l_tls_offset字段,以告诉NPTL代码保留多少空间。请注意,程序启动后加载的库将不属于此部分-有关详细信息,请参见 __thread ABI spec
    __thread变量下面是堆栈。堆栈的顶部是start_thread()代码,因此它仍然是实际执行用户代码之前的一种方式(但不要过多)。

    关于linux - 哪些系统数据存储在堆栈中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8482079/

    10-11 22:05
    查看更多