Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 10 Nov 1996 14:58:06 +1100 (EST)
From:      Julian Assange <proff@suburbia.net>
To:        scrappy@ki.net (Marc G. Fournier)
Cc:        hackers@FreeBSD.org
Subject:   Re: MMAP: how to use...
Message-ID:  <199611100358.OAA32061@suburbia.net>
In-Reply-To: <Pine.NEB.3.95.961109102635.5378A-100000@quagmire.ki.net> from "Marc G. Fournier" at Nov 9, 96 10:27:53 am

next in thread | previous in thread | raw e-mail | index | archive | help
> 
> 
> Hi...
> 
> 	Can anyone direct me to either an online source, or a good
> book, on MMAP?  
> 
> Thanks...

Here are some tests I wrote for nntpcache. should give you an idea.


#include "config.h"
#ifdef HAVE_MMAP
/* $Id: mmap_tests.c,v 1.10 1996/11/08 20:29:02 proff Exp $
 * 
 * various mmap() implimentations suck; we attempt to find out just how
 * hard.
 *
 *        - Julian Assange (proff@suburbia.net)
 *
 * Test results: (please send additions to proff@suburbia.net)
 *
 *   linux 2.0.0 allows shared mmaps only for files, while 1.2.13
 *   doesn't permit shared mmaps at all.
 *
 *   Linux suburbia 2.0.0 #29- Thu Jul 11 18:03:20 EST 1996 i586 
 *
 *	HAVE_MMAP_FILE_PRIVATE_READ
 *	HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_FILE_PRIVATE_WRITE
 *	HAVE_MMAP_FILE_SHARED_READ
 *	HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *	HAVE_MMAP_FILE_SHARED_WRITE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_ANON_PRIVATE
 *	HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
 *
 *   Linux server 1.2.13 #6 Wed Feb 28 15:45:11 CST 1996 i486 (forget it)
 *	
 *	program output:
 *	HAVE_MMAP_FILE_PRIVATE_READ
 *	HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_FILE_PRIVATE_WRITE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_ANON_PRIVATE
 *	HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
 *
 *   Freebsd is purrrrfect.
 *
 *   FreeBSD profane 2.2-CURRENT #0 Sat Jul 27 19:16:00 EST 1996
 *
 *	HAVE_MMAP_FILE_PRIVATE_READ
 *	HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_FILE_PRIVATE_WRITE
 *	HAVE_MMAP_FILE_SHARED_READ
 *	HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *	HAVE_MMAP_FILE_SHARED_WRITE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_DEV_ZERO_SHARED
 *	HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
 *	HAVE_MMAP_ANON_PRIVATE
 *	HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_ANON_SHARED
 *	HAVE_MMAP_ANON_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_ANON_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_ANON_SHARED_PARENT_READ_CHILD_WRITE
 *
 *   Suprisingly, AIX is faultless too.
 *
 *   AIX whisky 2 3 000027477600
 *
 *	HAVE_MMAP_FILE_PRIVATE_READ
 *	HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_FILE_PRIVATE_WRITE
 *	HAVE_MMAP_FILE_SHARED_READ
 *	HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *	HAVE_MMAP_FILE_SHARED_WRITE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_DEV_ZERO_SHARED
 *	HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
 *	HAVE_MMAP_ANON_PRIVATE
 *	HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_ANON_SHARED
 *	HAVE_MMAP_ANON_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_ANON_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_ANON_SHARED_PARENT_READ_CHILD_WRITE
 *
 *   Shared mmap file writes are screwed under BSDI!  
 *
 *   BSD/OS telepath.com 2.1 BSDI BSD/OS 2.1 Kernel #3: Thu Mar  7 10:47:49 CST 1996
 *
 *	HAVE_MMAP_FILE_PRIVATE_READ
 *	HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_FILE_PRIVATE_WRITE
 *	HAVE_MMAP_FILE_SHARED_READ
 *	HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_DEV_ZERO_SHARED
 *	HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
 *	HAVE_MMAP_ANON_PRIVATE
 *	HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_ANON_SHARED
 *	HAVE_MMAP_ANON_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_ANON_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_ANON_SHARED_PARENT_READ_CHILD_WRITE
 *
 *   SunOS omega.iqm.unicamp.br 5.4 generic i86pc i386
 *
 *	HAVE_MMAP_FILE_PRIVATE_READ
 *	HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_FILE_PRIVATE_WRITE
 *	HAVE_MMAP_FILE_SHARED_READ
 *	HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *	HAVE_MMAP_FILE_SHARED_WRITE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_DEV_ZERO_SHARED
 *	HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
 *
 *   SunOS chaos 4.1C 4.1.3 sun4
 *
 *	HAVE_MMAP_FILE_PRIVATE_READ
 *	HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_FILE_PRIVATE_WRITE
 *	HAVE_MMAP_FILE_SHARED_READ
 *	HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *	HAVE_MMAP_FILE_SHARED_WRITE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_DEV_ZERO_SHARED
 *	HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
 *	
 *   SunOS unix1 5.3 Generic_101318-59 sun4m sparc (no shared file write?)
 *	
 *	HAVE_MMAP_FILE_PRIVATE_READ
 *	HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_FILE_PRIVATE_WRITE
 *	HAVE_MMAP_FILE_SHARED_READ
 *	HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_DEV_ZERO_SHARED
 *	HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
 *	
 *   SunOS sydney6 5.5 Generic_103093-03 sun4m sparc SUNW,SPARCstation-20
 *
 *	HAVE_MMAP_FILE_PRIVATE_READ
 *	HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_FILE_PRIVATE_WRITE
 *	HAVE_MMAP_FILE_SHARED_READ
 *	HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *	HAVE_MMAP_FILE_SHARED_WRITE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_DEV_ZERO_SHARED
 *	HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
 *
 *   Novell Unixware 2.03 (System V Release 4.2MP) UNIX_SV aapo 4.2MP 2.03 i386 x86at
 *
 *	HAVE_MMAP_FILE_PRIVATE_READ
 *	HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_FILE_PRIVATE_WRITE
 *	HAVE_MMAP_FILE_SHARED_READ
 *	HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *	HAVE_MMAP_FILE_SHARED_WRITE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_DEV_ZERO_SHARED
 *	HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
 *
 *   ULTRIX wolf.cs.washington.edu 4.2 0 RISC (way to go ultrix)
 *
 *	nothing. zilch. 
 *
 *   OSF1 porky-pig V3.2 214 alpha (unexpected. osf/1 sucks).
 *
 *	HAVE_MMAP_DEV_ZERO_PRIVATE
 *	HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_DEV_ZERO_SHARED
 *	HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_ANON_PRIVATE
 *	HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
 *	HAVE_MMAP_ANON_SHARED
 *	HAVE_MMAP_ANON_SHARED_CHILD_INHERIT
 *	HAVE_MMAP_ANON_SHARED_CHILD_READ_PARENT_WRITE
 *	HAVE_MMAP_ANON_SHARED_PARENT_READ_CHILD_WRITE
 */

