问题
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
回答1:
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;
...
回答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
.
回答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.
回答4:
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
来源:https://stackoverflow.com/questions/7495326/understanding-shared-memory-using-c