Понимание общей памяти с помощью C - PullRequest
2 голосов
/ 21 сентября 2011

С помощью C я пытаюсь настроить общую память.Мой код выглядит так:

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;

Однако, как только я запускаю эту последнюю строку, я получаю ошибку сегментации.При отладке я могу напечатать «sharedval» и получить адрес памяти, предположительно место в памяти, которое я получил.Поэтому я бы предположил, что все, что мне нужно сделать, это использовать *sharedval для оценки, но, видимо, нет.Как я должен читать из общей памяти?Толчок в правильном направлении был бы замечательным.Спасибо!

Редактировать:

Другой.anon.coward вывод:

$ ./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

Ответы [ 4 ]

5 голосов
/ 21 сентября 2011

Проблема в вашем случае может заключаться в том, что для данного ключа нет связанного сегмента памяти. Вам нужно создать сегмент памяти, передав в этом случае флаг IPC_CREAT в shmget. Пожалуйста, используйте perror, чтобы проверить сообщение об ошибке. Используйте можете попробовать следующий код

    #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 голосов
/ 08 августа 2012

Проблема в том, что ftok требует существующий файл, который можно передать в fstat, а не произвольную строку. Со страницы руководства:

key_t ftok (const char * pathname, int proj_id)

Функция ftok () использует идентификатор файла с именем по указанному пути (который должен ссылаться на существующий доступный файл) ...

Простое решение - попробовать:

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

Это также объясняет, почему вы получаете сообщение ENOENT (нет такого файла или каталога) от ftok.

1 голос
/ 21 сентября 2011

Как отмечено выше, в вашем коде отсутствует проверка ошибок.Например, shmat может указать на ошибку, чтобы возвратить -1, которая, когда она отображается в виде указателя, выглядит как long int - так что очень хорошо, что здесь происходит.

В частности, обратите внимание, что ftok(), что означает File Token, должен получить путь к допустимому файлу в файловой системе Linux для получения идентификатора общей памяти из номера файлового индекса (он не смотрит на содержимое файла).Если у вас нет файла в текущем каталоге с именем SomeString, поэтому этот вызов не выполняется.

И последнее, но не менее важное, я действительно рекомендую использовать API совместно используемой памяти POSIX, а не API SySV, который вы используете.Смотрите shm_open (3) (http://linux.die.net/man/3/shm_open) для деталей

1 голос
/ 21 сентября 2011

В современных программах правильно использовать разделяемую память с mmap и MAP_SHARED.Вы можете использовать либо обычный файл, либо именованный объект общей памяти, созданный с помощью shm_open.

...