Раньше я думал, что изменения файла сохраняются непосредственно на диск, то есть, как только я закрываю файл и решаю нажать / выбрать сохранить. Однако в недавнем разговоре мой друг сказал мне, что обычно это не так; ОС (в частности, мы говорили о системах Linux) хранит изменения в памяти, и у нее есть демон, который фактически записывает содержимое из памяти на диск.
Он даже привел пример внешних флэш-накопителей: они монтируются в систему (копируются в память), и иногда происходит потеря данных, потому что демон еще не сохранял содержимое во флэш-памяти; именно поэтому мы размонтируем флешки.
У меня нет знаний о функционировании операционных систем, и поэтому я абсолютно не знаю, так ли это и при каких обстоятельствах. Мой главный вопрос: происходит ли это так, как описано в системах Linux / Unix (и, возможно, в других ОС)? Например, означает ли это, что если я выключу компьютер сразу после редактирования и сохранения файла, мои изменения, скорее всего, будут потеряны? Возможно, это зависит от типа диска - традиционные жесткие диски или твердотельные диски?
Этот вопрос относится конкретно к файловым системам, которые имеют диск для хранения информации, даже если любые разъяснения или сравнения хорошо приняты.
источник
sync
, и приложения должныflush
гарантировать, что кэши будут записаны обратно, но даже успешное выполнениеsync
не гарантирует обратной записи только на физический диск, поскольку кэши ядра сбрасываются на диск, что может иметь задержку в драйвере или оборудовании диска (например, кэш-память на диске, которую вы теряете)Ответы:
Они могут быть. Я бы не сказал «скорее всего», но вероятность зависит от многих вещей.
Простой способ повысить производительность записи в файл - для ОС просто кэшировать данные, сказать (лгать) приложению, через которое прошла запись, а затем фактически выполнить запись позже. Это особенно полезно, если одновременно происходит другая активность на диске: ОС может назначать приоритеты чтению и делать записи позже. Это также может полностью устранить необходимость в реальной записи, например, в случае, когда временный файл удаляется быстро после этого.
Проблема с кэшированием становится более заметной, если хранилище работает медленно. Копирование файлов с быстрого SSD на медленный USB-накопитель, вероятно, потребует большого объема кэширования при записи, поскольку USB-накопитель просто не справляется. Но ваша
cp
команда возвращается быстрее, поэтому вы можете продолжать работать, возможно, даже редактируя только что скопированные файлы.Конечно, у такого кеширования есть и обратная сторона: некоторые данные могут быть потеряны до того, как они действительно будут сохранены. Пользователь будет недоволен, если его редактор скажет им, что запись прошла успешно, но на самом деле файл не был на диске. Вот почему существует
fsync()
системный вызов , который должен возвращаться только после того, как файл действительно попал на диск. Ваш редактор может использовать это, чтобы убедиться, что данные в порядке, прежде чем сообщать пользователю, что запись прошла успешно.Я сказал: «Предполагается», поскольку сам накопитель может сказать ту же ложь ОС и сказать, что запись завершена, в то время как файл действительно существует только в энергозависимом кеше записи внутри накопителя. В зависимости от диска, может не быть никакого пути к этому.
Кроме того
fsync()
, существуют такжеsync()
иsyncfs()
системные вызовы , которые запрашивают систему , чтобы убедиться , что все общесистемные записи или все записи на конкретной файловой ударяли диск. Утилитаsync
может быть использована для вызова тех.Кроме того, есть
O_DIRECT
флаг toopen()
, который должен «попытаться минимизировать эффекты кэширования ввода-вывода в этот файл и из него». Удаление кэширования снижает производительность, так что в основном оно используется приложениями (базами данных), которые выполняют свое собственное кэширование и хотят контролировать его. (O_DIRECT
не без проблем, комментарии об этом на странице руководства несколько забавны.)То, что происходит при отключении питания, также зависит от файловой системы. Вы должны быть обеспокоены не только данными файла, но и метаданными файловой системы. Наличие данных на диске не очень полезно, если вы не можете их найти. Простое расширение файла до большего размера потребует выделения новых блоков данных, и они должны быть где-то отмечены.
То, как файловая система справляется с изменениями метаданных, и порядок между метаданными и записью данных сильно различается. Например, с помощью
ext4
, если вы установите флаг монтированияdata=journal
, тогда все записи - даже записи данных - проходят через журнал и должны быть достаточно безопасными. Это также означает, что они пишутся дважды, поэтому производительность снижается. Параметры по умолчанию пытаются упорядочить записи так, чтобы данные находились на диске до обновления метаданных. Другие параметры или другие файловые системы могут быть лучше или хуже; Я даже не буду пытаться всесторонне изучить.На практике в слегка загруженной системе файл должен попасть на диск в течение нескольких секунд. Если вы имеете дело со съемным хранилищем, размонтируйте файловую систему перед извлечением носителя, чтобы убедиться, что данные действительно отправлены на диск, и больше никаких действий нет. (Или ваша среда графического интерфейса сделает это за вас.)
источник
some cases where
Похоже, ваша ссылка не говорит ни о каких подобных случаях - вместо этого говорится, что были проблемы, когда приложения не использовалисьfsync
. Или я должен посмотреть в комментариях, чтобы найти эти случаи, на которые вы указываете?sync
непосредственно как команду системной оболочки, чтобы запустить ядро для очистки всех кешей.fsync()
после записи файла. По умолчанию для Linux установлено значение/proc/sys/vm/dirty_writeback_centisecs
500 (5 секунд), и PowerTop рекомендует установить значение 1500 (15 секунд). ( kernel.org/doc/Documentation/sysctl/vm.txt ). В слегка загруженной системе ядро просто оставит грязным в кеше страницы задолгоwrite()
до того, как записать его на диск, чтобы оптимизировать его для случая, когда оно вскоре будет удалено или изменено снова.Существует чрезвычайно простой способ доказать, что не может быть правдой, что изменения файлов всегда сохраняются непосредственно на диск, а именно тот факт, что существуют файловые системы, которые в первую очередь не поддерживаются диском . Если файловая система не имеет диска, то она никогда не сможет записать изменения на диск .
Вот некоторые примеры:
tmpfs
файловая система, которая существует только в ОЗУ (или, точнее, в буферном кеше)ramfs
файловая система, которая существует только в оперативной памятиsysfs
,procfs
,devfs
,shmfs
, ...)Но даже для дисковых файловых систем это обычно не так. Страница Как повредить базу данных SQLite содержит главу под названием « Невозможность синхронизации», в которой описываются различные способы, с помощью которых записи (в этом случае фиксируются в базе данных SQLite) могут не поступать на диск. В SQLite также есть технический документ, объясняющий множество циклов, через которые вы должны перейти, чтобы гарантировать атомарную фиксацию в SQLite . (Обратите внимание, что атомарная запись гораздо сложнее, чем просто запись , но, конечно, запись на диск является подзадачей атомарной записи, и вы также можете многое узнать об этой проблеме из этой статьи.) раздел о том, что может пойти не так, который включает в себя подраздел оНеполные сбросы диска, которые приводят некоторые примеры тонких хитростей, которые могут помешать записи достигнуть диска (например, сообщение контроллера жесткого диска о том, что оно записано на диск, когда на самом деле его нет - да, есть производители жестких дисков, которые делают это, и это может быть даже законно в соответствии со спецификацией ATA, потому что это неоднозначно сформулировано в этом отношении).
источник
Это правда, что большинство операционных систем, включая Unix, Linux и Windows, используют кэш записи для ускорения операций. Это означает, что выключение компьютера без его выключения является плохой идеей и может привести к потере данных. То же самое верно, если вы извлекаете USB-накопитель до того, как он будет готов к удалению.
Большинство систем также предлагают возможность делать записи синхронно. Это означает, что данные будут на диске до того, как приложение получит подтверждение успеха, за счет того, что оно будет медленнее.
Короче говоря, есть причина, по которой вы должны правильно выключить компьютер и правильно подготовить USB-накопитель для удаления.
источник
fsync()
системного вызова из программы. Из оболочки просто используйтеsync
команду.sync
были реализованы как неактивные. И даже для файловых систем , которые бы правильно реализоватьsync
, есть еще проблема , что некоторые диски прошивки реализоватьFLUSH CACHE
как не-оп или немедленно вернуться из него и выполнять его в фоновом режиме.1. Flash-хранилище
Когда у вас есть выбор, вы не должны позволять флэш-хранилищам терять энергию без чистого выключения.
В недорогом хранилище, таком как SD-карты, вы можете ожидать потери целых блоков стирания (в несколько раз превышающих 4 КБ), потери данных, которые могут принадлежать разным файлам или основным структурам файловой системы.
Некоторые дорогие твердотельные накопители могут утверждать, что предлагают лучшие гарантии в случае сбоя питания. Однако стороннее тестирование показывает, что многие дорогие твердотельные накопители этого не делают. Слой, который перераспределяет блоки для «выравнивания износа», является сложным и запатентованным. Возможные сбои включают в себя потерю всех данных на диске.
2017: https://dl.acm.org/citation.cfm?id=2992782&preflayout=flat
2013: https://www.usenix.org/system/files/conference/fast13/fast13-final80.pdf?wptouch_preview_theme=enabled
2. Вращающиеся жесткие диски
Вращающиеся жесткие диски имеют разные характеристики. В целях безопасности и простоты я рекомендую предположить, что они имеют ту же практическую неопределенность, что и хранилище на основе флэш-памяти.
Если у вас нет конкретных доказательств, которых у вас явно нет. У меня нет сравнительных данных по вращению жестких дисков.
Жесткий диск может оставить один не полностью записанный сектор с неверной контрольной суммой, что впоследствии даст нам хороший сбой при чтении. Вообще говоря, этот режим отказа жестких дисков вполне ожидаем; родные файловые системы Linux разработаны с учетом этого. Они стремятся сохранить договор
fsync()
перед лицом этого типа потери питания. (Мы бы очень хотели, чтобы это было гарантировано на SSD).Однако я не уверен, что файловые системы Linux достигают этого во всех случаях, или это вообще возможно.
Следующая загрузка после этого типа ошибки может потребовать восстановления файловой системы. Так как это Linux, возможно, что при восстановлении файловой системы будут заданы некоторые вопросы, которые вы не понимаете, где вы можете только нажать Y и надеяться, что она уладится.
2.1 Если вы не знаете, что такое контракт fsync ()
Контракт fsync () является источником как хороших, так и плохих новостей. Сначала вы должны понять хорошие новости.
Хорошие новости:
fsync()
хорошо документирован как правильный способ записи данных файла, например, когда вы нажимаете «сохранить». И широко известно, что, например, текстовые редакторы должны заменять существующие файлы атомарно, используяrename()
. Это делается для того, чтобы вы всегда сохраняли старый файл или получали новый файл (который былfsync()
отредактирован до переименования). Вы не хотите, чтобы вас оставили наполовину написанную версию нового файла.Плохая новость: в течение многих лет вызов fsync () для самой популярной файловой системы Linux может эффективно привести к зависанию всей системы на десятки секунд. Поскольку приложения ничего не могут с этим поделать, было очень распространено оптимистично использовать rename () без функции fsync (), которая в этой файловой системе оказалась относительно надежной.
Следовательно, существуют приложения, которые неправильно используют fsync ().
Следующая версия этой файловой системы обычно избегала зависания fsync () - в то же время, когда она начала полагаться на правильное использование fsync ().
Это все довольно плохо. Понимание этой истории, вероятно, не помогло пренебрежительным тоном и оскорблением, которое использовалось многими конфликтующими разработчиками ядра.
Текущее разрешение заключается в том, что текущая самая популярная файловая система Linux
по умолчанию поддерживается шаблон rename () без использования fsync ()реализует совместимость «ошибка за ошибкой» с предыдущей версией. Это можно отключить с помощью опции монтированияnoauto_da_alloc
.Это не полная защита. По сути, он сбрасывает ожидающий IO во время rename (), но не ожидает завершения ввода-вывода перед переименованием. Это намного лучше, чем, например, 60-секундное окно опасности! См. Также ответ на вопрос: Какие файловые системы требуют fsync () для обеспечения безопасности при сбое при замене существующего файла на rename ()?
Некоторые менее популярные файловые системы не обеспечивают защиту. XFS отказывается это сделать. И UBIFS также не реализовал это, по-видимому, это можно было бы принять, но для этого нужно много работать. На той же странице указывается, что у UBIFS есть несколько других проблем с «TODO» для обеспечения целостности данных, в том числе при потере питания. UBIFS - это файловая система, используемая непосредственно во флэш-памяти. Я полагаю, что некоторые трудности, о которых упоминает UBIFS с флеш-памятью, могут быть связаны с ошибками SSD.
источник
В слегка загруженной системе ядро позволит вновь записанным данным файла находиться в кэше страниц в течение, возможно, 30 секунд после a
write()
, перед тем как записать их на диск, чтобы оптимизировать ситуацию, когда они скоро будут удалены или изменены снова.По
dirty_expire_centisecs
умолчанию Linux имеет значение 3000 (30 секунд) и контролирует, как долго истекает срок действия вновь записанных данных. (См. Https://lwn.net/Articles/322823/ ).См. Https://www.kernel.org/doc/Documentation/sysctl/vm.txt для получения дополнительной информации о настройках и Google для получения дополнительной информации. (например, Google на
dirty_writeback_centisecs
).По умолчанию для Linux установлено значение
/proc/sys/vm/dirty_writeback_centisecs
500 (5 секунд) , и PowerTop рекомендует установить его на 1500 (15 секунд) для снижения энергопотребления.Задержка обратной записи также дает ядру время увидеть, насколько большим будет файл, прежде чем начать его запись на диск. Файловые системы с отложенным размещением (такие как XFS и, возможно, другие в наши дни) даже не выбирают, где на диске помещать данные вновь записанного файла, пока не потребуется, отдельно от выделения места для самого inode. Это уменьшает фрагментацию, позволяя им не помещать начало большого файла в промежуток в 1 мегабайт между другими файлами, например.
Если записывается много данных, обратная запись на диск может быть инициирована порогом того, сколько грязных (еще не синхронизированных на диске) данных может находиться в кэше страниц.
Однако если вы больше ничего не делаете, индикатор активности жесткого диска не будет светиться в течение 5 (или 15) секунд после нажатия кнопки «Сохранить» для небольшого файла.
Если ваш редактор использовался
fsync()
после записи файла, ядро запишет его на диск без задержки. (Иfsync
не вернется, пока данные не будут отправлены на диск).Кэширование записи в диске также может быть вещью, но диски обычно пытаются совершить их от записи кэша для постоянного хранения как можно скорее, в отличии от алгоритмов страниц кэша для Linux. Кэши записи на диск - это скорее буфер хранилища для поглощения небольших пакетов записей, но, возможно, также для задержки записи в пользу операций чтения и предоставления места для прошивки дисков для оптимизации схемы поиска (например, две соседние операции записи или чтения вместо одной). затем ищет далеко, затем ищет назад.)
На вращающемся (магнитном) диске вы можете увидеть несколько задержек поиска от 7 до 10 мс каждый перед тем, как данные из команды записи SATA будут фактически защищены от отключения питания, если перед вашей записью были ожидающие чтения / записи. (Некоторые другие ответы на этот вопрос более подробно описывают кэши записи на диск и барьеры записи, которые журнализированные FS могут использовать, чтобы избежать повреждения.)
источник