我在书上读到过一个linux的线程大概占8M内存。
然而从一些人那里得到类似的描述说,其实没有那么多,有说法的线程的内核栈是8k的物理空间,还读到过下面的说法:
“linux的栈是通过缺页来分配内存的,不是所有栈地址空间都分配了内存。因此,8M是*最大*消耗,实际的内存消耗只会略大于实际需要的内存(内部损耗,每个在4k以内)。”
读到这些我就有点懵了,所以想请教两个问题
1.一个linux 线程到底占有多大内存(虚拟的,物理的)?
2.java中的线程是不是也有类似的说法?默认说一个线程1M,实际内存没有那么大。
通过缺页来分配内存这个描述基本上是准确的。你申请一块内存,操作系统不是马上给你一块实际内存,而只是给你一个逻辑地址,当你真的访问这段地址时,操作系统才会进行逻辑地址到物理地址的映射。所以才会有物理内存和虚拟内存两个概念,如果一样的话,也就没有区分的必要了。
至于具体占用是多少,我认为明白原理就行了,硬记这个数字没什么必要。顺便 8 MB只是系统默认设置,并不是定死的,可以通过 ulimit 之类的命令修改。
一个task_struct 几千行加上一个运行栈 需要几k
默认的话,那个8M是进程栈,也是主线程的栈,如果是64位系统那么就是在进程地址空间的0x0000,7FFF,FFFF,FFFF处并向下生长,这个地址比较高,然后这个8M对于99%的程序都是够用的,很少超过64k的,而且这个可ulimit重配置的。
如果在此基础上再创建一个线程,那么我们要mmap或者malloc申请一个区域作为新线程的栈,8k,16k,32k都行,出了事自己承担。而这个区域是在进程地址空间的内存映射区或者堆区,地址比较低。
一个线程占多大内存,谈task_struct结构本身占多大的内存没有意义因为那是线程实现的硬损耗,线程栈才是有意义的毕竟线程总归要跑用户代码的。
线程是调用cpu的最小单位,它占用多少内存,是要看线程内部代码要分配的内存,图像处理和压缩线程调用内存可能很多。至于你说的执行线程需要分配的上下文环境需要最小内存,可能不同的系统或者相同系统设置也可能不同。确切的数据可以参考系统说明书。
每个线程创建时都会共享进程的地址空间,另外在这里面分配8MB的虚拟内存用作线程调用栈(可以使用ulimit更改)。
由于缺页机制, 只会将用到的块调到物理内存中,而绝大部分线程需要用到的块很少,一个块默认是4k, 所以只需要几十k的真实物理内存。
linux线程其实也是一个进程,只不过原进程fork的时候设置了共享资源和地址空间。
所以不算共享内存,差不多就那么多。