Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.235.140.73] |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Есть у меня прога, которая постоянно держит открытым файл (For Random) и записывает в него данные по 128 байт. Сегодня обнаружил в этом файле мусор. Предполагаю, что мусор туда попал при аварийной перезагрузке компа. Заметил, что часто сбой происходит при открытом сайте vk.com (слушаю музыку), у них там постоянно баги вылазят. Из любопытства просмотрел данные мусора - там оказался текстовый код из часто открытого у меня ДРУГОГО проекта VB, т.е. из оперативки или временных файлов VB(?). Интересно, но не суть важно. Запись в файл происходит приблизительно 3 раза в минуту. Есть ли смысл постоянно закрывать/открывать файл, чтобы уменьшить вероятность записи в данные мусора или же так больше вероятность нарваться на ошибку и стоп проги? Или лучше пожалеть винт (скорость проги не играет роли)?
|
Сообщ.
#2
,
|
|
|
Цитата BlackSun @ Есть ли смысл постоянно закрывать/открывать файл, чтобы уменьшить вероятность записи в данные мусора Да. Цитата BlackSun @ или же так больше вероятность нарваться на ошибку и стоп проги? Вообще-то ошибки принято обрабатывать, стараясь восстановить нормальную работу программы. Цитата BlackSun @ Или лучше пожалеть винт Дополнительной нагрузки на хард практически не будет - последние блоки файла стопроцентно лежат в файловом кэше ОС. |
Сообщ.
#3
,
|
|
|
Цитата BlackSun @ . Есть ли смысл постоянно закрывать/открывать файл, чтобы уменьшить вероятность записи в данные мусора или же так больше вероятность нарваться на ошибку и стоп проги? Или лучше пожалеть винт (скорость проги не играет роли)? Сбрасывай буфер файла после каждой записи. FlushFileBuffers или что-то типа того. |
Сообщ.
#4
,
|
|
|
Олег М
Да у него по 20 секунд между записями, а autoflush емнип 2 секунды... |
Сообщ.
#5
,
|
|
|
Цитата Akina @ так значит отсюда мусор попадает ко мне? таки надо делать сброс кеша сразу... последние блоки файла стопроцентно лежат в файловом кэше ОС Добавлено А если я буду писать единовременно по несколько записей, столько, чтобы заполнить весь этот буфер сразу - места мусору не будет. Какой у него размер? |
Сообщ.
#6
,
|
|
|
Нет, мусор из буфера записи дисковой подсистемы ОС. Запись же идёт блоками (ну считай кластерами), а итоговый размер пишется только при фиксации (закрытии) файла. Вот всё, что за реальным концом, и будет забито случайным хламом.
Цитата BlackSun @ Какой у него размер? Вот кто бы знал... в первом приближении - кратно размеру кластера накопителя, но ещё и делит нацело стандартный блок предчтения. Так что нечто бинарно-круглое от 4 кбайт до 2 Мбайт. А с учётом того, что буферов не один, а несколько независимо-последовательных (дисковая-файловая-приложения, и это на самом деле не всё), гадать вообще бессмысленно. Разумнее записывать не по 128, а поболе, довешивая этим 128 ещё контрольную сумму. Тогда по её невалидности инфо от хлама отличить - раз плюнуть. |
Сообщ.
#7
,
|
|
|
Можно довешивать CRC, но не хочется увеличивать объём данных. Хотелось понять принцип попадания мусора в данные. Если в буфер попадают данные с разных приложений, то там же должны быть какие-то разграничители? При сбое просто не записывается конец файла и файл остаётся с мусором в конце? Этот мусор тогда не должен превышать по размеру размер буфера ОС? Он имеет произвольную длину или кратную 2^n (вместе с моей записью в начале)? Или как?
|
Сообщ.
#8
,
|
|
|
Цитата BlackSun @ . Хотелось понять принцип попадания мусора в данные. Покажи код, как ты пишешь в файл. |
Сообщ.
#9
,
|
|
|
Цитата BlackSun @ Хотелось понять принцип попадания мусора в данные. Очень просто. Ты открываешь файл. Под него резервируется буфер в памяти. Само собой там изначально мусор. Ты что-то пишешь в файл, а на самом деле в этот буфер. Соответственно в той части буфера, куда байты не кладутся, остаётся мусор. При сбросе на диск ОС записывает весь блок (минимально - кластер). Соответственно в неиспользованной с твоей точки зрения части кластера пишется мусор. Пока файл открыт, ОС фиксирует только занятые файлом кластеры. Только при закрытии она в элементе каталога укажет точный размер в байтах, а пока формальный размер файла округлён вверх до кластера, причём эти сведения есть только в оперативке. Если происходит аварийное завершение, данные об актуальном размере записаны не будут. В то время как данные об использовании кластеров - уже записаны (они пишутся непосредственно в момент их корректировки). При следующем старте ОС обнаружит в журнале тома сведения, что файл не закрыт корректно. Сведения об истинном размере - утрачены. Соответственно будет установлен такой размер, чтобы гарантированно ничего не потерять - т.е. по максимуму. Итог - тот мусор, который находится в неиспользованной части кластера и считался бы несуществующим при штатном закрытии, стал легитимным содержимым файла. |
Сообщ.
#10
,
|
|
|
Цитата Akina @ Ты открываешь файл. Под него резервируется буфер в памяти. Само собой там изначально мусор. Не "само собой". Если речь идет о системном файловом кэше, то он работает по принципу файл-маппинга, при котором под буфер всегда выделяются предварительно обнуленные страницы памяти (из соображений безопасности\приватности\конфиденциальности). Соотв-но, если в винде размер кластера равен или кратен размеру страницы, то мусор в конце файла может возникнуть только в случае, когда ОС сначала выделяет новые кластеры для файла и изменяет его размер, и только потом записывает данные - тогда при сбое\прерывании записи в конце файла может остаться мусор от старых данных на диске. |
Сообщ.
#11
,
|
|
|
Цитата leo @ Если речь идет о системном файловом кэше Речь о всех буферах - формируемых VB, формируемых файловым кэшем ОС, а если есть - и других. Цитата leo @ только в случае, когда ОС сначала выделяет новые кластеры для файла и изменяет его размер, и только потом записывает данные Если изменяется цепь занимаемых файлом кластеров, Win всегда сначала пишет в тело файла, потом помечает кластеры как использованные, и только потом изменяет цепь кластеров файла. Такая последовательность действий минимизирует вероятность возникновения ошибки, а в случае её возникновения - минимизирует тяжесть повреждения. Когда пишется изменённый размер файла, точно не скажу, надо смотреть у Руссиновича, но в случае скоропостижной смерти ОС после автовосстановления при старте размеры открытых на момент падения ОС файлов или корректны, или увеличиваются до кратности кластеру, так что скорее всего размер меняется в самую последнюю очередь, уже после работы с занимаемыми кластерами.. |
Сообщ.
#12
,
|
|
|
У меня размер кластера на томе винта 16КБ и насколько я знаю, минимальная порция записи на диск 512 байт. Сбой случается редко, максимум 2-3 раза мог быть. Я обнаружил мусора в файле >300КБ, и, наверняка, в файле ещё что-то осталось (я отсеивал мусор по некорректным значениям полей UDT-записи). По размерам не сходится, если мусор пишется не более 1 кластера. Т.к. в мусоре был программный код другого проекта, буфера были явно не обнулены. В целом я придумал корректную запись в файл без CRC, но для меня картина записи мусора осталась не прояснённой до конца.
|
Сообщ.
#13
,
|
|
|
Akina
Как бы то ни было, а источником мусора в файле может являться только сам диск, когда в результате сбоя последний кластер записывается из памяти на диск не полностью и соотв-но в его хвосте остаются старые мусорные данные на диске. Ни с какими буферами в памяти это невозможно, особенно когда этот мусор представляет собой данные какого-то другого приложения (?!) |
Сообщ.
#14
,
|
|
|
Насколько я знаю, физически данные записываются секторами, тут просто не записались служебные данные после записи самих данных, а именно размер файла. Так что мусор идёт из памяти. С Akina согласен. Открытым же остался вопрос большого объёма самого мусора... Возможно, файлу устанавливается некий логический размер после сбоя, и добавляются ещё сектора/кластера с диска (и тут уж мусор идёт от этих кластеров).
Из сети: Цитата Каждая дорожка разбивается на фрагменты, называемые секторами (sectors) или блоками (blocks), так что все дорожки имеют равное число секторов, в которые можно максимально записать одно и то же число байтов. Сектор имеет фиксированный для конкретной системы размер, выражающийся степенью двойки. Чаще всего размер сектора составляет 512 байтов... Сектор наименьшая адресуемая единица обмена данными дискового устройства с оперативной памятью.... Операционная система при работе с диском использует, как правило, собственную единицу дискового пространства, называемую кластером (cluster). При создании файла место на диске ему выделяется кластерами. Например, если файл имеет размер 2560 байт, а размер кластера в файловой системе определен в 1024 байта, то файлу будет выделено на диске 3 кластера.... Добавлено Вспоминая характер мусора, я видел разные значки (как письмо на почте в не той кодировке) - похоже, это был мусор из памяти, а ещё видел код на VB - это могут быть временные файлы VB, которые были удалены с диска, но данные на секторах остались... |
Сообщ.
#15
,
|
|
|
Цитата BlackSun @ Так что мусор идёт из памяти Не может он идти из памяти, особенно данные из другого приложения. В противном случае, винду с ее защитой\изоляцией памяти между процессами можно выкинуть коту под хвост. "Нет, Шура. Только кража" (С). Т.е. мусор м.б. только с диска, когда при сбое установленный размер файла превышает размер реально записанных данных. PS: При создании и/или увеличении размера файла защита тоже действует, поэтому в штатном режиме 1) данные пишутся на диск всегда целыми кластерами с обнуленным хвостом последнего кластера, чтобы затереть старые данные на диске, 2) при записи с пропусками (установкой SetFilePointer за пределы текущего размера файла с последующим вызовом WriteFile или SetEndOfFile) в образовавшуюся дырку автоматически записываются нули. Цитата BlackSun @ Вспоминая характер мусора, я видел разные значки (как письмо на почте в не той кодировке) - похоже, это был мусор из памяти Это м.б. данные какого-то двоичного файла на диске - удаленного или урезанного |