LINUX.ORG.RU

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


0

1

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

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

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


Реализация fwrite() пишет сначала в локальный буфер, который сбрасывает на диск когда: 1) буфер закончился; 2) вызыван fclose(); 3) ну и прочие условия, которые нам не суть в рамках вопроса.

Поэтому после вызова fwrite() операционная система еще ничего не знает о том, что ты что-то «писал». (Сискол write() еще не вызван.)

geekless ★★
()
Последнее исправление: geekless (всего исправлений: 1)

Программы __могут__ буферизировать свой вывод. Это возможность, а не требование.

При этом поведение программы может меняться в зависимости от обстоятельств. Например, при выводе на консоль программа gawk выводит построчно, то есть, как только строка сформировалась, она сразу же выводится. А вот если перенаправить вывод в файл, то будет использоваться буферизация. Таким образом увеличится производительность (и весьма существенно) за счет меньшего количества системных вызовов write (2),

anarquista ★★★★★
()

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

речь наверное идёт об отложенной записи, файл на диске пишется не сразу, а только после заполнения буфера (если вы не используете sync(1) (см. man 1 sync), и если вы открыли файл без O_SYNC (см. man 2 open)). Посему файл растёт не по одному байту, а кусками, равными размеру буфера. Размер буфера неопределён и системозависим. Обычно он равен 64Кб (но НЕ обязательно!)

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

Программы __могут__ буферизировать свой вывод

и ввод тоже.

При этом поведение программы может меняться в зависимости от обстоятельств.

если оно нужно, то можно даже этим управлять. См. например man sed, --unbuffered опцию.

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

Это уже следующий уровень информированности. :)

А вот что реализация fwrite() буферизирует данные, программисту знать нужно с самого начала. (Хотя многие, похоже, не в курсе).

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

А вот что реализация fwrite() буферизирует данные, программисту знать нужно с самого начала. (Хотя многие, похоже, не в курсе).

ИМХО следует с самого начала понять, чем отличается файл от потока. И не мешать их вместе. Любой поток == файл, но не любой файл — поток.

Потоки обычно буферезерированы, но и файлы обычно тоже. Т.ч. в этом смысле разницы между fwrite(3) и write(2) никакой нет(первая работает с потоками, а вторая с файлами).

А вот ТСу надо курить до просветления man 3 fflush и связанные с ним топики. Если его вопрос в контексте потоков конечно. Если волнуют «просто файлы», курить надо man 2 sync и до кучи man 8 sync.

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

Неправильный ответ. Первая работает с объектами типа FILE, о которых операционная система ничего не знает, это внутренние структуры данных процесса. Вторая работает с хэндлами, которые есть непосредственный объект операционной системы.

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

Неправильный ответ. Первая работает с объектами типа FILE, о которых операционная система ничего не знает, это внутренние структуры данных процесса. Вторая работает с хэндлами, которые есть непосредственный объект операционной системы.

У нас просто разное понимание термина «операционная система». Я подразумеваю под этим не только ядро, но и всё остальное. Потоки, которые пишет fwrite(3) определены в любой POSIX совместимой операционной системе. В частности в любом GNU/Linux. Потому говорить «ОС ничего не знает о потоках» неправильно. И да, «хэндлы» — тоже неверный термин(ИМХО), ты наверное хотел сказать «дескриптор»? Ну «file descriptor», в оригинале. Именно с ними и работает write(2).

И кстати, я не нашёл упоминания в man'е о совместимости с POSIX про write(2), но вот про fwrite(3) — таки нашёл. Посему fwrite(3) более «правильная» функция, а write(2) это какой-то самопальный велосипед. (:

Также и потоки — stream это более совместимая и ваще Ъ реализация, нежели твоя нетрушная linux-only file descriptor (:

Такие дела...

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

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

Это 1 байт.

моя EXT4 умеет минимум 4096 байт писать, НЕ менее. Даже если её sync'ать после каждого байта. Ну а потоки у меня минимум по 64К пишутся(если их не fflush'ить конечно). Т.ч. ты заблуждаешься.

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

И кстати, я не нашёл упоминания в man'е о совместимости с POSIX про write(2)

Можешь приобщиться к истокам отсюда: http://pubs.opengroup.org/onlinepubs/009695399/functions/write.html

про write(2)

Потому что смотреть надо было write(3).

Потоки, которые пишет fwrite(3) определены в любой POSIX совместимой операционной системе.

