Solved

mmap() disk file to shared memory

Posted on 1997-04-21
10
210 Views
Last Modified: 2013-12-26
I am trying to do the following in the Solaris environment.

Problem Statement
-----------------
My basic problem is that I would like to mmap() a disk file into *shared* memory. Or does this not make any sense at all?

Background
----------
I have been able to mmap() a disk file into memory.
I have been able to create a shared memory segment and attached/detached to it.
Now, what I would like is to mmap() the disk file into the shared memory segment I create in the previous step. I tried this by passing the address returned by the creation of the shared memory segment, to the mmap() call. But all mmap() did was to map the file in a memory location "close to" the shared memory segment.

Thanks in advance.
0
Comment
Question by:SatComm
  • 6
  • 4
10 Comments
 

Author Comment

by:SatComm
ID: 1292616
I meant to say that my environment was Solaris 2.5
0
 
LVL 2

Accepted Solution

by:
mlev earned 100 total points
ID: 1292617
The optional start address you specify as a parameter to mmap() call, is only a "hint". If you want mmap() to use the exact address, pass MAP_FIXED in the flags parameter.
On the other hand, you can pass NULL for start address and MAP_SHARED for flags. mmap() will then allocate memory on its own. You won't need to use either shmget() or shmat(). The memory
will be shared in the sense that if several processes call mmap() with start=NULL and flags=MAP_SHARED for the same file, they will all map to the same memory address. It will be different from the shared memory segments you create with shmget() in the sense that you cannot access it with a key or id.
Hope this helps.
0
 

Author Comment

by:SatComm
ID: 1292618
I liked the second approach and have gotten it to work.
Thanks for providing the missing link in my understanding of mmap()!

Unfortunately, I need to also use the first approach. When I changed the flags parameter to MAP_FIXED, and passed the address returned by shmat() to mmap() as the start address, mmap() fails with errno set to EINVAL. My offset parameter is still 0. Any hints on what could be going wrong? Could it be a page alignment problem? If you have some sample code handy, could you please provide that.

Thanks!
0
 
LVL 2

Expert Comment

by:mlev
ID: 1292619
In principle, page alignment could be a problem, but your
address comes from shmat() and is thus always page-aligned.
Your problem comes from invalid flags parameter.
Either MAP_PRIVATE or MAP_SHARED always has to be specified.
MAP_FIXED is an "add-on". That is, you have to use MAP_SHARED|MAP_FIXED.

Here is a sample program that works for me (Linux 2.0.18)

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/fcntl.h>
#include <sys/mman.h>

main()
{
        key_t key;
        int shmid;
        char *shmaddr;
        int fd;

        if ((key = ftok("/bin/cat", 'A')) == -1) { perror("ftok"); exit(1); }
        if ((shmid = shmget(key, 100000, IPC_CREAT|0600)) == -1) { perror("smget"); exit(1); }
        if ((shmaddr = shmat(shmid, NULL, 0)) == NULL) { perror("shmat"); exit(1); }

        if ((fd = open("shm.c", O_RDONLY)) == -1) { perror("open"); exit(1); }
        if (mmap(shmaddr, 500, PROT_READ, MAP_SHARED|MAP_FIXED, fd, 0) == -1) { perror("mmap"); exit(1); }
}

(I checked return values with strace.)

0
 

Author Comment

by:SatComm
ID: 1292620
Well, I got the "writer" side of things to work, i.e. if I can call the process that creates the shared memory and maps a file to that location as the writer, as you have indicated in your example above.

But now, another process, the "reader", needs to read that file in the shared memory created by the writer. I did an shmget() to get the shmId from the key (used by the writer); and then did an shmat(), using the  id. shmat() returns the same address as the start of the shared memory, but then I dont see the contents of the mapped file in the reader process! Am I missing something here?
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 2

Expert Comment

by:mlev
ID: 1292621
You have to use mmap() in both processes.
0
 

Author Comment

by:SatComm
ID: 1292622
If we use mmap() of the same file in the reader process also, then we are, in essence, back to the second option you had originally suggested, and I dont really need to use shmget() and shmat().
To use mmap() to map the *shared memory* to the specific location in the reader process, requires the shared memory file descriptor. shmget(), etc. dont return file descriptors, but rather IDs. Solaris 2.5 does not support the POSIX interface yet, i.e., shm_open() etc. that work with file descriptors...

I guess, at this point, I'm stuck.
0
 

Author Comment

by:SatComm
ID: 1292623
Any further suggestions???
0
 
LVL 2

Expert Comment

by:mlev
ID: 1292624
I don't think there is any way to use mmap() without opening the file in both processes.
You are right - there is no need to use shmget() and shmat() when you use mmap(). And shm_open() wouldn't help you, either. Below is the closest possible, to my understanding, analogy between shared memory segments and memory-mapped files:
shared memory segment <---> file
shmget()              <---> open()
shmid                 <---> fd
shmat()               <---> mmap()
shmdt()               <---> munmap()
N/A                   <---> close()
shmctl()              <---> fcntl()

You cannot map a file to a shared memory segment, same as you cannot map one file to another. The best you can do is make them share a common logical memory address in a process' paging space (which you did, with MAP_FIXED), but that doesn't help much.

Is there any special reason why you are reluctant to open the file in the second process?
0
 

Author Comment

by:SatComm
ID: 1292625
Thanks for your input.

The reason is that, I didn't want the second process to have to deal with files and filenames, but just memory and shared memory.  In our system, the files arrive on disk via FTP from a different location, and the files names might contain some type of timestamp for identification purposes. I wanted the first process to be the front end that opens the file, maps it to shared memory, makes some changes in memory, and then sends a notification to the second process to pick up the info from shared memory, and not worry about dynamically changing filenames, etc. Now, I could do other things to get around the name changes, I suppose, but I wanted to see if I could avoid that.

As a first step workaround, in my first process, after mapping the file to some other location in memory, I am doing a memcpy() into shared memory for the second process to be able to see the file...
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
How to create frequencies of a variable from SAS dataset? 10 121
sameEnds challenge 3 134
Fibonacci challenge 11 109
Detect file exist or not 3 132
Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
Introduction: Dialogs (2) modeless dialog and a worker thread.  Handling data shared between threads.  Recursive functions. Continuing from the tenth article about sudoku.   Last article we worked with a modal dialog to help maintain informat…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Internet Business Fax to Email Made Easy - With  eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, f…

910 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

24 Experts available now in Live!

Get 1:1 Help Now