RHEL6中线程的最大虚拟内存分配

时间:2015-12-16 06:19:04

标签: c multithreading memory rhel6

由于RHEL6引入了新的竞技场分配器设计,因为对于单个线程增加了相同数量的竞技场,这导致更多的虚拟内存使用。 RHEL6为每个线程分配单独的内存块。根据我对32/64位系统的理解,每个线程的竞技场数量计算如下:

On 32 Bit system  : 
Number of Arena = 2 * Number of cores .
On 64 Bit system :
Number of Arena = 8 * Number of cores . 

请确认我的理解是否有一些差距。

我的机器有4个内核和64位系统,

$ lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                4
On-line CPU(s) list:   0-3
Thread(s) per core:    2
Core(s) per socket:    2
Socket(s):             1
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 69
Stepping:              1
CPU MHz:               759.000
BogoMIPS:              4589.41
Virtualization:        VT-x
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              3072K
NUMA node0 CPU(s):     0-3
$ uname -a
Linux admin 3.13.0-71-generic #114-Ubuntu SMP Tue Dec 1 02:34:22 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

因此每个线程有4 * 8 = 32个竞技场。每个竞技场的最大尺寸为64MB; pet thread虚拟内存可以达到32 * 64 = 2GB(每个线程)。 如果我的理解是正确的,请告诉我。

我创建了一个示例程序。它被分配了1.5 GB的堆内存。

#include <pthread.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <unistd.h>

static void *thread(void *arg)
{
  int i=0;
  char *x[1024];
  unsigned int pid;
  char str[15];
  char cmd[30]="cat /proc/";
  pid = getpid();
  sprintf(str, "%d", pid);
  strcat(cmd,str);
  strcat(cmd,"/status");
  system(cmd);
  for(i=0;i<1536;i++)
  {
    x[i] = malloc(1*1024*1024);
    printf("Memory Allocated %d:\n ",i);
    system(cmd);
  }
  for(i=0;i<1536;i++)
  {
    *x[i] = 5;
    free(x[i]);
  }
  return NULL;
}

int main(void)
{
   unsigned i;
   pthread_t t;
   pthread_create(&t, NULL, thread, NULL);
   pthread_join(t, NULL);
  return 0;
}

线程t是堆内存分配小于2GB。但是在分配1GB大约后会产生coredump。有关详细信息,请参阅以下详细信息:

Name:   arena
State:  S (sleeping)
Tgid:   12511
Ngid:   0
Pid:    12511
PPid:   4417
TracerPid:  0
Uid:    1000    1000    1000    1000
Gid:    1000    1000    1000    1000
FDSize: 256
Groups: 4 24 27 30 46 108 124 129 1000 
VmPeak:  1133924 kB
VmSize:  1133924 kB
VmLck:         0 kB
VmPin:         0 kB
VmHWM:      4568 kB
VmRSS:      4568 kB
VmData:  1127636 kB
VmStk:       136 kB
VmExe:         4 kB
VmLib:      2012 kB
VmPTE:      2092 kB
VmSwap:        0 kB
Threads:    2
SigQ:   0/46560
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000006
SigCgt: 0000000180000000
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000001fffffffff
Seccomp:    0
Cpus_allowed:   ff
Cpus_allowed_list:  0-7
Mems_allowed:   00000000,00000001
Mems_allowed_list:  0
voluntary_ctxt_switches:    1027
nonvoluntary_ctxt_switches: 4

为什么coredump会产生?我的上述理解是不正确的,计算线程最大虚拟内存?

如果达到虚拟内存最大限制,会发生什么后果 请注意我已将ulimit设置为无限

$ ulimit
unlimited

2 个答案:

答案 0 :(得分:0)

  

为什么要生成coredump?

你有

  char *x[1024];
  …
  for(i=0;i<1536;i++)
  {
    x[i] = malloc(1*1024*1024);

- 阵列溢出的普通情况。

答案 1 :(得分:-1)

内存分配通常不是特定于任何分发。通常,分配器是glibc实现。但是,线程可以分配的内存量应该是内核的函数,而不是分配器的函数。你无法分配内存的一些原因可能包括耗尽物理内存,耗尽交换内存,ulimit,cgroups等......

如果你仍然怀疑分配器,你可以尝试使用mmap直接将内存映射到进程中。