Принудительная запись файла на диск

В настоящее время я реализую схему буферизации ping / pong для безопасной записи файла на диск. Я использую C ++ / Boost на машине Linux / CentOS. Теперь я столкнулся с проблемой принудительной записи файла на диск. Возможно ли это сделать независимо от всех политик кэширования файловой системы (ext3 / ext4) / пользовательских правил SO / контроллера RAID / контроллера жесткого диска?

Лучше всего использовать обычную файловую систему fread () / fwrite (), c ++ ostream или boost?

Я слышал, что простое удаление файла (fflush ()) не гарантирует фактическую запись

3

Решение

fflush (для FILE *), std :: flush (для IOStream) для принудительной отправки вашей программы в ОС.

POSIX имеет

  • sync (2), чтобы попросить запланировать запись своих буферов, но может вернуться до того, как запись будет завершена (Linux ожидает, что данные будут отправлены на оборудование, прежде чем вернуться).

  • fsync (2), который гарантированно ожидает отправки данных на оборудование, но нуждается в дескрипторе файла (вы можете получить его из FILE * с помощью fileno (3), я не знаю ни одного стандартного способа получить его из IOStream).

  • O_SYNC как флаг для открытия (2).

Во всех случаях аппаратное обеспечение может иметь свои собственные буферы (но если оно имеет контроль над ним, хорошая реализация попытается также сбросить их и ISTR, что некоторые диски используют конденсаторы, чтобы они могли сбросить все, что происходит с питанием) и сетевые файловые системы имеют свои собственные предостережения.

5

Другие решения

Ты можешь использовать FSYNC() /fdatasync() Принудительно (Примечание 1) данные на хранение.
Те требуют файлового дескриптора, как указано, например, открыть().
man-страница linux иметь больше специфической информации для Linux, особенно о разнице fsync и fdatasync.

Если вы не используете дескрипторы файлов напрямую, многие абстракции будут содержать внутренние буферы, находящиеся в вашем процессе.

например если вы используете ФАЙЛ *, сначала вы должны удалить данные из вашего приложения.

//... open and write data to a FILE *myfile
fflush(myfile);
fsync(fileno(myfile));
  • Примечание 1: Эти вызовы заставляют ОС гарантировать, что любые данные в любом кеше ОС записываются на диск, и диск подтверждает этот факт. Многие жесткие диски лгут ОС об этом и могут помещать данные в кэш-память на диске.
2

Не в стандартном C ++. Вам придется использовать какую-то конкретную систему
IO, как open с O_SYNC флаг под Unix, а затем write,

Обратите внимание, что это частично подразумевается тем фактом, что ostream (И в
C, FILE*) буферизируются. Если вы не знаете точно, когда что-то
записать на диск, тогда нет смысла настаивать на
Транзакционная целостность записи. (Это не будет слишком сложно
дизайн streambuf который только пишет, когда вы делаете явный сброс,
тем не мение.)

РЕДАКТИРОВАТЬ:

В качестве простого примера:

class SynchronizedStreambuf : public std::streambuf
{
int myFd;
std::vector<char> myBuffer;

protected:
virtual int overflow( int ch );
virtual int sync();

public:
SynchronizedStreambuf( std::string const& filename );
~SynchronizedStreambuf();
};

int SynchronizedStreambuf::overflow( int ch )
{
if ( myFd == -1 ) {
return traits_type::eof();
} else if ( ch == traits_type::eof() ) {
return sync() == -1 ? traits_type::eof() : 0;
} else {
myBuffer.push_back( ch );
size_t nextPos = myBuffer.size();
myBuffer.resize( 1000 );
setp( &myBuffer[0] + nextPos, &myBuffer[0] + myBuffer.size() );
return ch;
}
}

int SynchronizedStreambuf::sync()
{
size_t toWrite = pptr() - &myBuffer[0];
int result = (toWrite == 0 || write( myFd, &myBuffer[0], toWrite ) == toWrite ? 0 : -1);
if ( result == -1 ) {
close( myFd );
setp( NULL, NULL );
myFd = -1;
} else {
setp( &myBuffer[0], &myBuffer[0] + myBuffer.size() );
}
return result;
}

SynchronizedStreambuf::SynchronizedStreambuf( std::string const& filename )
: myFd( open( filename.c_str(), O_WRONLY | O_CREAT | O_SYNC, 0664 ) )
{
}

SynchronizedStreambuf::~SynchronizedStreambuf()
{
sync();
close( myFd );
}

(Это было только поверхностно проверено, но основная идея есть.)

0
По вопросам рекламы [email protected]