mmap is memory map. What it does is to map files into memory. mmap is mainly used as the following purposes.
- read/write files with less overhead - allocate a bigger memory space (depends on OS) - shared memory between processes
Think about the case that we read all contents from a file. In such a case, we might prepare a buffer and keep reading until the end of the file. It looks as follows:
/* naive code to read all contents of a file */
apr_file_t *fp;
apr_file_open(&fp, filename, APR_READ, APR_OS_DEFAULT, mp);
while (1) {
char buf[1024];
apr_size_t len = sizeof(buf);
rv = apr_file_read(fp, buf, &len);
if (rv != APR_SUCCESS) {
break;
}
/* scan buf */
}
apr_file_close(fp);
We can do the same thing with apr_mmap_t as follows:
/* excerpted from mmap-sample.c, but I omitted error checks */
apr_file_open(&fp, filename, APR_READ, APR_OS_DEFAULT, mp);
apr_finfo_t finfo;
apr_file_info_get(&finfo, APR_FINFO_SIZE, fp);
apr_mmap_t *mmap;
apr_mmap_create(&mmap, fp, 0, finfo.size, APR_MMAP_READ, mp);
/* scan mmap->mm */
apr_mmap_delete(mmap);
If the file is big enough, mmap based code can be faster.
More importantly, mmap can be against memory fragmentation. Most of dynamic memory allocation systems have memory fragmentation problem, but mmap is out of such user-space memory allocation managements. Unfortunatelly, on some OSes, mmap might be buggy or slow.
We can use mmap to modify files. We open the file with APR_WRITE, and we have to mmap the file with APR_MMAP_WRITE flag.
REMARK: You can't mmap the file that is opened with APR_BUFFERED flag. The following code returns APR_EBADF.
/* BUGGY mmap sample */
apr_file_t *fp;
apr_mmap_t *mm;
apr_file_open(&fp, fname, APR_READ|APR_BUFFERED, APR_OS_DEFAULT, mp);
rv = apr_mmap_create(&mm, fp, 0, finfo.size, APR_MMAP_READ, mp);/* BUG: rv==APR_EBADF */