В данный момент я пытаюсь решить аналогичную проблему, что и привело меня к вашему вопросу. Как я понимаю, суть в следующем:
int fd = open(path, O_CREAT|O_RDWR|O_EXCL, mode);
if (fd == -1)
{
/* File already exists. */
the_file_already_exists(fd);
}
else
{
/* I just now created the file. Now I'll lock it. */
/* But first I'll deliberately create a race condition!! */
deliberately_fork_another_process_that_handles_file(path);
int code = flock(fd,LOCK_EX);
if (code < 0)
{
perror("flock");
exit(1);
}
/* I now have the exclusive lock. I can write to the file at will --
or CAN I?? See below. */
write_to_the_file_at_will(fd);
}
Очевидно, что в реальной жизни я бы никогда не стал намеренно создавать такое состояние гонки, но его эквивалент, безусловно, может произойти случайно в реальной системе. Этот другой процесс может, например, открыть файл для чтения, установить на него совместную блокировку и прочитать файл. Он увидит пустой файл. Это может означать, что выполняется операция записи, но может означать, что файл просто пуст, и это правильный и окончательный ответ.
Если пустые файлы запрещены, программа чтения может вести себя точно так же, как если бы файл отсутствовал. В конце концов, если бы ридер запустился на миллисекунду раньше, он все равно не смог бы открыть файл. В этом случае читателю необходимо проверить, пуст ли файл после его открытия.
Если пустые файлы разрешены, то вы находитесь в затруднительном положении, и у меня нет готового ответа на этот вопрос.
Моя проблема заключается в том, что когда файл создается впервые, я хочу записать в него какое-то значение по умолчанию, потому что я хочу «авто-инициализировать» новую систему без предварительного создания всех возможных файлов, которые ей могут понадобиться. Этот другой процесс, обрабатывающий файл, возможно, сам уже инициализировал его! Насколько мне известно, в то же время могли запуститься три других процесса, которые изменили значение. В этом случае я, конечно, не хочу "записывать в файл по своему желанию" после получения эксклюзивной блокировки, потому что я уничтожу все эти изменения.
Я полагаю, что ответ для моего кода выше, чтобы убедиться, что файл пуст, прежде чем писать в него. Если он НЕ пуст, то код должен вести себя точно так же, как если бы файл уже существовал: т. е. он должен вызывать:
the_file_already_exists(fd);
Возможно, суть всего этого обсуждения заключается в том, что каждый процесс, который каким-либо образом обрабатывает файл, должен проверять, не является ли он пустым, и вести себя соответствующим образом. Опять же, если разрешены пустые файлы, то я пока не могу придумать никакого гарантированного решения. Во всем этом не было бы необходимости, если бы существовал какой-то способ создать файл и заблокировать его как единую атомарную последовательность, но я не думаю, что есть какой-либо способ сделать это.
person
Patrick Chkoreff
schedule
21.06.2018