ฉันสามารถcat /dev
ฉันสามารถผมไม่สามารถls /dev
less /dev
เหตุใดจึงcat
ให้cat
ไดเรกทอรีนี้ แต่ไม่มีไดเรกทอรีอื่น ๆ
ฉันสามารถcat /dev
ฉันสามารถผมไม่สามารถls /dev
less /dev
เหตุใดจึงcat
ให้cat
ไดเรกทอรีนี้ แต่ไม่มีไดเรกทอรีอื่น ๆ
คำตอบ:
ในอดีต (มากถึง V7 UNIX หรือประมาณปี 1979) การread
เรียกระบบทำงานได้ทั้งไฟล์และไดเรกทอรี read
ในไดเรกทอรีจะส่งคืนโครงสร้างข้อมูลอย่างง่ายซึ่งโปรแกรมผู้ใช้จะแยกวิเคราะห์เพื่อรับรายการไดเรกทอรี อันที่จริงls
เครื่องมือV7 ทำสิ่งนี้อย่างแน่นอน - read
ในไดเรกทอรีให้แยกโครงสร้างข้อมูลผลลัพธ์ออกในรูปแบบรายการที่มีโครงสร้าง
ในฐานะที่เป็นระบบไฟล์ที่มีความซับซ้อนมากขึ้นนี้ "ง่าย" โครงสร้างข้อมูลมีความซับซ้อนมากขึ้นเพื่อจุดที่ฟังก์ชั่นห้องสมุดถูกเพิ่มเข้าไปในโปรแกรมความช่วยเหลือในการแยกวิเคราะห์การส่งออกของreaddir
read(directory)
ระบบและระบบไฟล์ที่แตกต่างกันอาจมีรูปแบบบนดิสก์ที่ต่างกันซึ่งมีความซับซ้อน
เมื่อซันแนะนำระบบไฟล์เครือข่าย (NFS) พวกเขาต้องการทำให้โครงสร้างไดเรกทอรีบนดิสก์เป็นนามธรรมอย่างสมบูรณ์ แทนที่จะread(directory)
ส่งคืนการแสดงไดเรกทอรีโดยไม่ขึ้นกับแพลตฟอร์ม แต่พวกเขาเพิ่มการเรียกระบบใหม่getdirents
- และถูกแบนread
ในไดเรกทอรีที่ติดตั้งบนเครือข่าย การเรียกใช้ระบบนี้ได้รับการปรับให้ทำงานกับไดเรกทอรีทั้งหมดในรสชาติ UNIX ที่หลากหลายอย่างรวดเร็วทำให้เป็นวิธีเริ่มต้นในการรับเนื้อหาของไดเรกทอรี (ประวัติย่อจากhttps://utcc.utoronto.ca/~cks/space/blog/unix/ReaddirHistory )
เพราะreaddir
ตอนนี้เป็นวิธีเริ่มต้นในการอ่านไดเรกทอรีread(directory)
โดยทั่วไปจะไม่ได้รับการดำเนินการ (กลับ - EISDIR) บน OSE ที่ทันสมัยที่สุด (QNX เป็นต้น) เป็นข้อยกเว้นที่น่าสังเกตซึ่งใช้readdir
เป็นread(directory)
) อย่างไรก็ตามด้วยการออกแบบ "ระบบไฟล์เสมือน" ในเมล็ดที่ทันสมัยที่สุดมันเป็นจริงขึ้นอยู่กับแต่ละระบบไฟล์ว่าการอ่านไดเรกทอรีใช้งานได้หรือไม่
และแน่นอนว่าใน macOS devfs
ระบบไฟล์ที่รองรับ/dev
mountpoint นั้นรองรับการอ่านได้จริง ( https://github.com/apple/darwin-xnu/blob/xnu-4570.1.46/bsd/miscfs/devfs_vnops.c#L629 ) :
static int
devfs_read(struct vnop_read_args *ap)
{
devnode_t * dn_p = VTODN(ap->a_vp);
switch (ap->a_vp->v_type) {
case VDIR: {
dn_p->dn_access = 1;
return VNOP_READDIR(ap->a_vp, ap->a_uio, 0, NULL, NULL, ap->a_context);
สิ่งนี้เรียกอย่างชัดเจนREADDIR
หากคุณพยายามอ่าน/dev
(การอ่านไฟล์ภายใต้/dev
ได้รับการจัดการโดยฟังก์ชั่นแยกต่างหาก - devfsspec_read
) ดังนั้นหากโปรแกรมเรียกใช้การread
เรียกระบบ/dev
มันจะประสบความสำเร็จและรับรายชื่อไดเรกทอรี!
นี่เป็นคุณสมบัติที่มีประสิทธิภาพที่ถือครองจากวันแรก ๆ ของ UNIX และยังไม่ได้สัมผัสในระยะเวลานาน ส่วนหนึ่งของฉันสงสัยว่าสิ่งนี้กำลังถูกเก็บไว้ด้วยเหตุผลด้านความเข้ากันได้ย้อนหลัง แต่ก็เป็นความจริงที่ว่าไม่มีใครใส่ใจเพียงพอที่จะลบคุณลักษณะเนื่องจากไม่ได้ทำร้ายอะไรจริงๆ
Lessเป็นโปรแกรมดูไฟล์ข้อความcatเป็นเครื่องมือสำหรับการคัดลอกข้อมูลโดยพลการ ดังนั้นให้ทำการตรวจสอบตัวเองน้อยลงเพื่อให้แน่ใจว่าคุณไม่ได้เปิดบางสิ่งที่จะมีข้อมูลจำนวนมากหรือทำงานผิดปกติ ในขณะที่แมวไม่มีการตรวจสอบดังกล่าวเลย - ถ้าเคอร์เนลให้คุณเปิดบางสิ่งบางอย่าง (แม้ว่ามันจะเป็นท่อหรืออุปกรณ์หรืออะไรก็ตามที่แย่กว่านั้น) แมวก็จะอ่านมัน
เหตุใด OS จึงอนุญาตให้catเปิดไดเรกทอรี ตามธรรมเนียมในระบบสไตล์ BSD ไดเรกทอรีทั้งหมดสามารถอ่านเป็นไฟล์และนั่นคือวิธีที่โปรแกรมจะแสดงรายการไดเรกทอรีในตอนแรก: เพียงแค่ตีความโครงสร้างไดเรนท์ที่เก็บไว้ในดิสก์
ต่อมาโครงสร้างบนดิสก์เหล่านั้นเริ่มแตกต่างจาก dirent ที่ใช้โดยเคอร์เนล: ซึ่งก่อนหน้านี้ไดเรกทอรีเป็นรายการเชิงเส้นต่อมาระบบแฟ้มเริ่มใช้ hashtables, B-trees และอื่น ๆ ดังนั้นการอ่านไดเรกทอรีโดยตรงไม่ได้ตรงไปตรงมาอีกต่อไปแล้วเคอร์เนลจึงเพิ่มฟังก์ชั่นเฉพาะสำหรับสิ่งนี้ (ฉันไม่แน่ใจว่านั่นเป็นเหตุผลหลักหรือหากพวกเขาถูกเพิ่มเข้ามาด้วยเหตุผลอื่น ๆ เช่นการแคช)
ระบบ BSD บางระบบยังคงอนุญาตให้คุณเปิดไดเรกทอรีทั้งหมดเพื่ออ่าน ฉันไม่รู้ว่าพวกเขาให้ข้อมูลดิบจากดิสก์หรือไม่ว่าพวกเขาจะส่งคืนรายการไดเรนต์ที่เลียนแบบแทนหรือไม่หรือให้พวกเขาให้คนขับระบบแฟ้มเป็นผู้ตัดสินใจ
ดังนั้น macOS อาจเป็นหนึ่งในระบบปฏิบัติการที่เคอร์เนลอนุญาตตราบเท่าที่ระบบไฟล์ให้ข้อมูล และความแตกต่างคือ/dev
อยู่ในdevfs
ระบบไฟล์ที่ถูกเขียนขึ้นเพื่ออนุญาตสิ่งนี้ในวันแรกขณะที่/
อยู่ในระบบไฟล์ APFS ที่ละเว้นคุณสมบัตินี้โดยไม่จำเป็นในยุคปัจจุบัน
ข้อจำกัดความรับผิดชอบ: ฉันยังไม่ได้ทำการวิจัยใด ๆ เกี่ยวกับ BSD หรือ macOS ฉันแค่ปีกมัน
/etc
จะใช้ดังนั้นฉันจึงใช้มันเป็นเกณฑ์มาตรฐานของฉัน
mount
หรือ/sbin/mount
เพื่อดูสิ่งที่กำลังติดตั้งอยู่ที่
/dev
เป็นระบบไฟล์เสมือนโดยใช้devfs
ไดรเวอร์โดย/etc
เป็นส่วนหนึ่งของ/
ระบบไฟล์โดยใช้apfs
ไดรเวอร์ ดังนั้นเหตุผลที่cat
จะอ่านข้อหนึ่งไม่ใช่เหตุผลอื่นคือความแตกต่างระหว่างapfs
และdevfs
ไดรเวอร์
neofetch
สำหรับข้อมูลของคุณ :) i.imgur.com/3azpnDt.png