C: "Нет такого файла или каталога" в sem_open с O_CREAT и правильным именем семафора
Я пытаюсь создать семафоры в функции инициализации в C, как это:
void sem_init(int size, sem_t** sem1, sem_t** sem2) {
char* semname1 = "/somename";
char* semname2 = "/someothername";
errno = 0;
*sem1 = sem_open(semname1, O_CREAT, S_IRUSR|S_IWUSR, 0);
printf(strerror(errno));
errno = 0;
*sem2 = sem_open(semname2, O_CREAT, S_IRUSR|S_IWUSR, size);
printf(strerror(errno));
}
Но даже несмотря на то, что я установил флаг O_CREAT и имена well_formed, я всегда получаю "Нет такого файла или каталога" в качестве вывода. Семафоры создаются в /dev/shm/...
Я не вижу очевидной причины возникновения ошибки. Пожалуйста, помогите мне в том, что я делаю неправильно.
Заранее благодарны за Вашу помощь.
2 ответа
Как указывалось в комментариях к вопросу о ФП, неверное значение в errno
используется. Предложить:
void sem_init(int size, sem_t** sem1, sem_t** sem2) {
char* semname1 = "/somename";
char* semname2 = "/someothername";
sem_t local_sem1;
sem_t local_sem2;
if( (local_sem1 = sem_open(semname1, O_CREAT, S_IRUSR|S_IWUSR, 0) ) == SEM_FAILED )
{
perror( "sem_open for sem1 failed" );
exit( EXIT_FAILURE );
}
*sem1 = local_sem1;
if( (local_sem2 = sem_open(semname2, O_CREAT, S_IRUSR|S_IWUSR, 0) ) == SEM_FAILED )
{
perror( "sem_open doe awm2 failed" );
exit( EXIT_FAILURE );
}
*sem2 = local_sem2;
}
Как сообщалось в комментариях и предыдущих ответах, errno не определено после вызова службы, если последний не вернулся с ошибкой (например, -1 или SEM_FAILED или MAP_FAILED в зависимости от службы). Причина заключается в том, что служба может вызывать несколько подслужб, которые могут временно выйти из строя и привести к установке некоторых значений для параметра errno , но это не приведет к сбою самой службы.
Например, внутренне создает временный файл в /dev/shm. Для этого он генерирует случайное имя благодаря
#define NRETRIES 50
while (1)
{
/* We really want to use mktemp here. We cannot use mkstemp
since the file must be opened with a specific mode. The
mode cannot later be set since then we cannot apply the
file create mask. */
if (__mktemp (tmpfname) == NULL)
{
result = SEM_FAILED;
goto out;
}
/* Open the file. Make sure we do not overwrite anything. */
fd = __open (tmpfname, O_RDWR | O_CREAT | O_EXCL, mode);
if (fd == -1)
{
if (errno == EEXIST)
{
if (++retries < NRETRIES)
{
/* Restore the six placeholder bytes before the
null terminator before the next attempt. */
memcpy (tmpfname + sizeof (tmpfname) - 7, "XXXXXX", 6);
continue;
}
__set_errno (EAGAIN);
}
result = SEM_FAILED;
goto out;
}
/* We got a file. */
break;
}
В случае использования OP errno равно ENOENT , а служба возвращает значение, отличное от SEM_FAILED . На самом деле сервис понимает, что файл для создания уже существует. Поскольку флаг O_EXCL не передается, считается, что все в порядке. Таким образом, файл удаляется, и снова предпринимается попытка открытия, чтобы убедиться, что получен ENOENT перед повторным созданием файла. Вот фрагмент кода той же функции для этого варианта использования:
[...]
try_again:
fd = __open (dirname.name,
(oflag & ~(O_CREAT|O_ACCMODE)) | O_NOFOLLOW | O_RDWR);
if (fd == -1)
{
/* If we are supposed to create the file try this next. */
if ((oflag & O_CREAT) != 0 && errno == ENOENT)
goto try_create;
/* Return. errno is already set. */
}
else
/* Check whether we already have this semaphore mapped and
create one if necessary. */
result = __sem_check_add_mapping (name, fd, SEM_FAILED);
[...]
if ((oflag & O_EXCL) == 0 && errno == EEXIST)
{
/* Remove the file. */
__unlink (tmpfname);
/* Close the file. */
__close (fd);
goto try_again;
}
[...]