【问题标题】:Linux shared memory allocation on x86_64x86_64 上的 Linux 共享内存分配
【发布时间】:2011-10-17 12:34:08
【问题描述】:

我有 64 位 REHL linux,
Linux ipms-sol1 2.6.32-71.el6.x86_64 #1 SMP x86_64 x86_64 x86_64 GNU/Linux

RAM 大小 = ~38GB

我在 /etc/sysctl.conf 中更改了默认共享内存限制,并将更改的文件加载到内存中作为 sysctl -p

kernel.shmmni=81474836
kernel.shmmax=32212254720
kernel.shmall=7864320

仅作为实验基础,我已将 shmmax 大小更改为 32GB,并尝试使用 shmget() 在代码中分配 10GB,如下所示,但它无法一次性获得 10GB 共享内存,但当我将共享空间需求减少到8GB 它成功了关于我可能哪里出错的任何线索?

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>

#define SHMSZ 10737418240

main()
{
    char c;
    int shmspaceid;
    key_t key;
    char *shm, *s;
    struct shmid_ds shmid;

    key = 5678;
    fprintf(stderr,"Changed code\n");

    if ((shmspaceid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0) {
        fprintf(stderr,"ERROR memory allocation failed\n");
        return 1;
    }


    shmctl(shmspaceid, IPC_RMID, &shmid);
    return 0;
}

问候 喜满洲

【问题讨论】:

  • 您的 shmall 大小似乎假定 getconf PAGE_SIZE 是 4096。您确认了吗?
  • 平。你有没有想过这个?我很好奇答案是什么,因为这是其他人可能会在我们自己的项目中遇到的问题。

标签: linux


【解决方案1】:

我不确定这个解决方案是否也适用于共享内存,但我从正常的 malloc() 调用中知道这种现象。

当您在这里尝试时,通常无法分配非常大的内存块。函数调用的意思是“为我分配一块 10737418240 字节的连续内存”。很多时候,即使总的系统内存理论上可以满足这一需求,隐含的“一块连续内存”也会迫使可分配内存的限制要低得多。

内存中的程序结构、加载的程序数量都可能导致阻塞某些内存区域,并且不允许有 10 GB 的连续内存可分配。

我经常发现重新启动会改变这一点(因为程序被加载到堆上的不同位置)。您可以通过以下方式尝试最大可分配块大小:

int i=1024;
int error=0;
while(!error) {
  char *a=(char*)malloc(i);
  error=(a==null);
  if(!error)
    printf("Successfully allocated %i.\n", i);
  i*=2;
}

希望这有助于或适用于此处。我在检查为什么无法为 JVM 分配接近最大系统内存时发现了这一点。

【讨论】:

  • 它不应该是 10GB 的连续 RAM。它只需要几乎是连续的,并且在 64 位虚拟空间中应该有足够的空间来找到 10GB 的块。
  • 上面我只是写了一个示例程序来挑出问题,对连续共享内存的真正需要是它的数据库配置要求大型内存数据库连续拥有至少10GB的共享内存,w /o 它无法运行。但无论如何感谢您的 cmets,至少我知道我需要寻找的地方。
  • 所以这实际上是你的问题?那么接受我的解决方案怎么样? :)
  • 嘿 0xCAFEBABE 您的解决方案不适用。
【解决方案2】:

在黑暗中射击:您没有足够的交换空间。默认情况下,共享内存需要在交换中保留空间。您可以使用SHM_NORESERVE 禁用此行为:

http://linux.die.net/man/2/shmget

SHM_NORESERVE(自 Linux 2.6.15 起)此标志用于相同目的 作为 mmap(2) MAP_NORESERVE 标志。不要为此保留交换空间 部分。当交换空间被保留时,可以保证它是 可以修改段。未预留交换空间时 如果没有可用的物理内存,可能会在写入时获得 SIGSEGV。看 还讨论了文件 /proc/sys/vm/overcommit_memory proc(5).

【讨论】:

    【解决方案3】:

    我只是在看这个,我建议打印出确切的 errno 值和问题描述,而不是仅仅指出它失败了。例如:

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    
    //#define SHMSZ 10737418240
    #define SHMSZ 8589934592
    
    int main()
    {
        int shmspaceid;
        key_t key = 5678;
        struct shmid_ds shmid;
    
        if ((shmspaceid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0) {
            fprintf(stderr,"ERROR with shmget (%d: %s)\n", (int)(errno), strerror(errno));
            return 1;
        }
    
        shmctl(shmspaceid, IPC_RMID, &shmid);
        return 0;
    }
    

    我尝试在我的 16 GB 系统上使用 8 GB 块和 8 GB smhmax 和 shmall 重现您的问题,但我不能。它工作得很好。我确实建议使用ipcs -m 来查找可能会阻止您的 10 GB 分配被兑现的其他共享块。并且一定要仔细查看 shmget() 通过 errno 返回的确切错误代码。

    【讨论】:

      猜你喜欢
      • 2012-08-13
      • 2011-02-18
      • 2018-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-31
      • 1970-01-01
      相关资源
      最近更新 更多