【发布时间】:2023-03-08 05:05:01
【问题描述】:
Linux 中进程/线程的大小是多少?当一个进程/线程被创建时,连同task_struct 和其中的其他数据结构,还有什么其他的吗?
进程/线程的堆栈是否在进程/线程初始化时分配(固定大小)?还是在必要时分配(如虚拟内存)?
我如何知道标准进程/线程在内存中创建时的大小?
【问题讨论】:
标签: c linux multithreading kernel
Linux 中进程/线程的大小是多少?当一个进程/线程被创建时,连同task_struct 和其中的其他数据结构,还有什么其他的吗?
进程/线程的堆栈是否在进程/线程初始化时分配(固定大小)?还是在必要时分配(如虚拟内存)?
我如何知道标准进程/线程在内存中创建时的大小?
【问题讨论】:
标签: c linux multithreading kernel
当一大块内存(> pagesize = 4096 字节)在 Linux 上首次分配时,它会在页表中使用特殊的“空”内存页,这些内存页没有任何支持,所以当一个线程启动时,它会分配 ~这些零页中的 1 MB 用于线程堆栈。随着堆栈的增长,页面随后被转换为实际内存支持的页面。由于这种“空”页面的支持,通常可以有足够大的堆栈。
线程和进程都是使用称为 clone(2) 的相同底层系统调用创建的。它有很多选择,可以做很多事情。详细解释见man clone。
http://linux.die.net/man/2/clone
大块内存是通过匿名 mmap(2) 调用分配的。
您可能也有兴趣在网络上搜索“linux overcommit bit”
(如果你想完善你的问题,我可以更具体。)
【讨论】:
uname -a 时,我的堆栈大小限制为 8192 kb。这是每个进程/线程的上限吗?
Andrew 说的是真的,但这并不意味着您的线程/进程从创建的那一刻起就不会“使用内存”。为堆栈保留的空间总是在您的进程中消耗虚拟地址空间,这意味着对于大型线程堆栈,您将很快用完 32 位机器上的地址(默认线程堆栈只有大约 300 个线程) glibc 上的 -size 将耗尽虚拟地址空间)。此外,堆栈会产生提交费用,这决定了在禁用过度使用时可以分配的内存总量。
Linux 默认为主线程的堆栈预提交 128k,如果提交费用尚未用完,则允许自动获得更多。线程堆栈完全由用户空间(glibc/NPTL,在大多数 Linux 系统上)分配,并且不能超过其初始大小。根据版本和系统设置,glibc/NPTL 通常默认为每个线程分配 2 MB 到 10 MB 的空间。
【讨论】:
uname -a 显示的堆栈大小(以千字节为单位)是多少?最后一个线程的大小是thread_info struct + kernel stack (8KB) + thread stack (user stack, 2MB~10MB)的大小?