[comp.unix.questions] mmap

jonathan@axecore.UUCP (Jonathan Eunice) (12/29/89)

As I understand it, mmap() in V.4 is derived from SunOS's mmap(), which
implements an un-released  BSD design for mapping files to virtual memory.

Several questions:

1.      Sun's mmap() does not support the MAP_RENAME option.  From the
man page, it seems that MAP_RENAME is a way of writing a virtual-memory
range to a file post hoc.  That is, writing to the file rather than
mapping the file, then altering the mapped range). Is this a correct
interpretation?

2.	AT&T seems to be advertising V.4's "single level store."  Is this
feature predicated entirely upon mmap(), or will V.4 have other features 
which contribute?  

3.	Does V.4 use mmap() to map all files, or is it only a feature
for applications developers?

4.	Do many applications use mmap()?  That is, use it in important 
ways the shmat() facility or other approaches cannot match?

5.      For that matter, do many applications use shmat()?  I would
think, given its possible performance advantages over other V IPCs,
that it would be rather popular.

6.	Other than SunOS (and now V.4), what other UNIX variants support
mmap()? How are these implementations different from Sun's?

7.	Is there a limit on the number of files that can be
efficiently mapped at once?  I would think there would be a fairly low
number defined by the restrictions of the memory management hardware.

8.	In general, how do mmap() and shmat() compare for IPC and other uses?

9.	Leffler et al only briefly mentioned the design of mmap(), with few
details.  I could not extract any mmap()-specific references from the 
bibliography.  So, are there any good papers or technical reports to
consume?

Sorry to make this into an essay.  All information appreciated. If you email
me, I will summarize for the net. Thanks.

Jonathan Eunice
D.H. Brown Associates
uunet!axecore!jonathan

coleman@cam.nist.gov (Sean Sheridan Coleman X5672) (02/05/91)

Does anyone have any examples of mmap for sun's. I am especially
interested in being able to  open one file and copy it to
another  one. I also would like to see some examples that 
utilize the EXEC proto.


I am also looking for examples that use madvise, mcntl, and
mlock.


Thanks very much

Sean Coleman
NIST
coleman@bldrdoc.gov

lm@slovax.Eng.Sun.COM (Larry McVoy) (02/05/91)

In article <6991@alpha.cam.nist.gov> coleman@cam.nist.gov (Sean Sheridan Coleman X5672) writes:
>Does anyone have any examples of mmap for sun's. I am especially
>interested in being able to  open one file and copy it to
>another  one. I also would like to see some examples that 
>utilize the EXEC proto.

Don't have a quickie for EXEC.  Check this out, just some gunk I'm playing
with.


# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# mmapcp.c mmaplib.c

echo x - mmapcp.c
cat > "mmapcp.c" << '//E*O*F mmapcp.c//'
/*
 * a version of copy that maps in the data & writes it with mmap.
 *
 * Both sets of data are synced of memory.  This is designed to move data
 * fairly quickly but still disturb the system as little as possible.
 *
 * @(#)mmapcp.c	1.2
 */

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>

#define	SYNCSIZ	(256*1024)

main(ac, av)
	char **av;
{
	int	i, bytes;
	int	in, out;
	char	*ibuf, *obuf, *ip, *op;

	if (ac != 3) {
		printf("usage: %s src dest\n", av[0]);
		exit(0);
	}
	if ((in = open(av[1], 0)) == -1) {
		perror(av[1]);
		exit(1);
	}
	if ((out = open(av[2], O_RDWR|O_CREAT, 0644)) == -1) {
		perror(av[2]);
		exit(1);
	}
	if (mmap_init(in, &ibuf, 0, -1, 0) == -1) {
		perror("mmap_init in");
		exit(1);
	}
	if (mmap_init(out, &obuf, 0, size(in), 1) == -1) {
		perror("mmap_init out");
		exit(1);
	}
	ip = ibuf;
	op = obuf;
	for (i = size(in); i > 0; i -= SYNCSIZ) {
		bytes = SYNCSIZ < i ? SYNCSIZ : i;
		bcopy(ip, op, bytes);
		mmap_flush(ip, bytes, 1);
		mmap_flush(op, bytes, 0);	/* 1 takes longer */
		ip += bytes;
		op += bytes;
	}
	close(in);
	close(out);
	exit(0);
}
//E*O*F mmapcp.c//

echo x - mmaplib.c
cat > "mmaplib.c" << '//E*O*F mmaplib.c//'
/*
 * @(#)mmaplib.c	1.3
 */
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>

/*
 * Set things up to do I/O over the indicated range
 *
 * XXX - up to user to be sure that mmap is an OK thing to do (tapes).
 */
mmap_init(fd, basepp, off, bytes, writeable)
	caddr_t	*basepp;
	off_t	bytes;
{
	caddr_t	base;
	int	protbits;

	protbits = PROT_READ;
	if (writeable) {
		protbits |= PROT_WRITE;
	}
	if (!regfile(fd)) {
		return (-1);
	}
	if (bytes == (off_t)-1) {
		bytes = size(fd);
	}
	if (writeable && ftruncate(fd, off + bytes) == -1) {
		return (-1);
	}
	base = mmap((caddr_t)0, bytes, protbits, MAP_SHARED, fd, off);
	if (base == (caddr_t)-1) {
		return (-1);
	}
	madvise(base, bytes, MADV_SEQUENTIAL);
	*basepp = base;
	return (0);
}

/*
 * flush writes
 */
mmap_flush(addr, len, clean)
	caddr_t	addr;
	off_t	len;
{
	msync(addr, len, MS_ASYNC);
	if (clean)
		madvise(addr, len, MADV_DONTNEED);
}

static	struct stat sb;
static	lastfd = -1;

regfile(fd)
{
	if (lastfd != fd) {
		if (fstat(fd, &sb) == -1) {
			return (-1);
		}
		lastfd = fd;
	}
	return (S_ISREG(sb.st_mode));
}

size(fd)
{
	if (lastfd != fd) {
		if (fstat(fd, &sb) == -1) {
			return (-1);
		}
		lastfd = fd;
	}
	return (sb.st_size);
}
//E*O*F mmaplib.c//

echo Possible errors detected by \'wc\' [hopefully none]:
temp=/tmp/shar$$
trap "rm -f $temp; exit" 0 1 2 3 15
cat > $temp <<\!!!
      57     188    1124 mmapcp.c
      78     198    1239 mmaplib.c
     135     386    2363 total
!!!
wc  mmapcp.c mmaplib.c | sed 's=[^ ]*/==' | diff -b $temp -
exit 0
---
Larry McVoy, Sun Microsystems     (415) 336-7627       ...!sun!lm or lm@sun.com