Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/11: Рейтинг темы: голосов - 11, средняя оценка - 4.73
мну довольно <(-__-)l
 Аватар для gGrn-7DA
217 / 206 / 15
Регистрация: 17.01.2010
Сообщений: 2,462

Как происходит синхронизация при записи в файл?

21.04.2013, 10:14. Показов 2348. Ответов 5
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
начало

Меня тоже вопрос мучал, но однажды (когда "потерял" курсовую) я смирился.

Вопрос вот в чем.

После исчезания окна копирования/перемщения, в тот момент когда вроде бы "уже все записано", фактически записаны далеко не все данные.
Они зависают на пути к устройству в ?системном? кеше, где ожидают своей очереди. И ожидать они там могут достаточно долго - несколько секунд.

В случае же отмонтирования устройства, выполняется очистка буфеорв и кешей устройства.
При этом данной задаче выдается повышенный приоритет(?), для скорейшего выполнения.

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

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

Так почему же при окончании копирования файлов не вызывается очистка кеша устройства? это напрягает.
Ведь всех на первом курсе учили вызывать метод flush перед закрытием дескриптора файла/потока?
Так почему? почему при "закрытии" файла, завершении приложения (или это только поток? - наврядли) данные все так же лежат в кеше???
_____________________________

Не по теме:

могу ошибаться в некоторых моментах

0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
21.04.2013, 10:14
Ответы с готовыми решениями:

Не происходит перенос на следующую строку при записи в файл
Добрый день. Подскажите, пожалуйста, почему при записи в файл у меня игнорируется знак &quot;\n&quot; в функции ToString и строка не...

При записи в бинарный файл происходит segmentation fault
Всем доброго времени суток. В узлах дерева находятся структуры pair. #include &lt;stdio.h&gt; #include &lt;iostream&gt; #include...

При бинарной записи в файл целых чисел вместо них происходит запись каких-то символов
Проблема эта находится в функциях save_binary (строки 57 и 214) class country { private: char * name; char * stolica; ...

5
deleted
177 / 50 / 5
Регистрация: 29.03.2013
Сообщений: 365
21.04.2013, 17:38
Цитата Сообщение от gGrn-7DA Посмотреть сообщение
После исчезания окна копирования/перемщения, в тот момент когда вроде бы "уже все записано", фактически записаны далеко не все данные.
Они зависают на пути к устройству в ?системном? кеше, где ожидают своей очереди. И ожидать они там могут достаточно долго - несколько секунд.
Когда вызывается sys_read, ядро первым делом просматривает страничный кэш. И если находит в нём требуемый чанк, то не трогая устройства передаёт его пользователю(cache-hit). А если не находит, то считывает его в страничный кэш и даёт копию пользователю(cache-miss).
Когда вызывается sys_write, ядро пишет в страничный кэш и помечает соответствующие страницы как "грязные". Такие страницы копируются на диск если:
Если нет свободной памяти, но высрать её откуда то надо. /proc/sys/vm/min_free_kbytes /proc/sys/vm/dirty_background_bytes
Если страница была грязной дольше чем /proc/sys/vm/dirty_expire_centisecs сотых секунд, то при следуещем пробуждении синхронизирующих потоков, она будет копирована на диск.
Если пользователь сделал системный вызов типа sync, umount... /proc/sys/vm/drop_caches этого кстати не делает
После копирования на устройство они разумеется остаются и в страничном кэше. И могут "зависать" там ооооочень долго

Цитата Сообщение от gGrn-7DA Посмотреть сообщение
1)Во время записи больших файлов таки указывается скорость записи, значит сбор кешей периодически выполняется
2)(наверно тут дейстует ограничение на размер кеша для одного процесса.потока.устройства?)
1) если под "сбором кешей" имеется ввиду частота вызова потоков синхронизирующих диски с кешем, то это /proc/sys/vm/dirty_writeback_centisecs. если = 0, то по таймеру они не вызываются вообще
2)ограничения на размер кеша для процесса нет. Кеш привязан к данным, а не процессам, запрашивающим эти данные. Чему лежать в кеше решает LRU/n алгоритм, в линуксе n=2, то есть ключевую роль играет время последнего доступа. Есть ограничение на объём грязных страниц процесса, который производит записи /proc/sys/vm/durty_bytes

