この記事を書いた動機 (Nov 14 あたりの出来事)

 最近、HP Proliant ML 150 (9 Gen) の消費電力削減の目的で、休止状態を利用できるようにしようとした過程で、それが正しく機能しているのか調べたくなった。そこで、ただメモリをたくさん指定した量だけ消費するプログラムを作成し、とりあえず動くところまで作ったので、ここに置いておこうというわけである。どこまで意味があるのかは不明。

 ちなみに、一応メモリ割り当てに失敗したとき用に、再度メモリ割り当てを試みる機能や、メモリ割り当てに完全に失敗したときにプログラムを終了するなど、セーフティも実装しているが、結局使うことはなかったので正しく動く保証はない。

使い方

プログラムのコンパイル

gcc useram.c -o useram

プログラムの利用

# 10 GB のメモリを埋めるときの例
useram 10

Too many ram will be allocated by your request. denied operation. と出てくる時

  • プログラム内の定数 margin の大きさが大きすぎる可能性があるので、適宜調整する。
  • 後は単純に、実装されているメモリサイズより大きなサイズを指定してしまっているので、小さい値で再度プログラムを実行してみる。

プログラム本体

#include <stdio.h>
#include <stdlib.h>
#include <sys/sysinfo.h>

// unit GB
#define margin 10
#define retry 3

// Get the amount of entire installed RAM.
// No args are required.
// return: amount of entire installed RAM
int checkRAM(){
	unsigned int amount = 0; // GB
	struct sysinfo info;
	sysinfo(&info);

	// convert unit byte to Giga byte (10^9)
	amount = info.totalram / 1000 / 1000 / 1000;
	return amount;
}

// allocate RAM (amount GB)
// args:(Unit -> GB)
// 		amount: 	allocation size				unsigned int
// 		maxAmount: 	entire system RAM amount	unsigned int
// return:
// 		pointer:	pointer to allocated area	void*
//					If all ram allocation attempts are failed, return NULL.
void* allocateRAM(unsigned int amount, unsigned int maxAmount){
	// find specified allocation size is exceed entire system RAM amount or not.
	if(amount >= maxAmount - margin){
		printf("Too many ram will be allocated by your request. denied operation.\n");
		return 0;
	}

	// allocate ram but still the allocated area is not utilized.
	unsigned long allocateSize = (long)sizeof(char) * (long)amount * (long)1000 * (long)1000 * (long)1000;
	void* pointer = (void*)malloc(allocateSize);

	// retry ram allcation if it is failed.
	if(pointer == NULL){
		printf("ram allocation is failed. retry %d times\n",retry);
		int counter = 0;
		while(pointer == NULL && counter < retry){
			printf("retry %d\n",counter);
			void* pointer = (void*)malloc(allocateSize);
			counter++;
		}
	}

	// If all ram allocation attempts are failed, return NULL.
	if(pointer == NULL){
		printf("allocation failed!\n");
		return NULL;
	}

	printf("allocation OK\n");
	return pointer;
}

// amount unit GB
void useRAM(void* pointer,unsigned int amount){
	// 4 mean size of int
	unsigned long loopAmount = (long)amount * (long)1000 * (long)1000 * (long)1000 / (long) 4;
	int* arr = (int*)pointer;

	// For each loop, fill up the allocated area with random value by 4 byte(size of int)
	for(unsigned long i = 0; i < loopAmount; i++){
		arr[i] = (int)rand();
	}

	printf("Loop amount %lu\n",loopAmount);
	printf("RAM area is filled up. The process is finished.\n");
	return;
}

int main(int argc,char **argv){
	// find entire system ram
	unsigned int ramAmount = checkRAM();

	// If The allocation size is not specified, exit this program.
	if(argc <= 1){
		printf(" The size of ram amount that will be filled up is not specified. (GB)\n");
		return -1;
	}

	unsigned int amount = atoi(argv[1]);

	// find correct value is entered or not
	if(amount != 0){
		printf("%d GB\n",amount);
	}else{
		printf("You may enter string or 0 as args. Stop.\n");
		return -1;
	}

	printf("System info: \n %d GB RAM is installed\n",ramAmount);

	// ram allocation and filling up process
	void* pointer = allocateRAM(amount,ramAmount);
	useRAM(pointer,amount);

	// If ram allocation is failed, exit this program
	if(pointer == NULL) {
		printf("went worng\n");
		return -1;
	}

	// wait until get user input.
	// The filled up RAM area will not be free while there is no user input for 'q' key.
	char input = 'a';
	while(input != 'q') scanf("%c",&input);

	free(pointer);
	return 0;
}

参考にしたサイト