#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <setjmp.h>

#define MM_SIZE (100*1024)
#define TEST_FILE "mmap_test.tmp"

int caught_sigquit;

void sigquit (int sig)
{
	caught_sigquit++;
	signal (SIGQUIT, sigquit);
}

void sigalrm (int sig)
{
	caught_sigquit++;
	signal (SIGALRM, sigalrm);
}

jmp_buf jmp;

void sigsegv (int sig)
{
	signal (SIGSEGV, sigsegv);
	longjmp (jmp, 1);
}

/* 
 * TODO: test MAP_INHERIT, MAP_FIXED  (can't see that latter being much of an issue)
 */

void
test_child(char *p, char *msg)
{
	char *im = "inherit_magic";
	char *pm = "parent_magic";
	char *cm = "child_magic";
	pid_t pid;
	int ws;
	fflush (stdout);
	if (!setjmp(jmp))
		strcpy (p, im);
	caught_sigquit = 0;
	signal (SIGQUIT, sigquit);
	signal (SIGCHLD, SIG_IGN);
	signal (SIGALRM, sigalrm);
	pid = fork();
	if (pid<0)
		return;
	if (pid==0)
	{
		if (!setjmp(jmp))
			if (strcmp(p, im)==0)
				printf("%s_CHILD_INHERIT\n", msg);
		alarm(5);
		kill (getppid(), SIGQUIT);
		while (!caught_sigquit)
			pause ();
		caught_sigquit = 0;
		if (!setjmp(jmp))
			if (strcmp(p, pm)==0)
				printf("%s_CHILD_READ_PARENT_WRITE\n", msg);
		if (!setjmp(jmp))
			strcpy (p, cm);
		fflush (stdout);
		kill (getppid(), SIGQUIT);
		exit(0);
	}
	/* parent */
	alarm(5);
	while (!caught_sigquit)
		pause ();
	caught_sigquit = 0;
	if (!setjmp(jmp))
		strcpy (p, pm);
	alarm(5);
	kill (pid, SIGQUIT);
	while (!caught_sigquit)
		pause ();
	if (!setjmp(jmp))
		if (strcmp(p, cm)==0)
			printf("%s_PARENT_READ_CHILD_WRITE\n", msg);
	signal (SIGQUIT, SIG_DFL);
	alarm(0);
	wait(&ws);
}

