MMapping /dev/zero : Was Re: Shared Memory

Peter Belsanti (pbelsant@algorithmics.com)
Mon, 12 May 1997 12:57:16 -0400


> Does anyone know of a systtem call that is available so that given a
> process ID and a physical range of pages, one process could map that
> physical memory into the address space of the process that
> corresponds to the given PID?

A related question, I've tried to get a financial analysis package
working on Linux, and everything seems to be fine except for the piece
that "forks" children for big calculations.

For all other O/S's, (Solaris, OSF/1, AIX, HPUX), we mmap /dev/zero for
a chunck of shared memory and use that between children. The data space
is pretty big and we don't really want to hit the file system.

This code doesn't seem to work for Linux. A simple change to mmap an
actual file on the file system instead on /dev/zero fixes makes
everything work, but I'd rather not use the file system, if possible.
Is there a way to do this in Linux?

The following code shows the trick. Four children are "forked". They
display their PID and also store it in a shared memory array. The
parent displays the array once all children terminate.

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>

static int const NPROCS = 4;
//static char const * const MAPFILE = "/tmp/MMAP";
static char const * const MAPFILE = "/dev/zero";

int
main()
{
int fd;
int i, j, k;
int pid;
int* mapped;

if ((fd = open(MAPFILE, O_RDWR, 0)) < 0)
{
perror(MAPFILE);
exit(1);
}

printf("%d %d %d %d %d %d\n", (caddr_t)0, NPROCS*sizeof(int),
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);

if ((mapped = (int*)mmap((caddr_t)0,
NPROCS * sizeof(int),
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
// this is for alpha
// MAP_SHARED|MAP_ANONYMOUS|MAP_VARIABLE,
// -1,
0)) < 0)
{
perror("mmap");
exit(2);
}

if (close(fd) < 0)
{
perror("close");
exit(3);
}

for (i = 0 ; i < NPROCS - 1; i++)
{
pid = fork();

if (pid == 0)
{
break;
}
else if (pid == -1)
{
perror("fork");
exit(4);
}
}

{
int j;
j = getpid();
printf("%d\n", j);
mapped[i] = j;
}

if (pid == 0)
{
/* I am a child */
exit(0);
}

/* reap children */
for (j = NPROCS - 1; j--; )
{
if (wait(NULL) == -1)
{
perror("wait");
exit(5);
}
}

/* check result */
for (k = 0; k < NPROCS; k++)
{
printf("%d\n", mapped[k]);
}

if (munmap(mapped, NPROCS) < 0)
{
perror("munmap");
exit(6);
}

exit(0);
}