进程下多线程的内存模型
你是不是也是进程与线程傻傻分不清?内存管理是不是搞得你焦头烂额?一个进程到底能够有多少个线程?不搞清楚誓不罢休!
一.进程与线程
进程:资源(CPU、内存)分配的基本单位。
线程:CPU调度和分配的基本单位。
以上概念似乎耳熟能详,实际到底啥意思却还不知所以然。
首先时进程四要素:
1.有一段程序供其执行,不一定专用,可以与其他进程共用。
2.有专用的内核堆栈空间。
3.在Linux内核中有进程控制块task_struct,供内核调度器识别并参与调度。
4.有独立的用户堆栈空间。
以下为Linux下一个进程所分配的虚拟内存空间:
Linux系统下为进程分配4G的虚拟内存大小,其中低字节3G内存为用户空间,高字节1G为内核空间。
内存空间主要有四大部分组成:.text(代码段)、.bss与.data的全局存储区、堆区和栈区。
在32为Linux系统下,栈区大小为一般10M,可通过命令 ulimit -s或者ulimit -a 可以查看默认栈大小,也可通过命令ulimit -s+参数,临时修改线程栈大小。
而堆的大小为剩余的用户内存空间,既堆的大小 < 3G -(环境变量+命令行参数+栈+共享库+.bss+.data+.text等)。在单线程下堆的空间远大于栈。
二.多线程内存模型
那么一个进程能创建多少线程与什么有关呢?多线程之间数据如何共享呢?
以下为省略了内核空间的三线程的内存模型:
可从以上得知,
栈:是每个线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立,因此,栈是thread safe的,操作系统在切换线程的时候会自动的切换栈。
堆:为所有线程共有的,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是已经分配的空间。
多个线程通过内核CPU调度子系统进行调度,在代码段执行,使用独有栈区和公有堆区与全局存储区的资源。因此同一进程的多线程之间所有在非栈区的数据都是共享的。
一个进程能创建多少个线程由剩余堆的大小决定,若一个线程栈大小为10M,则理论上创建的线程个数少于3,221,225,472/(1024102410)=307,减去栈区以外的内存大小,实际创建线程数为300个左右。