4

Using C, I'm trying to set up shared memory. My code looks like:

key_t key = ftok("SomeString", 1);
static int *sharedval;
int shmid = shmget(key, sizeof(int), S_IRUSR | S_IWUSR); // less permissions
sharedval = (int *) shmat(shmid, NULL, 0);
*sharedval = 0;

However the second I run that last line, I get a segmentation fault. When debugging, I can print "sharedval" and I get a memory address, presumably the place in memory I got. So I would assume all I have to do is use *sharedval to assess it, but apparently not. How am I supposed to read from the shared memory? A push in the right direction would be wonderful. Thanks!

Edit:

another.anon.coward's output:

$ ./a.out 
ftok: No such file or directory
shmget: No such file or directory
Trying shmget with IPC_CREAT
shmget success
shmat success
Segmentation fault: 11
alk
  • 69,737
  • 10
  • 105
  • 255
adammenges
  • 7,848
  • 5
  • 26
  • 33

4 Answers4

7

The problem in your case could be that there is no associated memory segment for the given key. You need to create a memory segment by passing IPC_CREAT flag in shmget in that case. Please use perror to check your error message. Use can try the following code

    #include <stdio.h> //For perror
    ...

    key_t key = ftok("SomeString", 1);
    if ( 0 > key )
    {
       perror("ftok"); /*Displays the error message*/
       /*Error handling. Return with some error code*/
    }
    else /* This is not needed, just for success message*/
    {
       printf("ftok success\n");
    }

    static int *sharedval;
    int shmid = shmget(key, sizeof(int), S_IRUSR | S_IWUSR | IPC_CREAT);
    if ( 0 > shmid )
    {
        perror("shmget"); /*Displays the error message*/
    }
    else /* This is not needed, just for success message*/
    {
       printf("shmget success\n");
    }

    sharedval = (int *) shmat(shmid, NULL, 0);
    if ( 0 > sharedval )
    {
       perror("shmat"); /*Displays the error message*/
       /*Error handling. Return with some error code*/
    }
    else /* This is not needed, just for success message*/
    {
       printf("shmat success\n");
    }
    *sharedval = 0;
    ...
another.anon.coward
  • 11,087
  • 1
  • 32
  • 38
  • Awesome, thanks for writing that up. However I get an error. I added the output to my post. So I still get the Segmentation fault when running *sharedval = ... – adammenges Sep 21 '11 at 15:26
  • There's no need to do a double call to `shmget`, you can always call it with `IPC_CREAT`, it will either create a new segment, or use the existing one. – Hasturkun Sep 21 '11 at 15:40
  • 1
    @InBetween: You have to add error handling code instead of the comment in the code after `perror` call :) ... As it is seen from your output there is no file which exists by the name "SomeString" in the current directory which is indicated by the error message of `ftok`. The same was pointed out by @gby. Please create a file by the name "SomeString" in the path where you are running this and post the output. Could you also some info about the environment and the compiler? @Hasturkun: Thank you for the input! I will update the code. – another.anon.coward Sep 22 '11 at 03:22
3

The problem is that ftok requires an existing file which can be passed to fstat and not an arbitrary string. From the man page:

key_t ftok(const char* pathname, int proj_id)

The ftok() function uses the identity of the file named by the given pathname (which must refer to an existing, accessible file) ...

An easy fix is to try:

int main(int argc, char* argv[])
{
  key_t key = ftok(argv[0], 1);
  ...
}

This also explains why you are getting an ENOENT (No such file or directory) error from ftok.

Barnaby Dalton
  • 158
  • 1
  • 1
  • 8
2

The right way to do shared memory in modern programs is with mmap and MAP_SHARED. You can use either an ordinary file or a named shared memory object created with shm_open.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
1

As noted above your code is missing error checking. For example the way for shmat to indicate an error is to return -1, which when it is displayed as a pointer looks like a long int - so that very well what is happening here.

Specifically, note that ftok(), which stand for File Token, needs to get the path to a valid file on the Linux file system to derive the shared memory ID from the file inode number (it does not look at the file content). Unless you have a file in your current directory called SomeString this is why this call is failing.

Last but not least, I really recommend using POSIX shared memory API rather then the SySV API you are using. See shm_open(3) (http://linux.die.net/man/3/shm_open) for the details

gby
  • 14,900
  • 40
  • 57