Linux系统把所有线程都当做进程来实现,线程作为轻量级进程(LWP)。
线程仅仅被视为一个与其他进程共享某些资源的进程,而
是否共享地址空间几乎是进程和 Linux 中所谓线程的唯一区别
。线程创建的时候,加上了 CLONE_VM 标记,这样
线程的内存描述符 将直接指向 父进程的内存描述符
,也就是说,
线程的mm_struct *mm指针变量和所属进程的mm指针变量相同。
所有线程都共享一份地址空间,这不但包括text、heap和进程stack等,
甚至还包括了线程stack。
注意此处表达的字面意思:
所有线程共享包括线程栈在内的地址空间,并不意味着所有线程都共享一个栈地址,而是一个线程可以访问另一个线程的栈数据
(虽然并没什么用,但确实可行,通过实验可以验证)。显然,
不同线程有不同的函数调用关系所以不能使用同一个栈
。之所以能做到线程A能访问线程B的栈数据,正是因为内核为每个线程在不同地址处分配了栈空间,从进程的全局地址空间看(cat /proc/PID/maps),每个线程的stack都位于不同的地址段。
虽然线程共享地址空间,但线程的私有数据,又是需要单独保存的,这包括了:
pthread属性相关,pthread_attr
线程栈,thread stack
线程本地存储,TLS(thread local storage)
这三种数据位于同一块内存中,是在创建线程的时候,用mmap系统调用从heap分配出来的