Linux中没有为线程设置专门的数据结构,而是使用进程来模拟线程,结果就是我们现在所使用的pthread库,这个库不是Linux给我们提供的,而是后来的系统工程师使用Linux提供的进程接口打包出来的线程库。
那么当一个线程被创建的时候,“线程”是如何存储的呢?“线程”产生的临时数据又放在哪?
目录
一、线程创建前后,pthread库所在位置
Linux一切皆文件,pthread库也是一个文件,由于pthread属于第三方库,并不会一开始就被加载到内存中,所以在线程被创建之前,pthread库在磁盘中!!
当一个进程被创建,而且这个进程需要使用第三方库pthread,此时pthread库就被加载到(物理)内存中,OS会通过页表,给进程的虚拟内存和物理内存建立起映射关系,此时pthread库就会出现在进程的视野中了!
无论有多少个进程,物理内存中的pthread库都只要一份,其他的都可以通过页表映射到虚拟内存中。栈区和堆区之间的区域是共享区,一般我们所知道的共享内存、动态库都是放在这个区域!
二、“线程”放在哪??OS怎么找到“线程”??
既然Linux不给我们提供线程对应的数据结构,但是pthread库里给我们提供了!
从上面我们知道,主线程创建以后,pthread库放在虚拟内存的共享区,每当创建一个线程,这个区域就会多一个线程的数据结构来存储线程的私有数据!
从图中我们可以看到,不光是表示线程的数据结构,还有线程栈也都在第三方库所在区域中,由第三方库来管理。这也同时解释了,系统工程师在设计的时候,是如何将私有数据和共享数据给区分开的。这就回答了我们的第一个问题“线程放在哪?”
第二个问题“怎么找到线程?”为了便于OS找到线程并获取对应的线程ID,我们使用线程在虚拟内存中的地址作为线程ID,也就是每次通过pthread_self()函数获取线程ID、测试时看到的一长串数字!
上面这个图只是画出了一个线程所包含的内容,如果存在多个线程,那么第三方库中就应该存在多个这样的结构
三、pthread_t tid 和 LWP 的关系
上面我们谈到了线程ID其实就是 在虚拟内存中的一个地址,但是我们之前在测试的时候,为了区分是否创建了新的线程,我们在命令行输入 ps -aL 查看轻量级进程时,看到了LWP
主线程的PID和LWP是一样的,新线程的不一样,所以我们得出新线程确实产生了的结论,但是这里的LWP的数字和线程ID有什么联系吗??
==》答案是两者的关系是一一对应的,都可以用来表示线程ID。只不过,LWP是在内核中的表现,pthread_t tid是在用户层面的体现
那么pthread_t tid是如何跟LWP对应上的呢?类似于IO中的文件结构体struct file会包含文件描述符fd,动态库管理的线程结构体struct thread 也会包含LWP