Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 25 Sep 96 11:28:39 MDT
From:      johnson@charming.nrtc.northrop.com
To:        questions@freebsd.org
Subject:   Question regarding mmap <--> procfs
Message-ID:  <9609251828.AA09743@charming.nrtc.northrop.com>

next in thread | raw e-mail | index | archive | help

Hello all,

My impression is that it is possible in FreeBSD to manipulate the virtual
memory system from outside the kernel.

As an exercise to see if I understand manipulation of virtual memory outside
the kernel, I am trying to do the following:

Execute a program, and have that program manipulate its own virtual memory
mapping, so that two 4096-byte pages get swapped.  (The idea would be to
have a page-aligned 8192-byte array, and initialize it (as a 2048-int array)
with the values 0, 1, 2, .. 2047.  Then, swap the two virtual pages.
Finally loop over the array printing out the values, and have it start out
1024, 1025, ..  This would demonstate that the two pages had indeed been
swapped.)

The way I thought I could do this was to use the mmap function in conjunction
with the procfs file /proc/curproc/mem.  However, at the moment I can't get
this to work.

First question:  Is what I am trying to do supposed to be possible?  (If I
understand mmap and /proc/curproc/mem, it should be possible in principle.)

Second question:  Is there some other means of manipulating virtual memory
outside the kernel that I should be using instead of mmap and /proc/curproc/mem?

Third question:  Why does the program below fail??  ;-)  Am I doing something
obviously wrong in the following program?

I am having some fun playing with mmap.  It seems to work well, and
is really an interesting concept.  However, one thing that I
cannot get to work is using mmap in conjunction with /proc/curproc/mem.

Here's how I thought I could  swap two virtual pages:
(let's call the two pages to be swapped A and B):

1) malloc a fairly large chunk of memory, so that I have something to play with

2) open /proc/curproc/mem in order to get a file descriptor that can be
   used with mmap to manipulate virtual memory.

3) mmap page A into some temporary area of virtual memory.

4) mmap page B into the virtual memory location previously occupied by A.

5) mmap the temporary area into the location previously occupied by B.

The problem I am having is that after I mmap /proc/curproc/mem, I cannot
access it.  I get bus errors.  As in intermediate step to the above
`swap virtual pages' idea, I tried the following experiment, which didn't
work.  Would much appreciate any ideas.

Greg Johnson
johnson@nrtc.northrop.com

--------------------------- cut here -----------------------------
/*
The following program simply attempts to malloc an array, and then
mmap /proc/curproc/mem into virtual memory, to create an `alias' to the
array.  (The same physical memory address would be accessible via two
different virtual memory addresses.)
*/

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

main()
{
   char *map_addr, *vec;
   int i;
   int fd;
   char buf[256];
   char *addr;


/* get a large array to play with */

   vec = (char *) malloc( 80000 );
   printf( "vec %x\n", vec );

/* get a file descriptor to the virtual memory of this process */

   fd = open( "/proc/curproc/mem", O_RDWR );
   printf( "%d\n", fd );

/* demonstrate that we have indeed succeeded in getting at our own
   virtual memory:  Set vec[0] to `A', and then read and print the
   corresponding byte through the file descripter.
*/
   i = lseek( fd, (off_t) vec, SEEK_SET );
   printf( "lseek result %x\n", i );

   vec[0] = 'A';

   i = read( fd, buf, 1 );

/* this works just fine!  Way cool. */

   printf( "read result %x, `%c'\n", i, buf[0] );

/* attempt to map the part of virtual memory containing the array `vec'
   into some other place in virtual memory
*/
   map_addr = mmap( (caddr_t) 0, (size_t) 4096,
	       PROT_READ | PROT_WRITE,
	       MAP_PRIVATE,
	       fd,
	       (off_t) vec
	     );

/* this printf comes back happy; I get a return value that looks like
   a virtual address
*/
   printf( "map_addr %x\n", map_addr );

/* get ready to exercise the alias; here we will write a value to the
   physical address using one virtual address
*/
   vec[0] = 'B';

/* here we are going to try to read the data value back, using the other
   virtual address...  KABOOM.  Bus error.
*/
   printf( "`%c'\n", map_addr[0] );
}



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