int
main()
{
	volatile int fd;
	char *m = malloc(MM_SIZE);
	char buf[1024];
	signal (SIGSEGV, sigsegv);
#if defined(MAP_PRIVATE)
	fd = open(TEST_FILE, O_RDWR|O_CREAT|O_TRUNC, 0666);
	strcpy (m, "mmap magic");
	write (fd, m, MM_SIZE);
	lseek (fd, 0, SEEK_SET);
	if (fd>=0)
	{
		char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
		if (p!=(char *)-1)
		{
			if (!setjmp(jmp))
				if (strcmp(p, m)==0)
					puts("HAVE_MMAP_FILE_PRIVATE_READ");
			test_child(p, "HAVE_MMAP_FILE_PRIVATE");
			if (!setjmp(jmp))
			{
				strcpy (p, "mmap magic2");
				munmap (p, MM_SIZE);
				read (fd, buf, 12);
				if (strcmp(buf, "mmap magic2")!=0)
					puts("HAVE_MMAP_FILE_PRIVATE_WRITE");
			} else
				munmap (p, MM_SIZE);
		}
		close (fd);
	}
#endif
#if defined(MAP_SHARED)
	fd = open(TEST_FILE, O_RDWR|O_CREAT|O_TRUNC, 0666);
	strcpy (m, "mmap magic");
	write (fd, m, MM_SIZE);
	lseek (fd, 0, SEEK_SET);
	if (fd>=0)
	{
		char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
		if (p!=(char *)-1)
		{
			if (!setjmp(jmp))
				if (strcmp(p, m)==0)
					puts("HAVE_MMAP_FILE_SHARED_READ");
			test_child(p, "HAVE_MMAP_FILE_SHARED");
			if (!setjmp(jmp))
			{
				strcpy (p, "mmap magic2");
				munmap (p, MM_SIZE);
				read (fd, buf, 12);
				if (strcmp(buf, "mmap magic2")==0)
					puts("HAVE_MMAP_FILE_SHARED_WRITE");
			} else
				munmap (p, MM_SIZE);
		}
		close (fd);
	}
#endif
#if defined(MAP_PRIVATE)
	fd = open("/dev/zero", O_RDWR, 0666);
	if (fd>=0)
	{
		char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
		if (p!=(char *)-1)
		{
			if (!setjmp(jmp))
			{
				strcpy (p, "mmap magic_dev_zero");
				if (strcmp (p, "mmap magic_dev_zero")==0)
					puts("HAVE_MMAP_DEV_ZERO_PRIVATE");
			}
			test_child(p, "HAVE_MMAP_DEV_ZERO_PRIVATE");
			munmap (p, MM_SIZE);
		}
		close (fd);
	}
#endif
#if defined(MAP_PRIVATE)
	fd = open("/dev/zero", O_RDWR, 0666);
	if (fd>=0)
	{
		char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
		if (p!=(char *)-1)
		{
			if (!setjmp(jmp))
			{
				strcpy (p, "mmap magic_dev_zero_shared");
				if (strcmp (p, "mmap magic_dev_zero_shared")==0)
					puts("HAVE_MMAP_DEV_ZERO_SHARED");
			}
			test_child(p, "HAVE_MMAP_DEV_ZERO_SHARED");
			munmap (p, MM_SIZE);
		}
		close (fd);
	}
#endif
#if defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
#define MAP_ANON MAP_ANONYMOUS
#endif
#ifdef MAP_ANON
	{
		char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
		if (p!=(char *)-1)
		{
			if (!setjmp(jmp))
			{
				strcpy (p, "mmap magic_anon");
				if (strcmp(p, "mmap magic_anon")==0)
					puts("HAVE_MMAP_ANON_PRIVATE");
			}
			test_child(p, "HAVE_MMAP_ANON_PRIVATE");
			munmap (p, MM_SIZE);
		}
	}
#endif
#if defined(MAP_ANON) && defined(MAP_SHARED)
	{
		char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
		if (p!=(char *)-1)
		{
			if (!setjmp(jmp))
			{
				strcpy (p, "mmap magic_shared_anon");
				if (strcmp(p, "mmap magic_shared_anon")==0)
					puts("HAVE_MMAP_ANON_SHARED");
			}
			test_child(p, "HAVE_MMAP_ANON_SHARED");
			munmap (p, MM_SIZE);
		}
	}
#endif
	unlink(TEST_FILE);
	exit (0);
}
#else /* HAVE_MMAP */
#  error no working mmap call on this system?!
#endif


-- 
"Of all tyrannies a tyranny sincerely  exercised for the good of its victims  
 may be the most  oppressive.  It may be better to live under  robber barons  
 than  under  omnipotent  moral busybodies,  The robber baron's  cruelty may  
 sometimes sleep,  his cupidity may at some point be satiated; but those who  
 torment us for own good  will torment us  without end,  for they do so with 
 the approval of their own conscience."    -   C.S. Lewis, _God in the Dock_ 
+---------------------+--------------------+----------------------------------+
|Julian Assange RSO   | PO Box 2031 BARKER | Secret Analytic Guy Union        |
|proff@suburbia.net   | VIC 3122 AUSTRALIA | finger for PGP key hash ID =     |
|proff@gnu.ai.mit.edu | FAX +61-3-98199066 | C7F81C2AA32D7D4E4D360A2ED2098E0D |
+---------------------+--------------------+----------------------------------+



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199611100358.OAA32061>