2013-05-19 3 views
1

Я пытаюсь записать в разделяемую память, но по какой-то причине после вызова shmat() и strcpy я получаю ошибку сегментации (сбрасывание ядра), почему это так?shmat возвращает ошибку сегментации (core dumped)

Это мой код:

int fd,shmid; 
key_t shmkey; 
char *shm_add; 
pid_t pid,pid1=0,pid2=0; 

shmkey=ftok("shmdemo.c",'j'); 
if (shmkey == (key_t)-1) 
{ 
    printf("main: ftok() for shm failed\n"); 
    return -1; 
} 
shmid=shmget(shmkey, 50, 0666 | IPC_CREAT | IPC_EXCL); 
if (shmid == -1) 
{ 
    printf("main: shmget() failed\n"); 
    return -1; 
} 
shm_add=(char *)shmat(shmid,0,0); 
if (shm_add==NULL) 
{ 
    printf("main: shmat() failed\n"); 
    return -1; 
} 

strcpy(shm_add,"hello"); 

редактировать: У меня есть имя файла shmdemo.c на каталог, а ERRNO из shmget сказать «Файл существует», но когда я удалить «shmdemo.c» из каталог, новое errno приходит в ftok, который говорит «Нет такого файла или каталога».

спасибо, Asaf.

+1

Какая ценность 'shm_add'? (Или, как правило, проверьте возвращаемые значения всех системных вызовов, если они сообщают об успехе.) – millimoose

+0

Хорошо, я добавил возврат для системных вызовов, проблема в shmget. Зачем? –

+2

Ну, что [значение 'errno' после сбоя вызова] (http://linux.die.net/man/3/perror)? И, следовательно, что означает '' man shmget' '(http://linux.die.net/man/2/shmget), что означает значение errno? – millimoose

ответ

0

Попробуйте удалить IPC_EXCL флаг и проверьте программу.

+0

Ну, когда я удаляю это, это работа! В чем важность этого? мне все еще нужно удалить сегмент, прежде чем создавать новый? –

+0

@asafregev Без 'IPC_EXCL' вы получите ранее созданный сегмент разделяемой памяти, если он есть. Однако обратите внимание, что он будет иметь размер, на который он был сначала назначен, а не тот, который находится в текущем вызове 'shmget', поэтому вы используете' IPC_EXCL', когда хотите убедиться, что вы получаете новый сегмент памяти. (Как правило, это ожидание, когда вы не хотите явно использовать ранее созданный.) – millimoose

+1

Использование IPC_EXCL означает, что вам гарантировано, что никакой другой процесс не использует ключ общей памяти; если вы не используете это в вызове 'shmget()', вы можете использовать чей-то кусок разделяемой памяти, что обычно является причиной большого несчастья хотя бы одной из программ. Таким образом, параметр IPC_EXCL важен для безопасности в долгосрочной перспективе. В краткосрочной перспективе, пропуская IPC_EXCL, вы получите код мимо горба до тех пор, пока не удалите раздел разделяемой памяти до выхода программы. –

2

Ответы на различные комментарии. Когда вы звоните:

shmget(..., IPC_CREAT | IPC_EXCL); 

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

Если вы используете только:

shmget(..., IPC_CREAT); 

вы говорите: Если сегмент разделяемой памяти уже существует с этим ключом, вернуть его; иначе создать новый для этого ключа и вернуть его.

Как правило, вам, вероятно, не нужен второй вариант вызова. Параллелизм достаточно сложный, без добавления какого-либо собственного недетерминированности. (Т. Е. Просто учитывая, что какой-либо из нескольких взаимодействующих процессов приходит сначала, создает общую память, а не имеет назначенный процесс «владелец».)

При использовании первого вызова, если сегмент разделяемой памяти уже существует в заданном ключ, syscall с ошибкой errnoEEXISTS. SysV IPC являются постоянными, поэтому они автоматически не очищаются после выхода из вашей программы, например дескрипторов файлов. (Фактически, они более похожи на временные файлы.)

Вы должны очистить их в своей программе, используя что-то вроде shmctl(shmid, IPC_RMID, NULL);. Вы также можете проверить наличие бродячих объектов IPC с помощью ipcs и удалить оставшиеся с ipcrm или cleanipcs.

Смежные вопросы