Getting Free and Real Memory with C++

I'm working on a port I maintain and the code has drastically changed. Everything is going we except that the program gives warnings that there isn't enough free memory on the system to perform certain actions.

The program uses Linux call to /proc/meminfo to get this information. I've worked it out that I should be using the sysctl function to get this information. I wrote this code that seems to give the information that I need, but it does not seem to match up with calling [CMD=""]sysctl[/CMD] from the command line.

Code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
#include <sys/limits.h>
#include <vm/vm_param.h>

struct vmtotal getVMinfo(){
  struct vmtotal vm_info;
  int mib[2];
  
  mib[0] = CTL_VM;
  mib[1] = VM_TOTAL;

  size_t len = sizeof(vm_info);
  sysctl(mib, 2, &vm_info, &len, NULL, 0);

  return vm_info;
}

int getSysCtl(int top_level, int next_level){
	int mib[2], ctlvalue;
	size_t len;

	mib[0] = top_level;
	mib[1] = next_level;
	len = sizeof(ctlvalue);

	sysctl(mib, 2, &ctlvalue, &len, NULL, 0);	
	
	return ctlvalue;
}


int main(void){
	int realmem = getSysCtl(CTL_HW, HW_REALMEM);
	int usermem = getSysCtl(CTL_HW, HW_USERMEM);
	int pagesize = 	getSysCtl(CTL_HW, HW_PAGESIZE);
	
	printf("Real Memory: %i\n",realmem);
	printf("User Memory: %i\n",usermem);
	printf("Page Size: %i\n",pagesize);
		
	struct vmtotal vmsize = getVMinfo();
	printf("Total VM Memory: %i\n",vmsize.t_vm);
	printf("Total Real Memory: %i\n",vmsize.t_rm);
	printf("shared real memory: %i\n",vmsize.t_rmshr);
	printf("active shared real memory: %i\n",vmsize.t_armshr);
	printf("Total Free Memory pages: %i\n",vmsize.t_free);
}

gives me the following output:
Code:
Real Memory: 1006632960
User Memory: -1004396544
Page Size: 4096
Total VM Memory: 269489480
Total Real Memory: 153927
shared real memory: 6015
active shared real memory: 5736
Total Free Memory pages: 1497516

But [CMD="sysctl"]vm.vmtotal[/CMD]

outputs:
Code:
vm.vmtotal: 
System wide totals computed every five seconds: (values in kilobytes)
===============================================
Processes:		(RUNQ: 1 Disk Wait: 0 Page Wait: 0 Sleep: 89)
Virtual Memory:		(Total: 1078017644K Active: 4167380K)
Real Memory:		(Total: 617380K Active: 516236K)
Shared Virtual Memory:	(Total: 38944K Active: 28844K)
Shared Real Memory:	(Total: 24652K Active: 23536K)
Free Memory:	5987760K

I see that if I use the formula (Total Free Pages * Page Size)/1024, I get a number extremely close to the Free Memory number of the command line output, but I'm not sure if that is correct.

Any suggestions?
 
roddierod said:
I see that if I use the formula (Total Free Pages * Page Size)/1024, I get a number extremely close to the Free Memory number of the command line output, but I'm not sure if that is correct.

Any suggestions?

You are calculating free memory the correct way if you are reading total free pages from vm.stats.vm.v_free_count.
 
roddierod said:
Any suggestions?
Have you tried reverse-engineering /usr/src/sbin/sysctl/sysctl.c? Particularly the function S_vmtotal() should give you an idea of how the above figures are calculated.
 
I posted this on hackers and they all suggested that calculation of free memory should not be part of the application. I even contacted the author and he agreed...so in the end I don't need to add a function for this.
 
Hmm isn't this a problem with using integers for numbers bigger than 2G or 4G (unsigned). I see values much over 4G in system output and you are using integers which are 32 bits. Maybe use size_t or unsigned long long which are both 64 bit. Even intermediate values before dividing by 2^10 can cause integer overflow.
 
Back
Top