Комментарии 24
статья должна называться не «всё о fsync», а «как вызвать fsync из php».
если учесть, что 99% кода php — веб-приложения, это требуется примерно никогда.
возможно, появление новых фич как раз подстегнёт развитие и использование php в других ипостасях кроме веба.
интересно, что за use case?
и зачем тут fsync?
fsync нужен чтобы быть уверенным, что в случае нештатной перезагрузки или отключения питания данные окажутся записанными в файл.
это понятно, непонятно зачем вам fsync.
для штатной записи в файл fsync не нужен.
и да, синхронная запись медленнее асинхронной, разница, в зависимости от аппаратной конфигурации, может быть быть на порядок и более.
пробовал много раз, правда не на php, всё работает как ожидается.
сейчас попробовал на php (без fsync), тоже работает как ожидается.
можете привести пример кода, на котором проблема воспроизводится?
<?php
$file = fopen('sample.txt', 'wb');
for ($j=0; ; $j++) {
for($i=0; $i<10000; $i++) {
$data = "$j:$i ";
if (fwrite($file, $data) !== false) {
$success = true;
}
}
usleep(100000);
}в соседней консоли
$ while true; do echo -n …; tail -c 20 sample.txt; echo; sleep 1; done
…997 13:9998 13:9999
…997 21:9998 21:9999
…997 30:9998 30:9999
…997 39:9998 39:9999
…997 48:9998 48:9999
…997 57:9998 57:9999
…997 66:9998 66:9999
…001 75:1002 75:1003
…997 83:9998 83:9999
…997 92:9998 92:9999
…7 101:9998 101:9999 как говорится, ЧЯДНТ?
не понимаю. приведите рабочий пример, посмотрим.
пока у меня устойчивое ощущение, что вы вообще не понимаете что делает fsync()
update: да, если файл лежит на удалённом сервере (nfs, smb), и клиент A пишет, а клиент B читает, то действительно клиент B может не «увидеть» записанное клиентом A пока тот не вызовет fsync(). но, вроде бы, мы не про этот случай, в рамках одной операционной системы процессы «видят» данные, записанные другими процессами в файлы, независимо от fsync().
Т.е., в этих примерах информация из файла читается в практическом смысле "сразу" после того, как она была туда записана.
да, именно так, как только один процесс записал что-то в связанный с файлом файловый дескриптор, другой при чтении из другого связанного с тем же файлом дескриптора получит актуальные данные.
но есть ещё один уровень абстракции — stream io (функции fread/fwrite), который работает уже в userspace и может буферизовывать запись.
то есть если процесс выполняет fwrite, то он может на самом деле не «сказать» операционной системе, что надо данные записать, а отложить их пока в свой внутренний буфер; естественно, что другие процессы ничего об этой записи не узнают.
именно для «борьбы» с этой буферизацией и придумана функция fflush.
теперь про fsync: вызов этой функции говорит ос, что надо записать изменённые данные на накопитель (и дождаться когда накопитель отрапортует, что запись завершена).
никакого отношения к stream io и к взаимодействию между процессами fsync не имеет.
другое дело, что, судя по документации, вызов fsync в php подразумевает неявный вызов fflush (бессмысленно сбрасывать на диск буферы операционной системы, не передав операционной системе перед этим изменения из буфера приложения).
P. S. stream io реализован в libc, «большой» linux обычно использует glibc, openwrt же uclibc или musl. это независимые реализации одних и тех же стандартов.
этим может объясняться различие в кэшировании, про которое вы писали.
но fflush должен работать одинаково.
$file = fopen('sample.txt', 'wb');
$data = "Hello\nthis is a test file!";
if (fwrite($file, $data) !== false) {
$success = true;
}[sheldon cooper mode ON]
будет проблематично делать fwrite если не создался файловый дескриптор..
все-таки желательно сначала проверять на его наличие:
if (!$file) { ... }
или
if (($file=fopen('sample.txt','wb')===false) { ... }
[sheldon cooper mode OFF]
Предупреждение четвёртое:
Даже если fsync успешно выполнился, верить ему полностью нельзя
https://habr.com/ru/post/472684/
Если вы в php-скриптах интенсивно работаете с файлами, то fsync и кеши ОС меньшая из проблем. Более серьезная проблема – разграничение доступа к файлам. Если только вы не используете php-daemon или т.п. механизмы, то каждый веб-запрос обрабатывается в своем worker-е, и кроме как flock-ми конкурентный доступ к файлам не разрулить.
Пример с логами вряд ли уместен в современных реалиях, поскольку более эффективно писать логи в централизованное хранилище, либо на каждый worker свой файл. В большинстве же случаев люди кладут на это болт и обходятся file_put_contents с флагами APPEND и LOCK_EX.
Если вы хотите, действительно обеспечить надежность файла в Linux, вы должны открыть дескриптор к каталогу содержащему файл и также применить для него
fsync().
Разве кроссплатформенность не должна гарантировать идентичного результата на разных платформах? Возможно, это было сделано ради производительности, но не думаю, что уместно жертвовать некоторым шансом записи, когда мы хотим гарантий, что она произойдет.
В языке C fsync() является частью стандартной библиотекиНе является.
Всё о fsync