RE: B*gg*r mallocs, mmap JOY!

John Carter (john@dwaf-hri.pwv.gov.za)
Thu, 13 Feb 1997 12:41:14 +0200 (SAT)


Ha! I just _luv_ Linux.

Thanks to Ingo Molnar and many others on the list who gave me clues
along they way...

Here is an example program for anyone else who wishes to use
mmap. (Note you _can_ use mmap to write to files, the trick is
ftruncate())

It does what 'cp' does, but a little bit slower. A cute thing to note
is the load graph soars to 3, maybe it would be civilized to 'nice'
any programs you run that do this.

The joy of it is that if you are actually doing real work like
neighbourhood operations on a satellite image, you can forget all
those nasty horrid boundary conditions on the buffers, as there are no
buffers (visible).

50% of the code and 90% of the bugs of such a program is typically
handling boundary conditions on the buffering.

I LOVE LINUX. I tested this creating 150Mb of VM on a 24Mb real mem
system and used 0 swap space.

By gorrah, what a mess programming in DOS and Vax/VMS was in
comparison.

John Carter EMail: ece@dwaf-hri.pwv.gov.za
Telephone : 27-12-808-0374x194 Fax:- 27-12-808-0338

Founder of the Council for Unnatural Scientists.

======================================================================
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
#include <iostream.h>

main()
{
int ifd, ofd;
struct stat st;
char * icp, * ocp;

ifd = open( "/home/john/pgm/tryout/temp", O_RDONLY);
if( ifd < 0)
{
perror( "input file");
return 1;
}

fstat( ifd, &st);
cout << "Open " << st.st_size << " byte input file.\n";

ofd = open( "/home/john/pgm/tryout/temp1", O_CREAT | O_RDWR, S_IRWXU);
if( ofd < 0)
{
perror( "output file");
return 1;
}

cout << "Opened output file, now truncating file at " <<
st.st_size / 1024 / 1024 << " Mb's.\n";

ftruncate( ofd, st.st_size); // Note this cuty...
// ftruncate is not in glibc, its a system call, and works instantaneously.

cout << "Truncated file.\n";

icp = (char *)mmap( 0, st.st_size,
PROT_READ, MAP_FILE | MAP_SHARED, ifd, 0);

if( icp == (char *)-1)
{
perror( "input memory map");
return 1;
}

cout << "Mapped input file.\n";

ocp = (char *)mmap( 0, st.st_size,
PROT_WRITE, MAP_FILE | MAP_SHARED, ofd, 0);

if( ocp == (char *)-1)
{
perror( "output memory map");
return 1;
}

cout << "Mapped output file.\n";

memcpy( ocp, icp, st.st_size); // Shove data across, this is where
// the real work would go.

cout << "Done the mem copy.\n";

munmap( icp, st.st_size);

cout << "Unmapped input array.\n";

munmap( ocp, st.st_size);

cout << "Unmapped output array.\n";

if( close( ifd) < 0)
{
perror( "close input file");
return 1;
}

cout << "Closed input file.\n";

if( close( ofd) < 0)
{
perror( "close output file");
return 1;
}

cout << "Closed output file.\n";
}