lkml.org 
[lkml]   [2004]   [Jul]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
Subjectmmap + mprotect + malloc strange behaviour
Hi all,

I am writing a tool which keeps track of the accessed
memory pages and needs to persist the modified pages
back to disk on exit. For the purpose, it mmaps a
large file (512MB or 131072 pages), then protects all
its pages for both reading and writing using mprotect(
ptr, PAGE_SIZE, 0). I do this in order to be able to
keep track of the accessed pages.

Throughout the code I also use malloc in order to
allocate heap memory for some of the internal
structures. The problem I have is that all mallocs
that follow the mmapping and mprotect described above
return NULL, no matter what the passed size is.

I noticed that this behaviour is caused by the
mprotection of the pages one-by-one rather than as a
whole chunk. E.g., if I mprotect my whole mmapped
space with a single call everything works fine at the
beginning. However, this is not very helpful, because
in the process of execution, I eventually mprotect
many separate pages, and malloc starts to fail again.

I checked my limits using the "ulimit" BASH command
and it shows that I have no limits concerning
memory-related issues.

------------------
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
max locked memory (kbytes, -l) unlimited
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 4092
virtual memory (kbytes, -v) unlimited
-------------------

With my lack of knowledge about Linux VM management I
can only suspect that is some way I am exceeding the
process' virtual address space slots and it cannot
bookkeep the additional malloc entries.

I am using Fedora Linux on a dual AMD Athlon MP 2600+
processor machine with 512MB of physical memory and
1GB swap disk space. However, I observe the same
effects on many other machines and distributions (for
example, 4 Intel Xeon processor machine with 4GB RAM +
6GB swap running Red Hat Linux 9).

Has anyone had a similar problem, and does anyone know
a remedy for it? At the bottom of this post I have
pasted a sample program that exhibits this behaviour.

Any help will be much appreciated. Please, if
possible, reply to (or CC) my personal email address
in answers to this post.

Many thanks in advance.

Cheers,
Kaloian.


----- Sample code (buildable)
--------------------------

#include <stdio.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>

#define PAGE_SIZE 4096
#define NUM_PAGES 131072
#define SIZE PAGE_SIZE * NUM_PAGES
#define MMAP_ADDR ((void *)0x10000000L)

int array[ NUM_PAGES * 64];
int * mem_load;

int main( int argc, char ** argv) {
char c;
int i;
int fd_mmap = open( "/tmp/swap.tmp", O_CREAT |
O_RDWR, S_IRWXU);

if ( fd_mmap) {
lseek( fd_mmap, SIZE - 1, SEEK_SET);
write( fd_mmap, &c, 1);
}

printf( "Allocating %d bytes of memory...\n",
SIZE);
mem_load = malloc( SIZE);
printf( "mem_load = %p\n", mem_load);
array[ NUM_PAGES * 64 - 1] = 10000;

if ( NULL == mem_load)
printf( "Failed...\n");

void * p = mmap( MMAP_ADDR, SIZE, PROT_READ |
PROT_WRITE,
MAP_FIXED | MAP_SHARED, fd_mmap, PAGE_SIZE);
printf( "File %d mapped at %p.\n", fd_mmap, p);
if ( !p) {
exit( 1);
}
void * alias = mmap( MMAP_ADDR + 2 * SIZE, SIZE,
PROT_READ |
PROT_WRITE, MAP_SHARED, fd_mmap, PAGE_SIZE);
if ( !alias) {
exit( 2);
}
void * pg = p;
for ( i = 0; i < NUM_PAGES; i++) {
if ( 0 > mprotect( pg, PAGE_SIZE, 0)) {
printf( "Failed to mprotect.\n");
exit( 4);
}
pg += PAGE_SIZE;
}

/* If you substitute the above with the call
below,
malloc suddenly starts to work. */
// mprotect( pg, SIZE, 0);

printf( "Alias mapped at %p.\n", alias);

assert( mem_load > p + SIZE || ( (mem_load < p +
SIZE) && ((
mem_load + SIZE) < alias)));

free( mem_load);
mem_load = malloc( SIZE);
printf( "mem_load = %p\n", mem_load);

return 0;
}



__________________________________
Do you Yahoo!?
Yahoo! Mail - Helps protect you from nasty viruses.
http://promotions.yahoo.com/new_mail
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 14:04    [W:0.034 / U:0.248 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site