strlen() тоже в любой POSIX-совместимой системе определено, и что? Это не делает строки объектом архитектуры операционной системы, такими как файлы, процессы и так далее.

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

Разница, в том, что это за кэширование, и где оно происходит.

Например, убей процесс, который не сбросил буфер FILE-а, и почувствуй разницу.

geekless ★★
()
Последнее исправление: geekless (всего исправлений: 1)
Ответ на: комментарий от emulek

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

Это 1 байт.

моя EXT4 умеет минимум 4096 байт писать

А еще она умеет читать. В отличие от тебя.

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

Можешь приобщиться к истокам отсюда: http://pubs.opengroup.org/onlinepubs/009695399/functions/write.html

очень познавательно, а зачем мне это?

Потому что смотреть надо было write(3).

Патрег такого мануала мне не дал. Следовательно его не существует. Это ересь и апокриф. (:

strlen() тоже в любой POSIX-совместимой системе определено, и что? Это не делает строки объектом архитектуры операционной системы, такими как файлы, процессы и так далее.

У нас просто разные точки зрения на одни и те же факты. С моей т.з. строки ASCIIZ являются объектом OS. Например имена файлов, и это не просто ASCIIZ, а ASCIIZ размером не более 256 байт.

Продолжим спорить о том, что _считать_ объектом, а что не считать? Я не против, но разъясни окружающим, что независимо от результата этой СО, ASCIIZ ну никак не изменятся. Как и потоки с файлами.

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

Во-вторых, какая разница, объект или нет, если кэширование происходит в обоих случаях

ну оно действительно по разному происходит. В struct FILE есть свой буфер (точнее даже два буфера, для чтения и для записи). А в том, на что указывает file descriptor тоже есть свой буфер(обычно). ТС, как я понял, спрашивал про второй буфер, а geekless рассказал нам про первый. Я так понимаю.

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

Например, убей процесс, который не сбросил буфер FILE-а, и почувствуй разницу.

а что будет?

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

в отличие от тебя, я умею читать первый пост целиком, а не только subject. Что-бы тебе было проще научится, я процитирую:

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

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

И если ты внимательно рассмотришь практически любой процесс записи в практически любое блочное устройство, ты осознаешь, что действительно, запись происходит не по одному байту.

emulek
()

Товарищи, а может не будем так сильно вдаваться в саму реализацию. В любом случаи на данный момент у меня сложилось следующие впечатление: минимальная единица объема информации для записи в файл может зависит от реализации данной функции в самом приложении/OC, а так же от файловой системы на которую будет производиться запись.

Но мне остается до сих пор не понятно почему в книжке стоит «1 или 4 Кбайт (KiB)», а не 1 байт. 1 килобайт!=1 байт.

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

минимальная единица объема информации для записи в файл может зависит от реализации данной функции в самом приложении/O

В POSIX, минимальная единица записи в файл ОС - 1 байт. Поверх этого могут быть любые объемы буферизации, снизу могут быть любые размеры блоков В/В, но ОС гарантирует, что ты можешь записать 1 байт.

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

В книжке приведены наиболее частые значения потокового буфера (допустим функция fprintf()) по умолчанию в разных системах. Как я понял, всё что хотел скзать автор, что если делается конвеер их всяких там:

tail | grep | sed > FILE

то вот этот файл скорее всего будет меняться в размере по 1 или 4 кБайта и это нужно знать.

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

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

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

Я думаю, чувствительность цветовосприятия является симптомом каких-то более глубоких проблем.

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

Но мне остается до сих пор не понятно почему в книжке стоит «1 или 4 Кбайт (KiB)», а не 1 байт. 1 килобайт!=1 байт.

в той части книжки речь идёт о блочном устройстве, оно так называется потому, что умеет писать только БЛОКАМИ. Так понятно? Если речь про FS(файловая система), то размер блока там 4К (для ext4), потому запись в файл на блочном устройстве ВСЕГДА по 4К и никогда не меньше. И ненулевой файл занимает ВСЕГДА 4К или больше(причём размер ВСЕГДА делится на 4К. Конечно сам размер может быть любым, но если он не делится на 4096, остаток забивается мусором или нулями).

А в древности иногда делали и в 1К, если диск маленький, и файлов _очень_ много. Сейчас не делают, просто потому, что диски большие стали. Ещё можно 512 и 2048, но сегодня ненужно. Было-бы круто 8192, но нельзя.

Кстати, размер страницы памяти тоже 4К(сейчас), потому ты не можешь выделить и кусок памяти менее 4К. Конечно ты можешь написать malloc(1), но выделится не один байт, а все 4096. Это такая _конструктивная_ особенность x86, он иначе не умеет (точнее умеет, но страницы ещё больше могут быть, но никак НЕ меньше)

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

В POSIX, минимальная единица записи в файл ОС - 1 байт. Поверх этого могут быть любые объемы буферизации, снизу могут быть любые размеры блоков В/В, но ОС гарантирует, что ты можешь записать 1 байт.

ну создай мне файл, про который du скажет, что он занимает 1 байт. У меня не получилось. Как не изворачивайся, получается 4К. Хотя размер файла да, может быть 1байт, но это не значит, что записывается именно один. А не 4096.

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

ЕМНИП он никогда не был равен 1 или 4К. Во всяком случае последние 15 лет он везде не меньше 32К. Т.ч. речь о каком-то другом «буфере».

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

Но мне остается до сих пор не понятно почему в книжке стоит «1 или 4 Кбайт (KiB)»

Потому что книжка — говно, вероятно.

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

tail | grep | sed > FILE то вот этот файл скорее всего будет меняться в размере по 1 или 4 кБайта и это нужно знать. Но программа, если захочет, может не буферизировать свои выходные данные и в файле будет сколько она запишет байт.

кстати неправильно ты понимаешь: эти команды в этом случае НЕ МОГУТ управлять буфером. Это не их буфер. И ессно никак не могут отключить буферизацию.

Однако, grep и sed могут сбрасывать буфер в конце каждой строки (см. --line-buffered для grep и --unbuffered для sed), это нужно помнить, что-бы не удивляться, когда top|grep '...'|sed '...' «не работает». Работает, но нужно упомянутые ключики применить.

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

кстати неправильно ты понимаешь: эти команды в этом случае НЕ МОГУТ управлять буфером. Это не их буфер. И ессно никак не могут отключить буферизацию.

...гиперактивный генератор бреда выходит на максимальную мощность.

Однако, grep и sed могут сбрасывать буфер в конце каждой строки

tailgunner не прав был выше: читать-то ты может и умеешь. И даже писать. А вот думать — нет.

geekless ★★
()
Последнее исправление: geekless (всего исправлений: 1)
Ответ на: комментарий от emulek

я думаю, ТСу будет понятно, кто здесь «говно». (:

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

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

...гиперактивный генератор бреда выходит на максимальную мощность.

Я не уверен, что это предел

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

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

т.е. обезьянке можно говном кидаться, а парнокопытным в пятницу нельзя? А пернатым?

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

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

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

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

Да нет, был когда то давно, он вобще определяется разрядностью процессора, это на Intel 4004 были 4 кбайт буфер, а сейчас с нормальными процессорами на 64 бита всё стало больше.

Не знаю зачем, но всё же покажу пример скрипта, может ТС разберётся в нём и поймёт о чём речь:

#!/bin/bash
for (( i=0; i<20; i++ )) ; do 
   for ((j=0; j<50; j++ )) ; do 
      echo "$j -- AAAAA" 
   done 
  { ls -l /tmp/TEST-sed 1>&2; } 
done | sed 'p' > /tmp/TEST-sed
и его вывод:
-rw-rw-r--. 1 kostya kostya 0 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 0 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 0 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 4096 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 4096 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 4096 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 8192 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 8192 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 8192 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 8192 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 12288 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 12288 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 12288 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 16384 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 16384 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 16384 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 16384 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 20480 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 20480 Aug 31 01:13 /tmp/TEST-sed
-rw-rw-r--. 1 kostya kostya 20480 Aug 31 01:13 /tmp/TEST-sed

Если sed'у дать опцию ″-u″, то размер этого файла будет изменяться не по 4 кБайт, а по 1180 байт.

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

эти команды в этом случае НЕ МОГУТ управлять буфером.

Однако, grep и sed могут сбрасывать буфер в конце каждой строки

То есть сброс буфера это не управление? А вобще, ″man setvbuf″.

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

т.е. обезьянке можно говном кидаться, а парнокопытным в пятницу нельзя? А пернатым?

Я ж не кидался не в кого, просто тихо мирно сру в комменты.

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