Однако st->st_size
отражает фактический размер, но не размер файла диска, т.е. не включает буферизованные данные ядра?
Я не понимаю, что вы имеете в виду под данные в буфере ядра .Число в st->st_size
отражает размер файла в символах.Таким образом, если файл имеет 1000000
символов, число, которое st->st_size
будет 1000000
, с позициями символов от 0
до 999999
.
Существует два способа получить размер файла.в системах POSIX:
- сделать
off_t saved = lseek(fd, 0, SEEK_END);
, который возвращает фактическую позицию (вы должны сохранить ее, чтобы восстановить ее позже), и второй вызов off_t file_size = lseek(fd, saved, SEEK_SET);
, который возвращает к позиции, которой вы былидо, но возвращает в качестве числа позицию, в которой вы были до этого (это последняя позиция файла после последнего символа). Если вы отметите это, это будет соответствовать значению, возвращенному st->st_size
. - выполните
stat(2)
для файлового дескриптора, чтобы получить указанное выше значение.
Первый способ имеет некоторые недостатки, если у вас есть несколько потоков или процессов, совместно использующих дескриптор файла (с помощьюdup(2)
системный вызов или fork()
ed-процесс), если они делают вызовы read(2)
, write(2)
или lseek(2)
между вашими двумя lseek
вызовами, вы потеряете позицию, которая была в файлеранее и не сможет восстановиться доправильное место.Это странно и делает первый подход не рекомендуемым.
Наконец, нет никакой связи с буферизацией файла, выполняемой в ядре, с размером файла.Вы всегда получаете истинный размер файла на stat(2)
.Единственная вещь, которая может сбить вас с толку - это экономия в ядре, когда вы запускаете следующий фрагмент кода (но это прозрачно для вас, и вам не нужно это учитывать, кроме случаев, когда вы собираетесь скопировать файл в другой файл).место).Просто запустите эту крошечную программу:
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd = open("file", O_WRONLY | O_CREAT | O_TRUNC, 0666);
lseek(fd, 1000000, SEEK_SET);
char string[] = "Hello, world";
write(fd, string, sizeof string);
close(fd);
}
, в которой вы получите файл размером 1000013
байт, который использует только один или два блока дискового пространства.Это файл holed , в котором перед записанной строкой находится 1000000
ноль байтов, и система не выделяет для него блоки на диске.Только когда вы пишете эти блоки, система заполняет записанные вами части новыми блоками, чтобы сохранить ваши данные ... но до тех пор система покажет вам нулевые байты, но они нигде не хранятся.
$ ll file
-rw-r----- 1 lcu lcu 1000013 4 jul. 11:52 file
$ hd file
[file]:
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 :................
*
000f4240: 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 00 :Hello, world.
000f424d
$ _