Skip to main content

Command Palette

Search for a command to run...

πŸ“‚ File Descriptors in Linux β€” The Complete Guide (Beginner to Advanced)

Updated
β€’6 min read
πŸ“‚ File Descriptors in Linux β€” The Complete Guide (Beginner to Advanced)

🧠 Introduction

Every time you:

  • open a file πŸ“„

  • make an API call 🌐

  • connect to a database πŸ—„οΈ

  • chat in an app πŸ’¬

πŸ‘‰ Your system is using file descriptors (FDs) behind the scenes.

They are simple, powerful, and critical for system performance and scalability.

This blog explains file descriptors in a way that:

  • beginners can understand easily

  • developers can apply in real-world systems


🍽️ What is a File Descriptor? (Canteen Analogy)

🧩 Simple Analogy β€” Canteen Token System

Imagine a college/office canteen πŸ›

  • Food items = files/resources

  • Canteen staff = Operating System (OS)

  • Token number = file descriptor


🎯 How it works:

Instead of saying:

β€œGive me one masala dosa with extra chutney from counter 2”

You simply say:

β€œToken #5”

πŸ‘‰ Staff already knows:

  • Token #5 β†’ your order

πŸ” Important detail (same as FDs!)

Once your order is served:

  • Token #5 becomes free

  • Next person may get token #5 again

πŸ‘‰ Just like file descriptors are reused


🧠 One-line definition:

A file descriptor is a small number used by the OS to identify and manage an open resource.


πŸ”’ Standard File Descriptors

Every Linux program starts with 3 default FDs:

FD   Name     Purpose
-------------------------
0    stdin    Input (keyboard)
1    stdout   Output (screen)
2    stderr   Error messages

πŸ“Š Diagram

Program starts:

   [Process]
      |
   ---------
   | 0 | β†’ Keyboard (Input)
   | 1 | β†’ Screen (Output)
   | 2 | β†’ Error Output
   ---------

βš™οΈ How File Descriptors Work

Step-by-step

int fd = open("file.txt", O_RDONLY);

🧠 What happens internally:

  1. OS receives a request

  2. Opens file

  3. Finds the lowest free number

  4. Assigns FD (e.g., 3)


πŸ“Š Diagram

Process FD Table:

FD   β†’   Resource
------------------------
0    β†’   Keyboard
1    β†’   Screen
2    β†’   Error screen
3    β†’   file.txt

πŸ” FD Allocation Rule (Very Important)

πŸ‘‰ OS always gives the lowest available FD


πŸ“Š Example

FDs in use: 0, 1, 2, 4, 5
Free FD: 3

Next open() β†’ FD = 3

❌ Not like this:

Highest FD = 5
Next FD β‰  6

🌐 Everything is a File in Linux

πŸ‘‰ File descriptors are not just for files

Resource Type        Example
--------------------------------
File                 file.txt
Socket               network connection
Pipe                 process communication
Device               keyboard, disk

πŸ”„ Lifecycle of a File Descriptor

OPEN β†’ USE β†’ CLOSE

πŸ“Š Diagram

open()      read/write      close()
  |             |              |
  v             v              v
 [FD] ------> [DATA] ------> [FREE]

πŸ’» Example

int fd = open("file.txt", O_RDONLY);
read(fd, buffer, size);
close(fd);

⚠️ File Descriptor Leak (Silent Killer)

🧠 What is it?

πŸ‘‰ Opening resources but not closing them


πŸ“‰ Example

while True:
    open("file.txt")

πŸ“Š Diagram

Iteration β†’ FD Count

1 β†’ FD 3
2 β†’ FD 4
3 β†’ FD 5
...
1024 β†’ πŸ’₯ Crash

❌ Error

Too many open files

🧨 Real-world impact

  • Server stops accepting users

  • Logs stop writing

  • Database connections fail

  • Random errors appear


πŸ§ͺ How to Check FDs in Linux

πŸ” List FDs

lsof -p <pid>

πŸ“Š Count FDs

ls /proc/<pid>/fd | wc -l

πŸ“Š FD Limits in Linux

Type        Meaning
--------------------------
Soft        Current usable limit
Hard        Maximum allowed

πŸ” Check limit

ulimit -n

πŸ“ˆ Typical values

  • Default β†’ 1024

  • Production β†’ 65535+


πŸ‘Ά File Descriptors & fork()

When a process creates a child:

πŸ‘‰ Child inherits all FDs


πŸ“Š Diagram

Before fork:

Parent
  |
 FD 3 β†’ file.txt

----------------------

After fork:

Parent            Child
  |                 |
 FD 3 β†’ file.txt   FD 3 β†’ file.txt

πŸ‘‰ Both share the same resource!


πŸ” FD Duplication

dup2(oldfd, newfd);

πŸ“Š Diagram

FD 1 β†’ Screen

dup2(3,1)

FD 1 β†’ file.txt

πŸ‘‰ Used in:

ls > output.txt

⚑ Real-World Use Cases

πŸ’¬ Chat Applications

1 user = 1 socket = 1 FD
1000 users = 1000 FDs

πŸ€– Backend APIs

1 request:
  β†’ socket FD
  β†’ DB FD
  β†’ log FD

πŸ‘‰ Multiple FDs per request


πŸŽ™οΈ Audio/Video Apps

1 user β†’ multiple streams β†’ multiple FDs

πŸ‘‰ Very high FD usage


🧠 Hidden Facts (Very Important)


πŸ” 1. FD numbers are reused

close(3)
open() β†’ FD 3 again

🧬 2. Child processes share FDs

  • Parent closes FD ❌

  • The child can still use it βœ…


⏳ 3. TIME_WAIT state

Sockets stay briefly after closing


πŸ”₯ 4. FD leak is slow

  • Works fine initially

  • fails later


🧠 5. One user β‰  one FD

1 user β†’ 3–5 FDs

βš™οΈ 6. High-performance systems rely on FDs

  • epoll

  • event loops


🧩 Best Practices


βœ… Always close resources

with open("file.txt") as f:
    data = f.read()

βœ… Use connection pooling

  • reuse DB connections

  • reduce FD usage


βœ… Monitor in production

  • track FD count

  • set alerts


βœ… Increase limits

ulimit -n 65535

🎯 Final Summary


🧠 Key Points

  • File descriptor = small number

  • Represents an open resource

  • Managed by OS

  • Reused efficiently


πŸ“Š Final Diagram

User Action
   |
   v
Open File / Socket
   |
   v
OS assigns FD (e.g., 3)
   |
   v
Program uses FD
   |
   v
Close FD β†’ freed

πŸš€ One-line takeaway

File descriptors are the invisible tokens that allow your program to communicate with files, networks, and the system.


πŸ’‘ Why it matters

Because it directly impacts:

  • scalability πŸ“ˆ

  • performance ⚑

  • system stability πŸ› οΈ


Good developers don’t just take tokensβ€”they make sure to return them.