ไดเร็กทอรีคืออะไรถ้าทุกอย่างบน Linux เป็นไฟล์


17

ผู้เริ่มต้นมักได้ยินวลี "ทุกอย่างเป็นไฟล์บน Linux / Unix" อย่างไรก็ตามสิ่งที่เป็นไดเรกทอรีแล้ว แตกต่างจากไฟล์อย่างไร

คำตอบ:


22

หมายเหตุ: เดิมนี้ถูกเขียนขึ้นเพื่อรองรับคำตอบของฉันสำหรับเหตุใดไดเรกทอรีปัจจุบันในlsคำสั่งที่ระบุว่าเชื่อมโยงกับตัวเอง แต่ฉันรู้สึกว่านี่เป็นหัวข้อที่ควรค่าแก่การยืนหยัดด้วยตนเองและด้วยเหตุนี้คำถาม & คำตอบนี้

ทำความเข้าใจกับระบบไฟล์และไฟล์ Unix / Linux: ทุกอย่างเป็นไอโหนด

โดยพื้นฐานแล้วไดเรกทอรีเป็นเพียงไฟล์พิเศษซึ่งมีรายการของรายการและ ID ของพวกเขา

ก่อนที่เราจะเริ่มการสนทนาสิ่งสำคัญคือการสร้างความแตกต่างระหว่างคำศัพท์สองสามคำและเข้าใจว่าไดเรกทอรีและไฟล์ใดเป็นตัวแทน คุณอาจเคยได้ยินคำว่า "Everything is a file" สำหรับ Unix / Linux สิ่งที่ผู้ใช้มักเข้าใจว่าเป็นไฟล์คือ: /etc/passwd- วัตถุที่มีพา ธ และชื่อ ในความเป็นจริงชื่อ (ไม่ว่าจะเป็นไดเรกทอรีหรือไฟล์หรืออะไรก็ตาม) เป็นเพียงสตริงข้อความ - คุณสมบัติของวัตถุจริง วัตถุนั้นถูกเรียกว่าinodeหรือ I-number และเก็บไว้ในดิสก์ในตาราง inode โปรแกรมที่เปิดยังมีตารางไอโหนด แต่นั่นไม่ใช่ความกังวลของเราในตอนนี้

แนวคิดของ Unix เกี่ยวกับไดเร็กตอรี่ก็เหมือนกับที่ Ken Thompson กล่าวไว้ในการสัมภาษณ์ปี 1989 :

... จากนั้นไฟล์บางไฟล์เป็นไดเรกทอรีที่เพิ่งมีชื่อและหมายเลข

การสังเกตที่น่าสนใจสามารถทำได้จากการพูดคุยของ Dennis Ritchie ในปี 1972ว่า

"... ไดเรกทอรีไม่เกินไฟล์ แต่เนื้อหาถูกควบคุมโดยระบบและเนื้อหาเป็นชื่อของไฟล์อื่น ๆ (บางครั้งไดเรกทอรีเรียกว่าแคตตาล็อกในระบบอื่น)"

... แต่ไม่มีการพูดถึงไอโหนดใด ๆ ในการพูดคุย อย่างไรก็ตามคู่มือ 1971เกี่ยวกับformat of directoriesรัฐ:

ความจริงที่ว่าไฟล์คือไดเร็กทอรีถูกระบุโดยบิตในคำแฟล็กของรายการ i - node

รายการไดเรกทอรีมีความยาว 10 ไบต์ คำแรกคือไอ - โหนดของไฟล์ที่แสดงโดยรายการถ้าไม่ใช่ -; ถ้าศูนย์รายการว่างเปล่า

ดังนั้นจึงมีตั้งแต่จุดเริ่มต้น

การจับคู่ไดเรกทอรีและ inode ยังอธิบายในโครงสร้างไดเรกทอรีที่จัดเก็บในระบบไฟล์ UNIX อย่างไร . ตัวไดเรกทอรีเองนั้นเป็นโครงสร้างข้อมูลโดยเฉพาะอย่างยิ่ง: รายการของวัตถุ (ไฟล์และหมายเลข inode) ที่ชี้ไปยังรายการเกี่ยวกับวัตถุเหล่านั้น (การอนุญาตประเภทเจ้าของขนาด ฯลฯ ) ดังนั้นแต่ละไดเรกทอรีมีหมายเลขไอโหนดของตัวเองแล้วชื่อไฟล์และหมายเลขไอโหนดของพวกเขา ที่มีชื่อเสียงมากที่สุดคือinode # 2 ซึ่งเป็น/ไดเรกทอรี (หมายเหตุ แต่ที่/devและ/runมีระบบไฟล์เสมือนดังนั้นตั้งแต่พวกเขาเป็นโฟลเดอร์รากระบบแฟ้มของพวกเขาพวกเขายังมี inode 2; เช่น inode นั้นมีความเป็นเอกลักษณ์ในระบบไฟล์ของตัวเอง แต่เมื่อติดตั้งระบบไฟล์หลายตัวคุณจะมี inode ที่ไม่ซ้ำกัน) แผนภาพที่ยืมมาจากคำถามที่เชื่อมโยงอาจอธิบายได้อย่างกระชับยิ่งขึ้น:

ไดเรกทอรี iNode บล็อก

ข้อมูลทั้งหมดที่เก็บไว้ในไอโหนดสามารถเข้าถึงได้ผ่านการstat()เรียกใช้ระบบตาม Linux man 7 inode:

แต่ละไฟล์มีไอโหนดที่มีข้อมูลเมตาเกี่ยวกับไฟล์ แอปพลิเคชันสามารถดึงข้อมูลเมตานี้โดยใช้ stat (2) (หรือการโทรที่เกี่ยวข้อง) ซึ่งส่งกลับโครงสร้าง stat หรือ statx (2) ซึ่งส่งกลับโครงสร้าง statx

เป็นไปได้หรือไม่ที่จะเข้าถึงไฟล์โดยรู้หมายเลขไอโหนดเท่านั้น ( ref1 , ref2 )? ในการใช้งาน Unix บางอย่างมันเป็นไปได้ แต่มันข้ามการตรวจสอบการอนุญาตและการเข้าถึงดังนั้นบน Linux ก็ยังไม่ได้ติดตั้งและคุณต้องสำรวจทรีของระบบไฟล์ (ผ่านfind <DIR> -inum 1234ตัวอย่าง) เพื่อรับชื่อไฟล์และ inode ที่เกี่ยวข้อง

ในระดับซอร์สโค้ดมันถูกกำหนดไว้ในซอร์สเคอร์เนลของ Linuxและยังได้รับการยอมรับจากระบบไฟล์จำนวนมากที่ทำงานบนระบบปฏิบัติการ Unix / Linux รวมถึงระบบไฟล์ ext3 และ ext4 (ค่าเริ่มต้นของ Ubuntu) สิ่งที่น่าสนใจ: มีข้อมูลเป็นเพียงบล็อกของข้อมูลลินุกซ์จริงมีฟังก์ชั่น inode_init_alwaysที่สามารถตรวจสอบว่า inode เป็นท่อ ( inode->i_pipe) ใช่ซ็อกเก็ตและท่อเป็นเทคนิคเช่นกันไฟล์ - ไฟล์ที่ไม่ระบุชื่อซึ่งอาจไม่มีชื่อไฟล์ในดิสก์ FIFOและซ็อกเก็ต Unix-Domainมีชื่อไฟล์ในระบบไฟล์

ข้อมูลอาจไม่ซ้ำกัน แต่หมายเลขไอโหนดไม่ซ้ำกัน ถ้าเรามีลิงก์ไปยัง foo ที่เรียกว่า foobar นั่นจะชี้ไปที่ inode 123 เช่นกัน ไอโหนดนี้มีข้อมูลว่าบล็อกพื้นที่ว่างในดิสก์นั้นถูกครอบครองโดยไอโหนดนั้น และในทางเทคนิคแล้วคุณจะสามารถ.เชื่อมโยงกับชื่อไฟล์ไดเรกทอรีได้อย่างไร ดีเกือบ: คุณไม่สามารถสร้าง hardlinks ไปยังไดเรกทอรีบน Linux ตัวเองแต่ filesystems สามารถอนุญาตให้เชื่อมโยงอย่างหนักเพื่อไดเรกทอรีในทางที่มีระเบียบวินัยมากซึ่งทำให้ข้อ จำกัด ของการมีเพียง.และ..การเชื่อมโยงอย่างหนัก

ต้นไม้ไดเรกทอรี

ระบบแฟ้มใช้โครงสร้างไดเรกทอรีเป็นหนึ่งในโครงสร้างข้อมูลแบบต้นไม้ โดยเฉพาะอย่างยิ่ง,

  • ext3 และ ext4 ใช้ HTree
  • xfs ใช้ B + Tree
  • zfs ใช้ต้นไม้แฮช

จุดสำคัญที่นี่คือไดเรกทอรีเองเป็นโหนดในต้นไม้และไดเรกทอรีย่อยเป็นโหนดลูกโดยที่เด็กแต่ละคนมีลิงค์กลับไปที่โหนดแม่ ดังนั้นสำหรับลิงก์ไดเรกทอรีจำนวน inode จึงเป็นขั้นต่ำ 2 สำหรับไดเรกทอรีที่ไม่มีการเชื่อมโยง (ลิงก์ไปยังชื่อไดเรกทอรี/home/example/และลิงก์ไปยังตนเอง/home/example/.) และแต่ละไดเรกทอรีย่อยเพิ่มเติมคือลิงก์ / โหนดเพิ่มเติม:

# new directory has link count of 2
$ stat --format=%h .
2
# Adding subdirectories increases link count
$ mkdir subdir1
$ stat --format=%h .
3
$ mkdir subdir2
$ stat --format=%h .
4
# Count of links for root
$ stat --format=%h /
25
# Count of subdirectories, minus .
$ find / -maxdepth 1 -type d | wc -l
24

แผนภาพที่พบในหน้าหลักสูตรของ Ian D. Allenแสดงไดอะแกรมที่ชัดเจนอย่างง่าย:

WRONG - names on things      RIGHT - names above things
=======================      ==========================

    R O O T            --->         [etc,bin,home]   <-- ROOT directory
   /   |   \                         /    |      \
etc   bin   home       --->  [passwd]  [ls,rm]  [abcd0001]
 |   /   \    \                 |      /    \       |
 |  ls   rm  abcd0001  --->     |  <data>  <data>  [.bashrc]
 |               |              |                   |
passwd       .bashrc   --->  <data>                <data>

สิ่งเดียวในไดอะแกรม RIGHT ที่ไม่ถูกต้องคือไฟล์นั้นไม่ได้รับการพิจารณาทางเทคนิคว่าอยู่ในแผนผังไดเรกทอรีเอง: การเพิ่มไฟล์ไม่มีผลต่อการนับลิงก์:

$ mkdir subdir2
$ stat --format=%h .
4
# Adding files doesn't make difference
$ cp /etc/passwd passwd.copy
$ stat --format=%h .
4

การเข้าถึงไดเรกทอรีราวกับว่าเป็นไฟล์

ในการอ้างLinus Torvalds :

จุดรวมของ "ทุกอย่างคือไฟล์" ไม่ใช่ว่าคุณมีชื่อไฟล์แบบสุ่ม (แน่นอนซ็อกเก็ตและท่อแสดงว่า "ไฟล์" และ "ชื่อไฟล์" ไม่มีส่วนเกี่ยวข้องกัน) แต่ความจริงที่ว่าคุณสามารถใช้งานร่วมกันได้ เครื่องมือในการทำงานกับสิ่งต่าง ๆ

พิจารณาว่าไดเรกทอรีเป็นเพียงกรณีพิเศษของไฟล์โดยธรรมชาติจะต้องมี API ที่ช่วยให้เราสามารถเปิด / อ่าน / เขียน / ปิดพวกเขาในลักษณะคล้ายกับไฟล์ปกติ

นั่นคือที่dirent.hมาของไลบรารี C ซึ่งกำหนดdirentโครงสร้างซึ่งคุณสามารถหาได้ในman 3 readdir :

   struct dirent {
       ino_t          d_ino;       /* Inode number */
       off_t          d_off;       /* Not an offset; see below */
       unsigned short d_reclen;    /* Length of this record */
       unsigned char  d_type;      /* Type of file; not supported
                                      by all filesystem types */
       char           d_name[256]; /* Null-terminated filename */
   };

ดังนั้นในรหัส C ของคุณคุณต้องกำหนดstruct dirent *entry_pและเมื่อเราเปิดไดเรกทอรีด้วยopendir()และเริ่มอ่านมันด้วยreaddir()เราจะเก็บแต่ละรายการไว้ในentry_pโครงสร้างนั้น แน่นอนว่าแต่ละรายการจะมีฟิลด์ที่กำหนดในเทมเพลตสำหรับdirentแสดงไว้ด้านบน

ตัวอย่างการปฏิบัติของวิธีการทำงานนี้สามารถพบได้ในคำตอบของฉันเกี่ยวกับวิธีการไฟล์รายชื่อและหมายเลขไอโหนดของพวกเขาในไดเรกทอรีการทำงานปัจจุบัน

โปรดทราบว่าคู่มือ POSIX ใน fdopenระบุว่า "[t] เขารายการไดเรกทอรีสำหรับจุดและจุดจุดเป็นตัวเลือก" และreaddir คู่มือรัฐ struct direntจะต้องมีd_nameและd_inoเขตข้อมูล

หมายเหตุเกี่ยวกับ "การเขียน" ไปยังไดเรกทอรี:การเขียนไปยังไดเรกทอรีกำลังแก้ไข "รายการ" ของรายการ ดังนั้นการสร้างหรือลบไฟล์จะเชื่อมโยงโดยตรงกับสิทธิ์ในการเขียนไดเรกทอรีและการเพิ่ม / ลบไฟล์เป็นการดำเนินการเขียนในไดเรกทอรีดังกล่าว


2
ฉันปฏิเสธที่จะยอมรับซ็อกเก็ตเป็นไฟล์;) "ทุกอย่างสามารถเข้าถึงได้เป็นไฟล์" จะแม่นยำยิ่งขึ้นหรือไม่
Rinzwind

@ Rinzwind วลี "ทุกอย่างเข้าถึงได้ในไฟล์" นั้นถูกต้อง ไฟล์ปกติมีopen()และread()ซ็อกเก็ตมีconnect()และread()เช่นกัน สิ่งที่จะแม่นยำมากกว่าคือ "ไฟล์" ถูกจัดระเบียบ "ข้อมูล" จริง ๆ ที่เก็บไว้ในดิสก์หรือหน่วยความจำและไฟล์บางไฟล์ไม่ระบุชื่อ - ไม่มีไฟล์ชื่อ โดยปกติผู้ใช้จะนึกถึงไฟล์ในรูปของไอคอนนั้นบนเดสก์ท็อป แต่นั่นไม่ใช่สิ่งเดียวที่มีอยู่ ดูเพิ่มเติมที่unix.stackexchange.com/a/116616/85039
Sergiy Kolodyazhnyy

คำถามก็คือถ้าไดเร็กทอรีเป็นไฟล์ และมันคือ. ซ็อกเก็ตอาจเป็นคำถามแยกต่างหากพร้อมกับท่อที่มีชื่อ FIFO
WinEunuuchs2Unix

ดีฉันได้รับคำตอบเกี่ยวกับท่อจนถึง: askubuntu.com/a/1074550/295286 บางที FIFOs จะเป็นถัดไป
Sergiy Kolodyazhnyy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.