[comp.unix.questions] Determining system memory

chris@lxn.UUCP (Christopher D. Orr) (03/31/88)

I have been trying to find a nice, clean way to determine system
memory under SYS V 2.2.  I have come up with two solutions to this
problem.  However, there must be a cleaner/faster way :-).

Solution 1:  The command 'wc -c /dev/mem' seems to work though it
             takes *FOREVER* on systems with large amounts on memory.

Solution 2:  The following 'C' program reports system memory much
             faster that Solution 1, but is still fairly slow:
	     #include <stdio.h>
	     #include <fcntl.h>

	     extern int errno;
	     static char BUF[32768];

	     void main()
	     {
	     long int L;
	     int M;
		 
	     M = open("/dev/mem",O_RDONLY);
	     if (M < 0) 
	      {
	        printf("Error: unable to open /dev/mem. errno=%d\n",errno);
	        exit(1);
	      }

	     for (L=0;read(M,BUF,16384) == 16384 ;++L);
	     printf("Memory Size: %ld\n",L * 16384);
	     }

Any other solutions are welcome (especially those that are faster :-)

---
Christopher D. Orr                  | US MAIL: Alcyone Inc.
UUCP: vu-vlsi\                      |          Lanark Building
      ihnp4   - !lehi3b15!lxn!chris |          Center Valley, PA  18034
      c11ux  /                      | Voice:   (215) 282-4525

edw@IUS1.CS.CMU.EDU (Eddie Wyatt) (03/31/88)

 > I have been trying to find a nice, clean way to determine system
 > memory under SYS V 2.2.  I have come up with two solutions to this
 > problem.  However, there must be a cleaner/faster way :-).
 > 
	....

 > Any other solutions are welcome (especially those that are faster :-)

If what you are really interested in is the memory currently available
to a given process I suggest using sbrk.  sbrk memory
in fix block sizes until sbrk fails.
-- 

Eddie Wyatt 				e-mail: edw@ius1.cs.cmu.edu

ram%shukra@Sun.COM (Renu Raman, Taco Bell Microsystems) (04/01/88)

In article <248@lxn.UUCP> chris@lxn.UUCP (Christopher D. Orr) writes:
>
>I have been trying to find a nice, clean way to determine system
>memory under SYS V 2.2.  I have come up with two solutions to this
>problem.  However, there must be a cleaner/faster way :-).
>
>Solution 1:  The command 'wc -c /dev/mem' seems to work though it
>             takes *FOREVER* on systems with large amounts on memory.
>
>Solution 2:  The following 'C' program reports system memory much
>             faster that Solution 1, but is still fairly slow:
>	     #include <stdio.h>
>	     #include <fcntl.h>
>
>	     extern int errno;
>	     static char BUF[32768];
>
>	     void main()
>	     {
>	     long int L;
>	     int M;
>		 
>	     M = open("/dev/mem",O_RDONLY);
>	     if (M < 0) 
>	      {
>	        printf("Error: unable to open /dev/mem. errno=%d\n",errno);
>	        exit(1);
>	      }
>
>	     for (L=0;read(M,BUF,16384) == 16384 ;++L);
>	     printf("Memory Size: %ld\n",L * 16384);
>	     }
>
>Any other solutions are welcome (especially those that are faster :-)
>
>---
>Christopher D. Orr                  | US MAIL: Alcyone Inc.
>UUCP: vu-vlsi\                      |          Lanark Building
>      ihnp4   - !lehi3b15!lxn!chris |          Center Valley, PA  18034
>      c11ux  /                      | Voice:   (215) 282-4525

    Bezerkely and its derivatives have a kernel variable called _physmem.
    Just get its location and read that variable from /dev/kmem.
    _physmem is the total memory in expressed in clicks (system pages). 
    There must be an equivalent in Sys V. too. You may need nlist or
    its variant for Sys. V.


Renu Raman

davy@ea.ecn.purdue.edu (Dave Curry) (04/01/88)

In article <248@lxn.UUCP> chris@lxn.UUCP (Christopher D. Orr) writes:
>
>I have been trying to find a nice, clean way to determine system
>memory under SYS V 2.2.  I have come up with two solutions to this
>problem.  However, there must be a cleaner/faster way :-).
>

Of course the simplest and fastest way, assuming you have the
permissions, is to just go dig it out of the kernel.

--Dave

/*
 * Figure out how much memory there is on a machine.  This works under
 * Berkeley UNIX.  It should work under System V if you change the
 * UNIX define to "/unix" instead of "/vmunix".
 *
 * Of course, if you don't have read permission on the kernel and 
 * kernel memory, this won't work.
 *
 * Dave Curry
 * Purdue University
 * Engineering Computer Network
 * davy@intrepid.ecn.purdue.edu
 */
#include <sys/param.h>
#include <sys/types.h>
#include <nlist.h>
#include <stdio.h>

#ifndef ctob			/* For System V */
#include <sys/sysmacros.h>
#endif

#define UNIX	"/vmunix"
#define KMEM	"/dev/kmem"

struct nlist nl[] = {
#define X_PHYSMEM	0
	{ "_physmem" },
#define X_MAXMEM	1
	{ "_maxmem" },
	{ NULL }
};

