EEXIST без IPC_EXCL на shmget - PullRequest
1 голос
/ 17 ноября 2011

У меня странная проблема с общей памятью.

Метод shmget возвращает -1, а errno устанавливается на EEXIST. По словам человека, это возможно только тогда, когда указаны оба флага IPC_EXCL и IPC_CREAT.

Мой код:

int main()
{
        int shmid = shmget(0xABCD, MAX_SIZE, IPC_CREAT | 0x660);
        int shmid2 = shmget(0xABCD, MAX_SIZE, IPC_CREAT | 0x660 );
        if(shmid == -1)
        {
                if(errno == EEXIST)
                        perror("Error");
                return -1;
        }
        if(shmid2 == -1)
        {
                if(errno == EEXIST)
                        perror("Error2");
                return -1;
        }
        shmctl(shmid, IPC_RMID, NULL);
        return 0;
}

Он компилируется с -Wall без предупреждений, я проверяю с помощью ipcs, если сегмент уже присутствует (и удаляю его при необходимости). Выход Error2: File exists. Это работает, когда я меняю второй shmget на:

int shmid2 = shmget(0xABCD, MAX_SIZE, 0 );

Цитата из man shmget:

EEXIST     IPC_CREAT | IPC_EXCL was specified and the segment exists. 

И еще один вопрос: правда ли, что mode_flags (то есть 0x660) не используются при попытке выполнить shmget?

1 Ответ

4 голосов
/ 17 ноября 2011

Режимы доступа должны быть указаны в восьмеричном , а не шестнадцатеричном.0x660 (шестнадцатеричный) = 03140 (восьмеричный).А флаг IPC_EXCL имеет восьмеричное значение 02000 в Linux ABI - поэтому, используя 0x660 вместо 0660, вы случайно устанавливаете IPC_EXCL, поэтому вы получаете ошибку.

Если я изменю оба экземпляра 0x660 на 0660 в вашей программе и исправлю другие вещи, которые делают его не компилируемым (в частности, вы исключили все заголовки и определение MAX_SIZE), это сработает, как и ожидалось.

...