LINUX.ORG.RU

Минимальная единица объема информации для записи в файл


0

1

Цитата из «Unix и Linux. Руководство системного администратора» (http://www.ozon.ru/context/detail/id/7607778/):

Однако следует иметь в виду, что программа, которая реализует запись данных в файл, может буферизировать свои выходные данные. Даже если строки будут добавляться регулярно (с точки зрения логики), они могут стать видимыми только фрагментами объемом 1 или 4 Кбайт (KiB).

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


Ответ на: комментарий от geekless

Книжку не читал, но в моей glibc 4 кБайт это размер буфера по умолчанию для вывода в файл. А 1024 байта (или около того) размер буфера при выводе stdout вывода на терминал (да, он line buffered, но для длинной строки будет несколько write() ).

Если читать название книги, то слово Unix, ИМХО, подразумевает множество ОС, вполне возможно, что где-то и для вывода в файл по умолчанию 1 кБайт.

mky ★★★★★
()
Ответ на: комментарий от mky

Мне кажется или пятница дает о себе знать. Обезьянки, совы и ослики никак не могут ужиться. Про кластер я знаю, и знаю что это минимальная логическая единица емкости на блочном устройстве. И если у меня будет файл в 1 байт то все равно на устройстве он занимает у меня 1 кластер=в большинстве случаев это 4096 байт (4 килобайт). Но речь не об этом, господа. Мне кажется emulek более всего близок к ответу, пока вы там фекалиями кидайтесь.

вывода в файл по умолчанию 1 кБайт

но означает ли что в файл не будет ничего записано пока «в буфере» (если это можно так назвать) не наберется этот 1 килобайт? Но выше опять таки говорилось про POSIX, и там речь идет об 1 байте.

hama
() автор топика
Ответ на: комментарий от hama

Пока не сделаешь sync или close, ничего туда не запишется, тебе это и пытаются сказать.

UVV ★★★★★
()
Ответ на: комментарий от hama

но означает ли что в файл не будет ничего записано пока «в буфере» (если это можно так назвать) не наберется этот 1 килобайт?

и да, и нет. Зависит от того, КАК открыт этот файл. Если ты его открыл с O_SYNC, то в файл запишется 1 этот байт и ещё 4095 байтов мусора. А если без O_SYNC, то будет ждать, пока наберётся 4096 байт.

Но выше опять таки говорилось про POSIX, и там речь идет об 1 байте.

ну ты всегда можешь записать один байт нужной информации. А ещё у тебя запишется 4095 байтов ненужной ерунды, если ты в Linux. В твоей книжке всё правильно написано. И со стандартом нет никаких противоречий: ты МОЖЕШЬ записать 1 байт. А про побочные эффекты там просто не сказано. Я и твоя книжка про это тебе рассказываем, а если не веришь — читай мануалы.

Да, про маздай я не в курсе.

emulek
()
Ответ на: комментарий от emulek

А ещё у тебя запишется 4095 байтов ненужной ерунды

помнится, была какая-то ФС, которая умела блоки между файлами делить. Или она уже давным-давно канула в Лету?

Anon
()
Ответ на: комментарий от Anon

помнится, была какая-то ФС, которая умела блоки между файлами делить. Или она уже давным-давно канула в Лету?

ЕМНИП это же райзерФС, только с хвостами!

notail By default, reiserfs stores small files and `file tails' directly into its tree. This confuses some utilities such as LILO(8). This option is used to disable packing of files into the tree.

emulek
()
Ответ на: комментарий от hama

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

но означает ли что в файл не будет ничего записано пока «в буфере» (если это можно так назвать)

Вы пытались разобраться с тем скриптом, который я привёл? Что он делает и почему даёт такой вывод?

то все равно на устройстве он занимает у меня 1 кластер=в большинстве случаев это 4096 байт (4 килобайт)

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

Есть прикладной уровень абстракции, страндартизированный POSIX'ом, там есть прямая запись в файл write() и потоковая fwrite(). Есть блочное устройство и драйвер файловой системе в ядре, который пишет блоками. Есть драйвер блочного устройства (НЖМД, допустим), который пишет секторами (или группами секторов). Есть микроконтроллер на жёстком диске, со своим дисковым кешем, который может писать данные своими блоками (на SSD нельзя переписать один байт или сектор, и на НЖМД давно аналогичная ситуация).

mky ★★★★★
()
Ответ на: комментарий от hama

буферов там несколько уровней.

1. буфер приложения (точнее, буфер libc) - fwrite пишет в него. Поэтому kill приложения, которое сделало fwrite и не сделало fflush, обычно приводит к неожиданным последствиям.

2. буферы VFS. Когда дело доходит до реального write (man 3 write), данные попадают в кэши VFS. Собственно, write может быть на любой размер - не только кратным размеру блока, и если write не выровнен по границе блока (а он весьма редко выровнен), делается read всех задействованных блоков, запись в кэш и пометка блоков кэша как «грязного». Но таки да, kill после write не приводит к потере данных. А отрубание питания - приводит.

Собственно запись на диск делает только cоответствующая ядерная нить.

P.S.: да, есть ещё O_DIRECT, который в принципе минует VFS, работая напрямую с ФС. Но у него write должен быть выровнен по 512 байтам, и это вообще отдельный случай.

no-dashi ★★★★★
()
Ответ на: комментарий от emulek

В исходниках glibc, реализующих потоковый вывод в файл. В файле libio/filedoalloc.c :

  size = _IO_BUFSIZ;
  if (fp->_fileno >= 0 && __builtin_expect (_IO_SYSSTAT (fp, &st), 0) >= 0)
    {
      if (S_ISCHR (st.st_mode))
        {
          /* Possibly a tty.  */
          if (
#ifdef DEV_TTY_P
              DEV_TTY_P (&st) ||
#endif
              isatty (fp->_fileno))
            fp->_flags |= _IO_LINE_BUF;
        }
#if _IO_HAVE_ST_BLKSIZE
      if (st.st_blksize > 0)
        size = st.st_blksize;
#endif
    }
  ALLOC_BUF (p, size, EOF);
  INTUSE(_IO_setb) (fp, p, p + size, 1);
  return 1;

ALLOC_BUF это и есть выделение буфера по умолчанию (потом он может быть переопределён через setvbuf) размером size. size в начале принимает значение _IO_BUFSIZ (равное 8 кБайт, определяется в файле libio.h), а потом переопределяется через размер блока файловой системы. st.st_blksize это поле структуры stat, возвращемой функцией fstat().

Для терминала st.st_blksize равен 1 кбайт, для большинства ext4fs равен 4 кбайт.

mky ★★★★★
()
Ответ на: комментарий от mky

полностью согласен, два уточнения:

райзер могут хранить данные двух файлов в одном блоке.

там, как я понял, ещё круче, прямо в дереве можно короткие файлы хранить. Т.е. типа как в инодах EXT4 (кстати в инодах EXT4 это отключено для простых файлов). И да, мегабакс ЕМНИП говорил, что лучше НЕ юзать эту фичу для райзера.

на SSD нельзя переписать один байт или сектор, и на НЖМД давно аналогичная ситуация

на НЖМД и на флопиках такое изначально. Как и на ленте. Ну и на флешках. На NAND так вообще конструктивно можно писать только по очень хитрым схемам, а не как хочется. Т.ч. по одному байту с такой сложной топологией и не получится. Только страницами, обычно тоже по 4К.

emulek
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.