使用 cgroups 控制 Linux 上的内存使用

Using cgroups to control memory usage on Linux

我正在尝试使用 cgroups 来停止实际使用过多内存的程序,同时让它们 运行 如果它们只是分配而不实际使用大量内存。但是,它似乎不起作用;有什么建议么?在 Ubuntu 机器上,我按如下方式设置我的 cgroup[1]:

#Changing $USER to a system user running the process
sudo apt-get install cgroup-bin
sudo cgcreate -a $USER -g memory:$USER
echo 100M > /cgroup/memory/$USER/memory.limit_in_bytes

#Running the program using cgroups
cgexec -g memory:$USER program

我正在使用以下程序(回答“否”应该有效,回答“是”应该停止)。

#include <stdlib.h>
#include <stdio.h>

#define SIZE (long int) 1*1024*1024*1024*sizeof(char)/*1 GB*/

int main(void)
{
  char *str = (char*) malloc(SIZE);
  char *ans = (char*) malloc(100);

  printf("Write random values to memory? (yes/no): ");
  scanf("%s", ans);

  if (strcmp(ans,"yes") == 0) {
    FILE *f = fopen("/dev/urandom","r");
    fread(str,1,SIZE,f);
    printf("Success!!\n");
    fclose(f);
    free(str);
  }
  else {
    printf("Have a good day!\n");
  }

  return(0); 
}

[1] https://askubuntu.com/questions/94619/how-to-set-cpu-limit-for-given-process-permanently-cpulimit-and-nice-dont-work

您的测试返回成功,因为它没有检查错误。事实上,当您的二进制文件达到内存限制时, fread 调用分配失败。 你可以通过更改代码来检查错误来看到:

#include <stdlib.h>
#include <stdio.h>

#define SIZE (long int) 1*1024*1024*1024*sizeof(char)/*1 GB*/

int main(void)
{
  char *str = (char*) malloc(SIZE);
  char *ans = (char*) malloc(100);

  printf("Write random values to memory? (yes/no): ");
  scanf("%s", ans);

  if (strcmp(ans,"yes") == 0) {
    FILE *f = fopen("/dev/urandom","r");
    int size = fread(str,1,SIZE,f);
    if (size < SIZE) {
        printf("incomplete read: %d, error %d\n", size, ferror(f));
    } else {
        printf("Success!!\n");
    }
    fclose(f);
    free(str);
  }
  else {
    printf("Have a good day!\n");
  }

  return(0);
}

更酷的是使用 cgroup 监视实用程序,例如 cadvisor 您可以以图形方式查看您的二进制文件达到极限。 。希望有所帮助:)

我认为下面是一个更好的测试程序。它分配了大量内存,如果您回答 'y' 它会尝试使用它。只需分配内存就可以了,但稍后尝试实际使用它应该会触发 OOM 杀手。一定要先运行"swapoff"。这不是从 /dev/urandom 读取(这需要一段时间),而是将 % 256 写入每个字节,这应该会更快。我还没有尝试用 cgroups 测试这个。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#define MiB 1024*1024

#define CHUNK_SIZE (100 * MiB)
#define CHUNKS 100000

void overwrite(char *s, size_t size) {
  for (; size > 0; s++, size--)
    *s = (char) (size % 256); // Vary what's written to prevent optimizations
}

int main() {
  char *chunk[CHUNKS];
  int i;
  int numchunks;
  int result;

  printf("Allocating many memory chunks.\n");
  fflush(stdout);
  for (i = 0; i<CHUNKS; i++) {
    chunk[i] = malloc(CHUNK_SIZE);
    if (!chunk[i]) {
      i--;
      printf("Cannot allocate any more\n");
    }
  }
  numchunks = i;

  printf("Should values be written to memory?\n");
  result = getchar();
  if (result == 'y' || result == 'Y') {
    printf("\nWriting chunks of size %d:\n", (unsigned) CHUNK_SIZE);
    fflush(stdout);
    for (i = 0; i<numchunks; i++) {
      printf(" %d", i);
      fflush(stdout);
      overwrite(chunk[i], CHUNK_SIZE);
    }
  }
  printf("Program exiting\n");
  return 0;
}