main()
{
	int kmem;
	int maxmem, physmem;

	/*
	 * Look up addresses of variables.
	 */
	if ((nlist(UNIX, nl) < 0) || (nl[0].n_type == 0)) {
		fprintf(stderr, "%s: no namelist.\n", UNIX);
		exit(1);
	}

	/*
	 * Open kernel memory.
	 */
	if ((kmem = open(KMEM, 0)) < 0) {
		perror(KMEM);
		exit(1);
	}

	/*
	 * Read variables.
	 */
	lseek(kmem, (long) nl[X_PHYSMEM].n_value, 0);
	read(kmem, (char *) &physmem, sizeof(int));

	lseek(kmem, (long) nl[X_MAXMEM].n_value, 0);
	read(kmem, (char *) &maxmem, sizeof(int));

	close(kmem);

	/*
	 * Print the numbers.  The internal representation is
	 * in units of core clicks; convert to bytes.
	 */
	printf("Physical machine memory: %d\n", ctob(physmem));
	printf("Max memory available to a process: %d\n", ctob(maxmem));

	exit(0);
}

dean@homxb.UUCP (D.JONES) (04/02/88)

In article <1271@PT.CS.CMU.EDU>, edw@IUS1.CS.CMU.EDU (Eddie Wyatt) writes:
>  > I have been trying to find a nice, clean way to determine system
>  > memory under SYS V 2.2.  I have come up with two solutions to this
>  > problem.  However, there must be a cleaner/faster way :-).
>  > Any other solutions are welcome (especially those that are faster :-)
> If what you are really interested in is the memory currently available
> to a given process I suggest using sbrk.  sbrk memory
> in fix block sizes until sbrk fails.
> Eddie Wyatt 				e-mail: edw@ius1.cs.cmu.edu

	Now you know how much memory you have for the current process, but
do you have to sbrk() it back if you are going to use malloc() ???  A call
to ulimit() on SysV 2.2 with an arg of 3 will return the max brk value for
the current process.  What about something <simple> like:

long memavail()
{
	return(ulimit(3) - (long)sbrk(0))
}

	It looks like this will work on our SunOS 4.0 machines also. I'm
Just starting to get into this UNIX stuff,   don't flame me if this is a
bozo idea...

					Dean S Jones
					AT&T Gateways!homxb!dean

dwc@homxc.UUCP (Malaclypse the Elder) (04/02/88)

In article <248@lxn.UUCP>, chris@lxn.UUCP (Christopher D. Orr) writes:
> 
> I have been trying to find a nice, clean way to determine system
> memory under SYS V 2.2.  I have come up with two solutions to this
> problem.  However, there must be a cleaner/faster way :-).
> 
i believe there is a system variable called physmem (or something
like that).  so all you have to do is to find the address of the
variable, open /dev/mem (or kmem, i'm never sure which) and read
that value (ala ps, sysdef, etc.)

danny chen
ihnp4!homxc!dwc

edw@IUS1.CS.CMU.EDU (Eddie Wyatt) (04/04/88)

    memory size via sbrk deleted.

> 	Now you know how much memory you have for the current process, but
> do you have to sbrk() it back if you are going to use malloc() ???

   Consider this as an independent facility at the shell level.
It's useful for things like finding out if the current machine that you
are running on has enough memory to load your lisp job and maintain it. 


-- 

Eddie Wyatt 				e-mail: edw@ius1.cs.cmu.edu

dannyb@kulcs.uucp (Danny Backx) (04/04/88)

In article <248@lxn.UUCP> chris@lxn.UUCP (Christopher D. Orr) writes:
>I have been trying to find a nice, clean way to determine system
>memory under SYS V 2.2.  I have come up with two solutions to this
>problem.  However, there must be a cleaner/faster way :-).

How about opening /dev/mem and seeking to the end ?
The manual entry for lseek(2) says the return value is the position you got at.
So, if you seek to the end (offset 0 relative to the EOF), the return value
of lseek should be the amount of memory your system has.

I don't know if this works on /dev/mem.  It works on ordinary files.
If your program works, this should, too.

The system call you should issue is :

	long	lseek(), pos ;

	pos = lseek(M, 0L, 2);

Don't forget the declaration of lseek() !!!

	Danny

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 Danny Backx                            |  mail: Katholieke Universiteit Leuven 
 Tel: +32 16 200656 x 3537              |        Dept. Computer Science
 E-mail: dannyb@kulcs.UUCP              |        Celestijnenlaan 200 A
         ... mcvax!prlb2!kulcs!dannyb   |        B-3030 Leuven
         dannyb@blekul60.BITNET         |        Belgium     

mouse@mcgill-vision.UUCP (der Mouse) (04/13/88)

In article <248@lxn.UUCP>, chris@lxn.UUCP (Christopher D. Orr) writes:
> I have been trying to find a nice, clean way to determine system
> memory under SYS V 2.2.

> Solution 2:  [This is faster than Solution 1, but still slow]:
[program]

Well, you could speed it up by doing a more intelligent search
technique than linear search:

/****** UNTESTED (no SV system to test it on) ******/

#include <stdio.h>
#include <fcntl.h>

extern int errno;
static char buf;

main()
{
 long int l;
 long int m;
 long int h;
 int fd;

 fd = open("/dev/mem",O_RDONLY);
 /* check for fd<0 omitted for brevity */
 l = 1;
 h = 2;
 while (1)
  { lseek(fd,h,L_SET); /* or whatever the SV way is */
    if (read(fd,&buf,1) != 1) break;
    l = h;
    h *= 2;
  }
 while (h-l > 1)
  { m = (h + l) / 2;
    lseek(fd,m,L_SET); /* or whatever */
    if (read(fd,&buf,1) == 1) l = m; else h = m;
  }
 printf("%ld bytes accessible via /dev/mem\n",h);
 exit(0);
}

					der Mouse

			uucp: mouse@mcgill-vision.uucp
			arpa: mouse@larry.mcrcim.mcgill.edu