堆栈中存储了哪些系统数据

时间:2011-12-12 22:51:12

标签: linux gcc pthreads

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

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

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

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

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

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

2 个答案:

答案 0 :(得分:4)

在Linux NPTL上:

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

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

在新线程实际开始运行之前,这主要是在pthread_create__pthread_create_2_1 nptl/pthread_create.c __thread中初始化的,如果你在eglibc源代码中跟随)。

TCB下面是静态分配的l_tls_offset变量 - 或者至少是链接器在启动时可以识别的变量。动态链接器初始化链接器映射中的__thread字段,以告知NPTL代码要保留多少空间。请注意,在程序启动后加载的库不会成为其中的一部分 - 有关详细信息,请参阅__thread ABI spec

start_thread()变量下面是堆栈。这个堆栈的顶部是{{1}}代码,所以它在实际执行用户代码之前仍然是一种方式(但不会太多)。

答案 1 :(得分:0)

  

堆栈分配和对齐如何与Linux x86_64上的pthread一起使用

子线程中的“堆栈”实际上只是一块内存,通常是malloc'd(内部可以通过mmaping匿名区域实现),尽管你也可以使用原始堆栈区域本身,只要它保持有效在线程的生命周期中,例如

char foo[2<<20];
pthread_attr_t attr;
pthread_t tid;

pthread_attr_init(&attr);
pthread_attr_setstack(&attr, foo, sizeof(foo));
pthread_create(&tid, &attr, func, NULL);
pthread_join(tid, NULL);