Цитата Сообщение от gGrn-7DA Посмотреть сообщение
Так почему же при окончании копирования файлов не вызывается очистка кеша устройства? это напрягает.
"Конец копирование" это я так понимаю закрытие файла-копии. С чего бы кеш должен очищаться? Если под очисткой имелся ввиду процесс синхронизации страничного кеша и дисков, то примерно такого поведения можно добиться, смонтировав диск с параметром flush. А просто так при закрытии файла ничего не синхронизируется. Некоторые неразумные программисты к примеру любят закрыть и открыть файл, чтобы переместиться таким образом на начало. Так что нет нужды в этом

Цитата Сообщение от gGrn-7DA Посмотреть сообщение
Ведь всех на первом курсе учили вызывать метод flush перед закрытием дескриптора файла/потока?
fflush(FILE) или любые его аналоги в iostream из C++ не синхронизируют содержимое страничного кеша с диском. Пример
C
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
 
int main ()
{
  FILE * pFile;
  char buffer[] = { 'x' , 'y' , 'z' };
  pFile = fopen ( "myfile.bin" , "wb" );
  for (int i = 0; i < 10; i++) {
    fwrite (buffer , 1 , sizeof(buffer) , pFile );
  }
  fclose (pFile);
  return 0;
}
Bash
1
2
3
4
5
6
7
8
strace ./a.out
 
