Process FD Table vs Global Open File Table
In Linux, file management is handled through a three-tier hierarchy. Understanding the difference between the Process FD Table and the Global Open File Table is key to understanding how processes share files and offsets.
The Process File Descriptor Table (Local)
Every process has its own private table of file descriptors.
- Where it lives: Inside the
task_struct(the process control block), specifically infiles_struct. - What it is: A simple array of pointers.
- The Index: The array index is the File Descriptor (FD) integer (0, 1, 2, 3...).
- The Value: Each entry in the array points to an entry in the Global Open File Table.
The Global Open File Table (System-wide)
This table contains "Open File Descriptions." It represents the actual active session of an open file.
- Where it lives: In kernel memory, shared by all processes.
- What it is: A list of
struct fileobjects. - Key Data Stored Here:
- File Offset (
f_pos): Where the read/write head is currently located. - Status Flags: How the file was opened (e.g.,
O_APPEND,O_CREAT,O_RDONLY). - Reference Count: How many FDs across the whole system point to this specific session.
- VFS Pointers: Pointers to the
dentryandinode.
- File Offset (
The Comparison
| Feature | Process FD Table | Global Open File Table |
|---|---|---|
| Scope | Per-Process. Private to you. | System-wide. Shared by all. |
| Entries | Integers (0, 1, 2...). | struct file objects. |
| Stores Offset? | No. | Yes (the shared cursor). |
| Stores Flags? | No (except FD_CLOEXEC). |
Yes (Read/Write/Append). |
| Creation | When you open(), dup(), or pipe(). |
When a new open() session starts. |
How they work together (The 3-Tier View)
To truly understand this, we must include the Inode Table (the actual data on disk).
Scenario A: Two different processes open the same file
- Process A calls
open("log.txt"). - Process B calls
open("log.txt").
- FD Table: Each process gets its own FD (e.g., FD 3).
- Global Table: Each gets its own
struct file. - Inode Table: Both point to the same
inode. - Result: They have independent offsets. If Process A reads 10 bytes, Process B's cursor stays at 0.
Scenario B: A process forks (Shared Session)
- Process A calls
open("log.txt"). - Process A calls
fork(), creating Process B.
- FD Table: Process B gets a copy of Process A's table.
- Global Table: Both point to the exact same
struct file. - Inode Table: Points to the same
inode. - Result: They share the offset. If the parent reads 10 bytes, the child’s cursor also moves to 10. This is how shells manage standard output for piped commands.
Where is the offset stored?
The offset is stored in the Global Open File Table (specifically in the struct file object).
It is NOT stored in the Process FD Table. The Process FD Table is too "shallow" for that; its only job is to map an integer (like 3) to a pointer in the Global Open File Table.