Почему semget() вызывает ошибку EACCES при * создании * семафора?

#c #unix #permissions #ipc #semaphore

#c #unix #разрешения #ipc #семафор

Вопрос:

Я должен создать массив семафоров для проекта на C . Я вызываю не semget() из main() ; у меня есть отдельный метод для упрощения, хотя и метод в main.cpp . Когда моя программа достигает semget(semkey,nsems,0666|IPC_CREAT) , она возвращает -1 с ошибкой EACCES, что, по-видимому, означает «Идентификатор семафора существует для key , но разрешение на операцию, указанное младшими 9 битами semflg , не будет предоставлено».

Я снова и снова повторял свой код с помощью GDB. Все три параметра для semget() выглядят правильно, и это первая точка, в которой вызывается программа semget() , поэтому семафор еще не существует; я даже запустил ipcs -s , чтобы убедиться. У меня есть #include <sys/sem.h> в верхней части main.cpp .

Что здесь происходит? Я уже создал и подключил сегмент общей памяти, может ли это иметь к этому какое-то отношение? Я не вижу, как.

Комментарии:

1. Правильно ли это работает в первый раз после перезагрузки?

2. Я не пробовал. Значит, это влияет на это? Почему?

3. Что ж, очистка с помощью ipcs должна была бы сработать, но, чтобы быть уверенным, перезагрузка системы наверняка очистит все оставшиеся общие ресурсы (семафоры, общую память и т.д.)

Ответ №1:

Из руководства :

  EACCES A semaphore set exists for key, but the calling process does not have permission to 
        access the set, and does not have the CAP_IPC_OWNER capability.
  

Напоминаю, поскольку семафор является системным объектом, он удаляется только тогда, когда для этого явно выполняется системный вызов. ( semctl с помощью IPC_RMID команды или ipcrm term).
Кроме того, семафор semkey должен быть уникальным (например, извлекаться из ftok() функции), или возможно, что другая программа создала его до вашего самого первого вызова semget . Поскольку она существовала бы, вы бы перехватили так называемую EACCES ошибку, потому что не все программы используют разрешение 0666 для семафора, как вы.

Перезагрузка очищает пул общих объектов (семафор, сегменты общей памяти, очередь сообщений), как если бы :

 #!/bin/bash
for i in `ipcs -s | cut -f 2 -d ' '`
do
   ipcrm -s $i
done

for i in `ipcs -m | cut -f 2 -d ' '`
do
   ipcrm -m $i
done

for i in `ipcs -q | cut -f 2 -d ' '`
do
   ipcrm -q $i
done