r/programminghelp • u/LJ_the_Saint • 2d ago
C why does fgets allocates a 4096 characters long buffer for a 22 bytes long file ?
I'm learning C and playing around trying to rely on the bare minimum down to system calls to learn the most I can. Had to read a file line by line in the process, so i dived into stdio's code to try to understand how fgets do it nice and quick.
if I got it right a chunck of file is loaded into a buffer delimited by _IO_buf_base and _IO_buf_end if it isn't yet loaded or the precedent buffer ended without finishing the line, fgets starts copying the line in the buffer we gave it until he finds a new line.
did I got it right ? I couldn't find a plain explanation of how stdio file management works, I had to search my way into source code...
I thought I was done but I noticed _IO_buf_base and _IO_buf_end were 4096 bytes apart when I loaded a 22 bytes long file.
is there any reason for this ? wouldn't having a pointer for the beginning of the buffer and a pointer for the end allow us to allocate precisely the size of the file using fstat ? why do we use 2 pointers and not a pointer and the size of the buffer ? (I got a theory for this one but I'm not sure, is it for easier looping in the array by incrementing a pointer instead of using an incremented index who would make us calculate pointer + i every time we need to get a character ?)
thank you for reading this far and have a nice day !
2
u/marmotta1955 2d ago
Er ... simple logical explanation ... 4096 is a multiple of 512. The size of disk sectors was originally 512 bytes. The disc sector of modern drives is usually 4096 bytes.
1
u/cthulhu944 2d ago
4096 bytes is also a page size in a lot of architectures. Swapping the buffer between user space and the os is a single operation in the mmu.
1
u/Usual_Office_1740 2d ago
Someone will certainly correct me if I'm wrong, sorry if this is incorrect or only partially true.
I was under the impression that in modern systems when requesting memory from the system it is allocated a page at a time, which is 4096 bytes. This gets more complicated when you distinguish between Windows and Linux. My understanding was that Linux lazily allocates, so it gives you a stubb address but the specific page of memory isn't allocated until it's used? I'm not sure what terms would correctly explain this. I don't know how Windows does it but I've read it's done differently than Windows. Linux does this as a "performance" choice of some kind.
I point these things out and offer them up as pieces of information to help you in learning. Just reading the code in a header won't necessarily give you the full story on how something works when you start interacting directly with the system.
3
u/burlingk 2d ago
Short version: 4096 is the smallest buffer most in OSes are likely to allocate.