open("myfile.bin", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f76a8e98000
write(3, "xyzxyzxyzxyzxyzxyzxyzxyzxyzxyz", 30) = 30
close(3)                                = 0
munmap(0x7f76a8e98000, 4096)            = 0
То есть fwrite при первом вызове выделил страницу памяти под буффер, а на всех последующих вызовах просто писал в него и в конце одним write'ом всё это дело записал. А fflush вообще ничего не сделал, не вызвал ни sync ни fsync. То что записано write'ом, будет записано в кеш, а когда эти данные попадут на диск, описано в начале сообщения. Это может случиться очень нескоро. Но если смонтирована фс с опцией sync тогда сразу данные попадают на диск

А если fflush поставить так
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
int main ()
{
  FILE * pFile;
  char buffer[] = { 'x' , 'y' , 'z' };
  pFile = fopen ( "myfile.bin" , "wb" );
  for (int i = 0; i < 10; i++) {
    fwrite (buffer , 1 , sizeof(buffer) , pFile );
    fflush(pFile);
  }
  
  fclose (pFile);
  return 0;
}
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
open("myfile.bin", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6ce219b000
write(3, "xyz", 3)                      = 3
write(3, "xyz", 3)                      = 3
write(3, "xyz", 3)                      = 3
write(3, "xyz", 3)                      = 3
write(3, "xyz", 3)                      = 3
write(3, "xyz", 3)                      = 3
write(3, "xyz", 3)                      = 3
write(3, "xyz", 3)                      = 3
write(3, "xyz", 3)                      = 3
write(3, "xyz", 3)                      = 3
close(3)                                = 0
munmap(0x7f6ce219b000, 4096)            = 0
то есть fflush всего лишь "сбрасывает кеш" сишной библиотеки, которая никакого отношения к страничному кешу не имеет. Данные на диск реально не записываются. Это делает fsync

Цитата Сообщение от gGrn-7DA Посмотреть сообщение
Так почему? почему при "закрытии" файла, завершении приложения (или это только поток? - наврядли) данные все так же лежат в кеше???
Данные лежат в кеше пока они кому то нужны. "Нужность" определяется LRU/2 алгоритмом, а закрытия каких то файлов или завершение каких то приложений на это особо не влияет. Они и после записи на диск ещё долго могут лежать в кеше
1
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
22.04.2013, 06:28
Цитата Сообщение от _1_ Посмотреть сообщение
То есть fwrite при первом вызове выделил страницу памяти под буффер, а на всех последующих вызовах просто писал в него и в конце одним write'ом всё это дело записал.
не, буфер находится в структуре файлового потока, с которой связан открытый файл
Цитата Сообщение от _1_ Посмотреть сообщение
C
1
FILE * pFile;
потом fclose() вызывает fflush()
0
deleted
177 / 50 / 5
Регистрация: 29.03.2013
Сообщений: 365
22.04.2013, 08:45
Цитата Сообщение от _1_ Посмотреть сообщение
То есть fwrite при первом вызове выделил страницу памяти под буффер, а на всех последующих вызовах просто писал в него и в конце одним write'ом всё это дело записал.
Цитата Сообщение от accept Посмотреть сообщение
не, буфер находится в структуре файлового потока, с которой связан открытый файл
К чему относится "не"? Где здесь противоречие? Я ничего и не говорил про местонахождение буффера. Но выделил его именно fwrite именно mmap'ом. А где указатель на буффер хранится для данного примера не более чем маловажная деталь реализации

Цитата Сообщение от accept Посмотреть сообщение
потом fclose() вызывает fflush()
И поэтому из моего первого примера fflush перед fclose исчез? Спасибо конечно за перенос сообщения и добавления тегов, когда я забываю добавлять их сам. Но внутреннее содержание попрошу не редактировать. Я взял пример с http://www.cplusplus.com/reference/cstdio/fwrite/ добавил цикл и вставил fflush перед fclose, чтобы всем было очевидно что он вызывается, а не только задротам читающим мануалы. Но вроде я сейчас смотрю, а он куда то исчез. Или может быть меня память подводит, и я сам забыл его написать? Чудеса какие то вообщем происходят
0
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
22.04.2013, 10:26
Цитата Сообщение от _1_ Посмотреть сообщение
Но выделил его именно fwrite именно mmap'ом.
а, ну да, проверил: если буфер не выделен, то выделяет его первая записывающая функция
я думал, его выделяет fopen()
(вообще, от реализации зависит, когда он выделяется)

Цитата Сообщение от _1_ Посмотреть сообщение
И поэтому из моего первого примера fflush перед fclose исчез?
его там и не было

Цитата Сообщение от _1_ Посмотреть сообщение
добавил цикл и вставил fflush перед fclose
не, ты что-то перепутал
код не редактировался вообще

fflush() ты вставлял только во втором примере

Цитата Сообщение от _1_ Посмотреть сообщение
Или может быть меня память подводит, и я сам забыл его написать?
я думаю, ты его хотел написать, и не написал

вот из этой фразы следует
Цитата Сообщение от _1_ Посмотреть сообщение
А fflush вообще ничего не сделал, не вызвал ни sync ни fsync.
0
deleted
177 / 50 / 5
Регистрация: 29.03.2013
Сообщений: 365
22.04.2013, 18:43
ну ладно тогда
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
22.04.2013, 18:43
Помогаю со студенческими работами здесь

Ini-файл: чтение происходит без проблем, но запись в файл не происходит, почему?
Пытаюсь научиться работать с ini файлам, чтение происходит без проблем но запись в файл не происходит, пишу на win7? почему та, всё же...

Как перенести строку при записи в файл при использовании BufferedWriter?
Записываю в файл строковые данные, но никак не получается перенести строку, все пишется сплошняком. BufferedWriter bw = new...

При запуске gdm и щелчку по записи происходит задержка
Debian 7 Wheezy В общем, проблема такова. При запуске подвисает даже gdm - по щелчку на учетной записи секунды 3 думает и только потом...

Не происходит вход пользователя в ИБ по учетной записи при смене пароля
Здравствуйте. В собственной конфигурации 1С 8.3 ставлю для пользователей аутентификацию 1С Предприятия и выбираю доменное имя пользователя....

Почему происходит округление при записи вещественных данных в таблицу?
Не могу понять в чем дело. Я записываю числовые данные в поле &quot;SUMRT&quot; (описано поле как NUMBER(8,2 )) в таблицу на оракле.Данные...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru