4.2.33 · D3 · HinglishOperating Systems

Worked examplesDirectory structure — tree, DAG (hard links, symbolic links)

3,763 words17 min read↑ Read in English

4.2.33 · D3 · Coding › Operating Systems › Directory structure — tree, DAG (hard links, symbolic links)

Yeh page parent topic ki "theory ko kaam mein lagao" companion hai. Hum koi nayi theory introduce nahi karenge — balki hum har tarah ki situation enumerate karenge jo yeh topic throw kar sakta hai, phir har ek ke liye ek worked example solve karenge. Agar koi symbol dikhta hai (jaise link count ), woh parent mein define hua tha; hum use yahan re-anchor karte hain taaki tumhe kabhi scroll back na karna pade.


Scenario matrix

Is topic ke "inputs" ko teen knobs ki tarah socho: kaunsi tarah ka link (hard / soft), target ke saath kya hota hai (created / deleted / renamed), aur hum kaunsi boundary cross karte hain (same FS / other FS / ek directory). Interesting behaviour corners par rehta hai.

Cell Case class Kya special / degenerate hai Covered by
C1 Hard link, count upar phir neeche jaata hai, data bachta hai ordinary DAG case Example 1
C2 Hard link, count tak pahunchta hai degenerate: data actually free hota hai Example 2
C3 Open handle inode ko hold karta hai jab ho free rule ka limiting case Example 3
C4 Symlink ek live target vs ek deleted target par dangling / broken-link boundary Example 4
C5 Symlink target renamed (deleted nahi) text-vs-inode subtlety Example 5
C6 Cross-filesystem attempt hard fail hota hai, soft succeed karta hai Example 6
C7 Ek directory se link hard forbidden, soft allowed Example 7
C8 Symlink chain / loop (limiting ELOOP) traversal cycle, depth cap Example 8
C9 Real-world word problem (versioned release) applied reasoning Example 9
C10 Exam twist: ek mixed ls -li table count karo link counts cold padhna Example 10
Recall Do numbers jo tumhe har example mein track karne chahiye

Har example asal mein do counters ke baare mein hai. Link count kya hai? ::: directory entries (dentries) ki sankhya jo ek inode ko point karti hain (on-disk). Open-handle count kya hai? ::: open file descriptors ki sankhya jo processes inode par hold karte hain (in-memory). Exact free condition kya hai? ::: data freed .


Forecast: aage padhne se pehle final count aur kya c.txt kaam karega guess karo.

Neeche di gayi figure ko ek running bar chart ke roop mein track karti hai, script ki har line ke liye ek bar — dekho yeh kaise chadhta hai phir girta hai.

Figure — Directory structure — tree, DAG (hard links, symbolic links)
  1. Line (i): echo hi > a.txt ek brand-new inode (isse inode 42 kaho) create karta hai jisme ek directory entry a.txt hai. Yeh step kyun? Ek fresh file bilkul ek naam se start hoti hai, toh (pehla bar).
  2. Line (ii): ln a.txt b.txt usi inode 42 mein ek doosra dentry add karta hai. Yeh step kyun? Hard link usi inode ke liye ek aur naam hai — parent note ka rule hai , toh (bar chadhta hai).
  3. Line (iii): ln a.txt c.txt ek teesra dentry add karta hai. Yeh step kyun? Wohi rule phir: , toh (bar peak par).
  4. Line (iv): rm b.txt unlink call karta hai, jo naam b.txt hata deta hai aur decrement karta hai: , toh (bar girta hai, figure mein coral step). Yeh step kyun? rm ek naam remove karta hai, data nahi. Data tab tak bachta hai jab tak ho.

Final count . Kyunki hai, blocks alive hain, toh cat c.txt hi print karta hai. ✅

Verify: Surviving names count karo: a.txt, c.txt → exactly 2 dentries → . Match karta hai. c.txt abhi bhi inode 42 ko reference karta hai, toh read succeed karti hai.


Example 2 — Count zero hit karta hai, data free hota hai (cell C2, degenerate)

Forecast: kis rm par actual data marega?

  1. echo + ln ke baad: (inode 42 ke liye do naam). Yeh step kyun? Example 1 jaisi hi up-count logic.
  2. rm a.txt: . Data free nahi hua. Yeh step kyun? Free rule hai . Yahan hai, toh condition false hai.
  3. rm b.txt: . Ab aur . Yeh step kyun? ke dono halves true hain, toh kernel inode aur uske data blocks ko free list mein wapas kar deta hai.

Data sirf doosre rm par free hota hai, pehle par nahi.

Verify: Parent se reachability argument: "koi bhi path data tak pahunch sakta hai" "kam se kam ek dentry exist karta hai" . Dono removals ke baad, zero dentries exist karti hain, toh koi path nahi pahunch sakta — freeing sahi hai. . ✅


Example 3 — Open handle data ko par bhi alive rakhta hai (cell C3, limiting)

Forecast: kya rm space free karta hai jabki writer abhi bhi chal raha hai?

Figure do counters (lavender) aur (mint) ko timelines ke roop mein dikhati hai; data tab tak jeeta hai jab tak dono floor par na aa jaayein.

Figure — Directory structure — tree, DAG (hard links, symbolic links)
  1. rm log.txtunlink, lekin abhi bhi hai. Yeh step kyun? Aakhri (aur ek hi) naam chala gaya, toh dentry count zero ho jaata hai — lavender line girती hai.
  2. Writer abhi bhi ek open file descriptor hold karta hai → . Yeh step kyun? Poora free rule hai . Yahan hai, toh AND false hai — data free nahi hua (mint line abhi bhi high hai).
  3. Blocks tab release hote hain jab process fd close kare (ya exit ho jaaye), jisse ho jaata hai jabki pehle se hai. Yeh step kyun? Sirf jab dono references gayab hote hain tab AND true hota hai — dono lines floor par.

Verify: Free condition ka truth table:

free?
1 1 nahi
0 1 nahi ← yeh example, mid-write
1 0 nahi
0 0 haan ← close ke baad

Sirf aakhri row free karta hai. "Space reclaimed on close" se match karta hai. ✅


Forecast: kya symlink banana a.txt ka count change karta hai?

  1. ln -s a.txt s.txt ek naya inode 99 banata hai jiska data block sirf string "a.txt" store karta hai. Yeh step kyun? Ek symlink ek special file hai jo ek path string hold karti hai — "Hard counts, Soft doesn't." Toh a.txt ka count rehta hai. → answer (a) 1 hai.
  2. cat s.txt: kernel inode 99 padhta hai, dekhta hai type l hai, text "a.txt" padhta hai, a.txt par lookup restart karta hai, inode 42 dhundhta hai, hi print karta hai. → answer (b) hi hai. Yeh step kyun? Symlink resolve karna = "string padho, phir path lookup dobara chalao."
  3. rm a.txt: a.txt ka count ho jaata hai, hai, toh inode 42 free ho jaata hai. Ab s.txt abhi bhi "a.txt" store karta hai lekin woh naam gaya. Yeh step kyun? Symlink ne kabhi inode 42 ka count nahi chhoa, toh kuch bhi usse protect nahi kar raha tha.
  4. cat s.txt: "a.txt" ka lookup fail → No such file or directory — ek dangling link. → answer (c) yeh error hai.

Verify: Count par sign check: symlink creation ne target ke count mein add kiya (), jabki ek hard link ne add kiya hota. Dangling behaviour exactly "signpost points at nothing" picture hai. ✅


Forecast: rename delete nahi hai — kya signpost use dhundh lega?

  1. s literal text "report.txt" store karta hai. Yeh step kyun? Symlinks naam se resolve hote hain, inode number se nahi.
  2. mv directory entry ka naam report.txt se report_final.txt kar deta hai (wohi inode, bas ek naya naam). Yeh step kyun? Data aur inode untouched hain, lekin woh naam jo symlink dhundh raha hai ab exist nahi karta.
  3. s ka resolution "report.txt" dhundha karta hai → nahi mila → s ab dangling hai, chahe data bilkul sahi se ek naye naam ke under alive ho. Yeh step kyun? Yahi sharp difference hai hard link ke muqable: ek hard link inode ko point karta hai aur renames se koi fark nahi padta.

Verify: Contrast case — agar s ek hard link hota (ln report.txt s), toh woh inode ko point karta; mv sirf doosra naam change karta, toh cat s abhi bhi data print karta. Do links, do behaviours, ek rename — exactly "points at path vs points at inode" distinction. ✅


Example 6 — Cross-filesystem: hard fail hota hai, soft jeet jaata hai (cell C6)

Forecast: kaunsa Invalid cross-device link deta hai?

  1. (a) hard link fail hota hai EXDEV: Invalid cross-device link ke saath. Yeh step kyun? Hard link ek inode number store karta hai, aur inode numbers sirf ek filesystem ke andar meaningful hote hain. USB par inode 500 aur root par inode 500 alag files hain, toh ~ mein ek dentry legally ek USB inode ko naam nahi de sakta.
  2. (b) soft link succeed karta hai. Yeh step kyun? Ek symlink sirf ek path string "/mnt/usb/movie.mp4" store karta hai. Strings ko fark nahi padta ki woh kaun sa filesystem cross kar rahi hain; resolution bas us path se namei() dobara run karta hai.

Verify: Parent se constraint table — "cross-filesystem? Hard = No, Soft = Yes." Mechanism (inode number FS-local hai vs path universal hai) us table row ke peeche ka kyun hai. ✅


Forecast: OS inme se ek kyun refuse karega?

Figure dekho: left par, ek directory se uske ancestor ki taraf ek hard link ek loop band kar deta hai (dashed coral arrow) — black parent-arrow ko neeche follow karna aur coral arrow ko upar follow karna forever circle karega. Right par, butter-yellow symlink sirf /var/log mein ek text signpost hai; aisi signposts ka ek loop bhi kernel ke hop cap se cut off ho jaata hai.

  1. (a) directory ko hard link → refuse hua (EPERM/Operation not permitted users ke liye). Yeh step kyun? Jaise left panel dikhata hai, har directory mein pehle se . aur .. hain. Agar users ek directory ko ancestor mein hard-link kar sakein, toh tum directories mein ek cycle bana lete, aur ek recursive walk (find, du, recursive rm) forever loop karta. Saath hi link-count-as-reachability idea toot jaata hai. Toh kernel ise ban karta hai.
  2. (b) directory ko symlink → allowed. Yeh step kyun? Jaise right panel dikhata hai, symlink sirf text hai; kernel symlink-chain depth cap karta hai (e.g. ~40 hops ke baad ELOOP), toh yahan accidental loops bhi terminate hote hain.
Figure — Directory structure — tree, DAG (hard links, symbolic links)

Verify: Parent se DAG rule: hum directories mein cycles forbid karte hain taaki traversal terminate ho. Ek directory hard link ek cycle inject karega → banned. Ek symlink cycle depth cap se bounded hai → allowed. Consistent. ✅


Forecast: error predict karo aur yeh bounded kyun hai.

  1. a "b" store karta hai, b "a" store karta hai — signposts ka ek two-node cycle. Yeh step kyun? Har symlink naam se doosre ko resolve karta hai, toh lookup ping-pong karta hai a → b → a → b ….
  2. Agar unbounded hota, toh namei() kabhi terminate na hoti. Toh kernel hops count karta hai aur ek fixed limit (commonly 40) exceed hone par abort karta hai, ELOOP: Too many levels of symbolic links return karta hai. Yeh step kyun? Yahi limiting-value safeguard hai: hard links ke unlike (jo construction se kabhi cycle nahi bana sakte), symlinks bana sakte hain, toh depth cap safety net hai.

Verify: Resolver ko ek counter ki tarah model karo jo 0 se start hota hai, har hop par increment hota hai, par fail hota hai. Loop ke liye, counter chalta hai aur provably finite steps mein 40 cross karta hai → ELOOP ke saath terminate hota hai. Toh yeh hang nahi kar sakta. ✅


Example 9 — Real-world word problem: atomic release swap (cell C9)

Forecast: hard link ya symlink? Aur "instant" kyun lagta hai?

  1. current ko ek symlink banao: ln -s /srv/www/v1 current. Yeh step kyun? Tumhe ek directory ko point karna hai aur sambhavtah mounts ke across — sirf symlink directory ko point kar sakta hai (Example 7). Woh ek path bhi store karta hai, toh re-pointing ek single text change hai.
  2. Switch karne ke liye, symlink atomically replace karo: ln -sfn /srv/www/v2 current (-s ise symlink banata hai, -f existing current overwrite karta hai, -n ise old directory mein jaane se rokta hai). Equivalently, mv -T newlink current. Yeh step kyun? Symlink replace karna ek rename operation hai → server ya toh old target ya new target dekhta hai, kabhi half state nahi. Reversible: usi tarah se v1 par wapas point karo.
  3. Count bookkeeping: directories v1 aur v2 apne khud ke link counts unchanged rakhte hain (symlink add karta hai). Sirf ek inode — current symlink — ka stored text swap hota hai. Yeh step kyun? "Soft doesn't count," toh yeh poora scheme har real directory ke ko untouched chhod deta hai.

Verify: Impact tally: directory v1 count change , v2 count change , involved symlink inodes ki sankhya . Switch ke across total link-count deltas . "Symlink creation/repoint kabhi target count nahi badhata" se match karta hai. ✅


Example 10 — Exam twist: ls -li table cold padho (cell C10)

Forecast: inodes count karo, names nahi.

  1. Pehla column (inode number) aur permissions column ka pehla character (type) padho: - = regular file, l = symlink. Yeh step kyun? Distinct data = distinct inode numbers, distinct names nahi; aur type char batata hai ki inode real data hold karta hai ya sirf ek path string.
  2. Present inode numbers: 42, 99, 71. Inode 99 ek symlink hai (type l) jiska "data" sirf text a.txt hai (size 5 = "a.txt" ki length). Toh distinct regular-file data blobs inode 42 aur inode 71 hain → 2. → (a) answer 2 (plus 1 symlink inode, jo koi khud ka file data store nahi karta). Yeh step kyun? Hume symlink inode ko data blob ki tarah count nahi karna chahiye — woh ek signpost hai.
  3. a.txt aur b.txt dono inode 42 dikhate hain link count 2 ke saath → woh ek data blob share karne wale do hard links hain. → (b) a.txtb.txt data share karte hain. Yeh step kyun? Wohi inode number + count = do naam, ek inode.
  4. s.txt (inode 99, type l) symlink hai; woh text "a.txt" store karta hai. Usne inode 42 ke count mein contribute nahi kiya (jo hai = do hard links). Ab twist: naam a.txt delete karne par inode 42 ka data b.txt ke zariye alive rehta hai (count girta hai), lekin s.txt naam "a.txt" se resolve karta hai, jo ab gaya → s.txt dangling ho jaata hai. Toh symlink apne target ko protect nahi karta aur khud us naam ke delete/renames ke liye fragile hai. → (c) s.txt symlink hai; woh apne target ko protect nahi karta. Yeh step kyun? Symlinks naam se resolve hote hain (Example 5); "Soft doesn't count."

Verify: Cross-checks: listing mein inode-42 dentries ki sankhya → printed count 2 se match karta hai. Woh inodes jinka printed count 1 hai: s.txt(99) aur c.txt(71) → har naam exactly ek baar aata hai → match karta hai. Distinct regular-file data inodes , size . Sab consistent. ✅



Connections

  • Inodes and File Metadata
  • Reference Counting and Garbage Collection
  • Path Resolution and the namei() routine
  • Unix system calls — link, unlink, symlink, stat
  • Mount points and Virtual File System (VFS)
  • Graphs — Trees vs DAGs
  • File System Implementation — Block Allocation