What Is A File System
What Is A File System
What Is A File System
Types of Computer
File Systems and How they Work –
Explained with Examples
Reza Lavarian
It's a bit tricky to explain what exactly a file system is in
just one sentence.
That's why I decided to write an article about it. This post is meant to
be a high-level overview of file systems. But I'll sneak into the lower-
level concepts as well, as long as it doesn't get boring. :)
Whenever you download a file or access a web page over the Internet,
a file system is involved too.
ANYWAY? 🤯
This guide helps you understand file systems in many contexts. I'll
cover partitioning and booting too!
Why do we need a file system in the first place, you may ask?
Well, without a file system, the storage device would contain a big
chunk of data stored back to back, and the operating system wouldn't
be able to tell them apart.
The term file system takes its name from the old paper-based data
management systems, where we kept documents as files and put them
into directories.
Imagine a room with piles of papers scattered all over the place.
The reason is that we don't want to manage the whole storage space as
a single unit and for a single purpose.
It's just like how we partition our workspace, to separate (and isolate)
meeting rooms, conference rooms, and various teams.
For example, a basic Linux installation has three partitions: one
partition dedicated to the operating system, one for the users' files, and
an optional swap partition.
A swap partition works as the RAM extension when RAM runs out of
space.
Back to the office example, having a call center and a tech team in a
common area would harm both teams' productivity because each team
has its own requirements to be efficient.
In the next section, we'll dive deeper into partitioning and get to know
two concepts that will change your perspective on file systems:
system firmware and booting.
Are you ready?
Here's an explanation:
The first few screens you see before your Windows logo appears are
the output of your computer's firmware, verifying the health of
hardware components and the memory.
Once the system is powered on, the BIOS firmware starts and loads
the boot loader program (contained in MBR) onto memory. Once the
program is on the memory, the CPU begins executing it.
Having the boot loader and the partition table in a predefined location
like MBR enables BIOS to boot up the system without having to deal
with any file.
If you are curious about how the CPU executes the instructions
residing in the memory, you can read this beginner-friendly and
fun guide on how the CPU works.
The boot loader code in the MBR takes between 434 bytes to 446
bytes of the MBR space (out of 512b). Additionally, 64 bytes are
allocated to the partition table, which can contain information about a
maximum of four partitions.
446 bytes isn't big enough to accommodate too much code, though.
That said, sophisticated boot loaders like GRUB 2 on Linux split their
functionality into pieces or stages.
The smallest piece of code known as the first-stage boot loader is
stored in the MBR. It's usually a simple program, which doesn't
require much space.
The responsibility of the first-stage boot loader is to initiate the next
(and more complicated) stages of the booting process.
Immediately after the MBR, and before the first partition starts, there's
a small space, around 1MB, called the MBR gap.
MBR gap can be used to place another piece of the boot loader
program if needed.
A boot loader, such as GRUB 2, uses the MBR gap to store another
stage of its functionality. GRUB calls this the stage 1.5 boot loader,
which contains a file system driver.
Stage 1.5 enables the next stages of GRUB to understand the concept
of files, rather than loading raw instructions from the storage device
(like the first-stage boot loader).
The second stage boot loader, which is now capable of working with
files, can load the operating system's boot loader file to boot up the
respective operating system.
And if we magnify the MBR, its content would look like this:
limitations 😑.
The content of the MBR sector has no backup 😱, meaning if MBR gets
corrupted due to an unexpected reason, we'll have to find a way to
recycle that useless piece of hardware.
And every partition can be the size of the biggest storage device
available in the market - actually a lot more.
GPT is gradually replacing MBR, although MBR is still widely
supported across old PCs and new ones.
Many hardware and operating systems now support UEFI and use the
GPT scheme to partition storage devices.
In the GPT partitioning scheme, the first sector of the storage device is
reserved for compatibility reasons with BIOS-based systems. The
reason is some systems might still use a BIOS-based firmware but
have a GPT-partitioned storage device.
To check it out, you can try to change the directory to the ESP mount
point, like so:
cd /sys/firmware/efi
UEFI-based firmware assumes that the storage device is partitioned
with GPT and looks up the ESP in the GPT partition table.
Once the EFI partition is found, it looks for the configured boot loader
- usually, a file ending with .efi.
UEFI-based firmware gets the booting configuration from
NVRAM (a non-volatile RAM).
NVRAM contains the booting settings and paths to the operating
system boot loader files.
UEFI firmware can do a BIOS-style boot too (to boot the system from
an MBR disk) if configured accordingly.
You can use the parted command on Linux to see what partitioning
scheme is used for a storage device.
sudo parted -l
And the output would be something like this:
# dmidecode 3.2
Getting SMBIOS data from sysfs.
SMBIOS 2.4 present.
✅ Confirmed!
...
Formatting partitions
When partitioning is done, the partitions should be formatted.
Most operating systems allow you to format a partition based on a set
of file systems.
In the early days, Microsoft used FAT (FAT12, FAT16, and FAT32)
in the MS-DOS and Windows 9x family.
Starting from Windows NT 3.1, Microsoft developed New
Technology File System (NTFS), which had many advantages over
FAT32, such as supporting bigger files, allowing longer filenames,
data encryption, access management, journaling, and a lot more.
NTFS has been the default file system of the Window NT family
(2000, XP, Vista, 7, 10, etc.) ever since.
Apple has also developed and used various file systems over the years,
including
Hierarchical File System (HFS), HFS+, and recently Apple File
System (APFS).
Just like NTFS, APFS is a journaling file system and has been in use
since the launch of OS X High Sierra in 2017.
But how about file systems in Linux distributions?
The Extended File System (ext) family of file systems was created
for the Linux kernel - the core of the Linux operating system.
The first version of ext was released in 1991, but soon after, it was
replaced by the second extended file system (ext2) in 1993.
In the 2000s, the third extended filesystem (ext3) and fourth
extended filesystem (ext4) were developed for Linux with journaling
capability.
ext4 is now the default file system in many distributions of Linux,
including Debian and Ubuntu.
You can use the findmnt command on Linux to list your ext4-
formatted partitions:
findmnt -lo source,target,fstype,used -t ext4
The output would be something like:
When people talk about file systems, they refer to one of these layers
or all three as one unit.
The physical file system interacts with the storage hardware via
device drivers.
The next layer is the virtual file system or VFS.
The virtual file system provides a consistent view of various file
systems mounted on the same operating system.
So does this mean an operating system can use multiple file systems at
the same time?
This convenient layer between the user (you) and the underlying file
systems is provided by the VFS.
Instead, they use a unified API between programs and the VFS.
mkdir -p /media/usb
mount /dev/disk1s1 /media/usb
If the mount-point directory already contains files, those files will be
hidden for as long as the device is mounted.
Files metadata
File metadata is a data structure that contains data about a file, such
as:
File size
The inode also includes the address of the blocks allocated to the file;
On the other hand, where exactly it's located on the storage device
Having the inode number, the file system fetches the respective inode
from the inode table.
Once the inode is fetched, the file system starts to compose the file
from the data blocks registered in the inode.
You can use the df command with the -i parameter on Linux to see
the inodes (total, used, and free) in your partitions:
df -i
The output would look like this:
On most operating systems, you can grab metadata via the graphical
user interface.
For instance, when you right-click on a file on Mac OS, and select Get
Info (Properties in Windows), a window appears with information
about the file. This information is fetched from the respective file’s
metadata.
Space Management
Storage devices are divided into fixed-sized blocks called sectors.
A sector is the minimum storage unit on a storage device and is
between 512 bytes and 4096 bytes (Advanced Format).
However, file systems use a high-level concept as the storage unit,
called blocks.
Blocks are an abstraction over physical sectors; Each block usually
consists of multiple sectors.
Depending on the file size, the file system allocates one or more
blocks to each file.
We already know depending on the file size, one or more blocks are
allocated to a file.
One block is the minimum space that can be allocated to a file. This
means the remaining space of a partially-filled block cannot be used
by another file. This is the rule!
Since the size of the file isn't an integer multiple of blocks, the last
block might be partially used, and the remaining space would remain
unused - or would be filled with zeros.
So "size" is basically the actual file size, while "size on disk" is the
space it has occupied, even though it’s not using it all.
623 icon-link.svg
And to check the size on disk:
du -B 1 "icon-link.svg"
Which will result in:
4096 icon-link.svg
Based on the output, the allocated block is about 4kb, while the actual
file size is 623 bytes. This means each block size on this operating
system is 4kb.
These frequent changes in the storage medium leave many small gaps
(empty spaces) between files. These gaps are due to the same reason
file size and file size on disk are different. Some files won't fill up the
full block, and lots of space will be wasted. And over time there' won't
be enough consequent blocks to store new files.
This overhead applies to saving the file back to the disk as well.
The fragmentation might also occur when a file is written to the disk
for the first time, probably because the file is huge and not many
continuous blocks are left on the partition.
Not having to call the file system's block allocator on every write
request helps the file system make better choices with distributing the
available space. For instance, by placing large files apart from smaller
files.
Imagine that a small file is located between two large files. Now, if the
small file is deleted, it leaves a small space between the two files.
Spreading the files out in this manner leaves enough gaps between
data blocks, which helps the filesystem manage (and avoid)
fragmentation more easily.
Directories
A Directory (Folder in Windows) is a special file used as a logical
container to group files and directories within a file system.
On NTFS and Ext4, directories and files are treated the same way.
That said, directories are just files that have their own inode (on Ext4)
or MFT entry (on NTFS).
The files aren't literally contained within the directory, but they are
associated with the directory in a way that they appear as directory's
children at a higher level, such as in a file explorer program.
These entries are called directory entries. Directory entries contain
file names mapped to their inode/MFT entry.
In addition to the directory entries, there are two more entries. The
. entry, which points to the directory itself, and .., which points to the
parent directory of this directory.
On Linux, you can use the ls in a directory to see the directory entries
with their associated inode numbers:
ls -lai
And the output would be something like this:
...
<!DOCTYPE html>
<html>
<head>
<title>Products - Your Website</title>
</head>
<body>
<!--SOME CONTENT-->
<img src="img/logo.png">
<!--SOME MORE CONTENT-->
</body>
</html>
If the actual file name is Logo.png (note the capital L), you can still
see the image when you open your web page on your web browser (on
your Windows machine).
However, once you deploy it to a Linux server and view it live, you'll
see a broken image.
Why?
Because in Linux (ext4 file system) logo.png and Logo.png point to two
different files.
So keep that in mind when developing on Windows and deploying to
a Linux server.
Apart from these GUI tools, operating systems expose the file
system’s APIs via the command-line interfaces too, like Command
Prompt on Windows, and Terminal on Mac and Linux.
For instance, a file owner (on Linux or Mac) can configure a file to be
available to the public, like so:
Once you save the file, your word processor program sends a “write”
request to the file system’s API (the logical file system).
But what if the system crashes while the older version of the file is
being replaced with the new version?
In older file systems (like FAT32 or ext2) the data would be corrupted
because it was partially written to the disk.
This is less likely to happen with modern file systems as they use a
technique called journaling.
Journaling file systems record every operation that’s about to happen
in the physical layer but hasn’t happened yet.
The main purpose is to keep track of the changes that haven't yet been
committed to the file system physically.
The journal is a special allocation on the disk where each writing
attempt is first stored as a transaction.
Once the data is physically placed on the storage device, the change is
committed to the filesystem.
In case of a system failure, the file system will detect the incomplete
transaction and roll it back as if it never happened.
That said, the new content (that was being written) may still be lost,
but the existing data would remain intact.
Modern file systems such as NTFS, APFS, and ext4 (even ext3) use
journaling to avoid data corruption in case of system failure.
cd /music/country/highwayman
However, in a database file system, there’s no concept of paths and
directories.
We can't! 😁
But let's finish this post with the brief description I used at the
beginning:
By the way, if you like more comprehensive guides like this one, visit
my website decodingweb. dev and follow me on Twitter because,
besides freeCodeCamp, those are the channels I use to share my
everyday findings.