У меня есть очень специфическое приложение, где мне нужна переменная с автоинкрементом и постоянным хранилищем
Чтобы быть точным, я храню десятичное представление переменной int
в файле. Чтобы сгенерировать следующее число, I read()
из файла, преобразовать содержимое обратно в int
, добавить 1 и write()
обратно в файл. Мне НЕ нужен одновременный доступ к этим данным. Только один поток из одного процесса вызывает функции для получения номера автоинкремента. Программа работает во встроенной среде, где никто не будет иметь доступа к консоли, поэтому безопасность не должна быть проблемой. Если это имеет значение, он работает на Linux 2.6.24 на MIPS.
Проблема в том, что я не получаю 100% воспроизводимых результатов. Иногда я получаю повторные номера, что неприемлемо для моего заявления.
Моя реализация заключается в следующем.
При запуске приложения у меня есть:
int fd = open("myfile", O_RDWR|O_CREAT|O_SYNC, S_IRWXU|S_IRWXG|S_IRWXO);
И функции автоинкремента:
int get_current(int fd)
{
char value[SIZE];
lseek(fd, 0, SEEK_SET);
read(fd, value, SIZE);
return atoi(value);
}
int get_next(int fd)
{
char value[SIZE];
int cur = get_current(fd);
memset(value, 0, SIZE);
sprintf(value, "%d", cur + 1);
lseek(fd, 0, SEEK_SET);
write(fd, value, SIZE);
//fsync(fd); /* Could inserting this be the solution? */
return (cur + 1);
}
Я специально исключил проверку ошибок выше для удобства чтения кода. У меня есть код для проверки возвращаемых значений всех системных вызовов.
Код был изначально написан другим человеком, и теперь, когда я обнаружил эту проблему, первый шаг к ее решению - выяснить, что могло ее вызвать. Я обеспокоен тем, что это может быть связано с кэшированием доступа к файлам. Я знаю, что когда у меня write()
нет никакой гарантии, что данные вообще когда-либо достигали физического носителя, но безопасно ли звонить на read()
, не позвонив на fsync()
, и все же получить предсказуемые результаты? Если это так, то у меня нет идей;)
Спасибо за прочтение.