Linux 进程栈与线程栈大小

前段时间和同事一块追一个多线程下栈溢出的bug,究其原因是引用的外部静态库中某个局部的字符串buffer太大导致(1MB),而程序中反复review并没有申请太大的栈空间,当时有怀疑栈空间本身太小,最后通过修改静态库的该buffer大小定义解决,问题看似解决,实则反应对进程和线程的理解不扎实,代码中潜在的问题并没有彻底消除(后来在分析thrift nonblockserver源码时发现是因为默认调用创建IO线程栈指定了大小为1MB),由此本文讨论Linux 下fork或exec调用创建的进程对应栈以及clone调用创建的线程栈。

先从操作系统的角度来复习下基础知识,进程是操作系统进行资源分配的基本单位,线程是CPU进行调度和分派的基本单位。我们通常意义下的进程包括:由二进制代码组成的应用程序、单线程、分配给该应用程序的一组资源(如内存、文件等),一个linux下进程对应的代码中并没有通过NPTL pthred_create显示调用创建线程实际看做只有一个主线程,one thread‘s process,通常多线程编程下默认是依附于该进程的众多线程(当然也可以分离detach);再回过来看栈这个说法,wikipedia上叫callstack调用栈,并不是孤立的有进程栈这个说法,进程只是在分配时通过如随机化方式指定了栈底的初始地址,进程的子线程们有各自的私有栈,可以共享父进程分配的堆内存空间,只有一个主线程的进程也就是有主线程对应的栈,所以栈这个说法通常只有线程栈,并没有明确的进程栈之说,那就更没有所谓的进程栈大小了。

我们通常使用ulimit -s可以看到”进程对应栈“的大小(现代linux系统下通常是8MB大小),不论在只有一个主线程的进程中,还是包含许多子线程的进程,都是指线程栈大小,默认8MB,pthread_create创建的线程就是对应这个值。

再者,根据引用7中的文章,线程栈的空间开辟在所属进程的堆区,线程与其所属的进程共享进程的用户空间,所以线程栈之间可以互访。

refer:
1. https://en.wikipedia.org/wiki/Call_stack
2. http://stackoverflow.com/questions/2131832/whats-the-difference-between-a-threads-stack-and-a-processs-stack
3. http://stackoverflow.com/questions/1762418/process-vs-thread
4. http://stackoverflow.com/questions/13749626/how-to-measure-the-stack-size-of-a-process
5. http://web.stanford.edu/class/cs140/cgi-bin/lecture.php?topic=process
6. 《深入linux内核架构》
7. http://blog.csdn.net/daniel_ice/article/details/8146003

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注