Linux แยกความแตกต่างระหว่างไฟล์จริงและไม่อยู่ (เช่น: อุปกรณ์) อย่างไร


28

นี่เป็นคำถามระดับต่ำและฉันเข้าใจว่าอาจไม่ใช่สถานที่ที่ดีที่สุดสำหรับการถาม แต่ดูเหมือนจะเหมาะสมกว่าเว็บไซต์ SE อื่น ๆ ดังนั้นที่นี่จะไป

ฉันรู้ว่าบนระบบไฟล์ Linux บางไฟล์มีอยู่จริงตัวอย่างเช่น: /usr/bin/bashเป็นไฟล์ที่มีอยู่จริง อย่างไรก็ตาม (เท่าที่ผมเข้าใจมัน) บางคนก็ไม่ได้มีอยู่จริงเช่นนี้และมีมากขึ้นเสมือนไฟล์เช่น: /dev/sda, /proc/cpuinfoฯลฯ คำถามของฉัน (พวกเขาเป็นสอง แต่เกี่ยวข้องอย่างใกล้ชิดเกินไปที่จะเป็นคำถามที่แยกต่างหาก):

  • เคอร์เนลของ Linux ทำงานอย่างไรว่าไฟล์เหล่านี้เป็นของจริง (และอ่านจากดิสก์) หรือไม่เมื่อมีการใช้คำสั่ง read (หรือเช่นนั้น)?
  • หากไฟล์ไม่จริง: เป็นตัวอย่างที่อ่านจาก/dev/randomจะกลับข้อมูลแบบสุ่มและอ่านจากจะกลับมา/dev/null EOFมันทำงานอย่างไรข้อมูลที่จะอ่านจากไฟล์เสมือนนี้ (และดังนั้นสิ่งที่จะทำเมื่อ / ถ้าข้อมูลที่เขียนไปยังไฟล์เสมือนด้วย) - มีแผนที่บางชนิดที่มีพอยน์เตอร์เพื่อแยกคำสั่งอ่าน / เขียนที่เหมาะสมสำหรับแต่ละไฟล์ หรือแม้แต่สำหรับไดเรกทอรีเสมือนเอง ดังนั้นรายการสำหรับก็สามารถกลับ/dev/nullEOF

1
เมื่อไฟล์ถูกสร้างขึ้นเคอร์เนลจะบันทึกประเภทของมัน ไฟล์ดิสก์ปกติจะได้รับการปฏิบัติแตกต่างจาก symlinks อุปกรณ์บล็อกอุปกรณ์ตัวอักษรไดเรกทอรีซ็อกเก็ต FIFO ฯลฯ มันเป็นหน้าที่ของเคอร์เนลที่ต้องรู้
Jonathan Leffler

ดูผู้ชาย pge สำหรับ mknod
Jasen

นี่เป็นการถามแบบ "สวิตช์ไฟจะรู้ได้อย่างไรว่าไฟเปิดอยู่" สวิตช์ไฟนั้นทำหน้าที่ตัดสินว่าจะเปิดไฟหรือไม่
การแข่งขัน Lightness กับโมนิก้า

คำตอบ:


25

ดังนั้นโดยทั่วไปมีสองประเภทที่แตกต่างกันของสิ่งที่นี่:

  1. ระบบไฟล์ปกติซึ่งเก็บไฟล์ในไดเรกทอรีที่มีข้อมูลและเมตาดาต้าในลักษณะที่คุ้นเคย (รวมถึงซอฟต์ลิงค์ฮาร์ดลิงก์และอื่น ๆ ) สิ่งเหล่านี้มักจะถูกสำรองข้อมูลโดยอุปกรณ์บล็อกสำหรับหน่วยเก็บข้อมูลแบบถาวร (tmpfs อาศัยอยู่ใน RAM เท่านั้น แต่จะแตกต่างจากระบบไฟล์ทั่วไป) ความหมายของสิ่งเหล่านี้คุ้นเคย อ่านเขียนเปลี่ยนชื่อและอื่น ๆ ทำงานตามที่คุณคาดหวัง
  2. ระบบไฟล์เสมือนชนิดต่าง ๆ /procและ/sysเป็นตัวอย่างที่นี่เช่นเดียวกับ FUSE ระบบไฟล์ที่กำหนดเองชอบหรือsshfs ifuseมีความหลากหลายมากขึ้นในสิ่งเหล่านี้เพราะจริงๆแล้วพวกเขาเพียงอ้างถึงระบบไฟล์ที่มีความหมายที่อยู่ในความรู้สึก 'กำหนดเอง' ดังนั้นเมื่อคุณอ่านจากไฟล์ข้างใต้/procคุณจะไม่สามารถเข้าถึงข้อมูลบางส่วนที่ถูกเก็บไว้โดยสิ่งอื่นที่เขียนไว้ก่อนหน้านี้เช่นเดียวกับในระบบไฟล์ปกติ คุณกำลังโทรเข้าเคอร์เนลเป็นหลักโดยขอข้อมูลบางอย่างที่สร้างขึ้นทันที และรหัสนี้สามารถทำอะไรก็ได้ที่มันชอบเพราะมันเป็นแค่ฟังก์ชั่นบางตัวที่ใช้readความหมาย ดังนั้นคุณมีพฤติกรรมแปลก ๆ ของไฟล์ที่อยู่ใต้/procตัวอย่างเช่นการแสร้งเป็น symlink เมื่อพวกเขาไม่ได้ '

ที่สำคัญคือที่/devจริงแล้วปกติหนึ่งในประเภทแรก เป็นเรื่องปกติในการแจกแจงแบบสมัยใหม่ที่จะมี/devบางอย่างเหมือน tmpfs แต่ในระบบเก่ามันเป็นเรื่องปกติที่จะเป็นไดเรกทอรีธรรมดาบนดิสก์โดยไม่มีคุณลักษณะพิเศษใด ๆ กุญแจสำคัญคือไฟล์ที่อยู่ภายใต้/devโหนดอุปกรณ์ประเภทของไฟล์พิเศษที่คล้ายกับ FIFOs หรือซ็อกเก็ต Unix; โหนดอุปกรณ์มีหมายเลขหลักและรองและการอ่านหรือเขียนกำลังเรียกไปยังเคอร์เนลไดรเวอร์เหมือนกับการอ่านหรือเขียน FIFO กำลังเรียกเคอร์เนลเพื่อบัฟเฟอร์เอาต์พุตของคุณในไพพ์ ไดรเวอร์นี้สามารถทำสิ่งที่ต้องการได้ แต่โดยปกติแล้วมันจะสัมผัสกับฮาร์ดแวร์เช่นเข้าถึงฮาร์ดดิสก์หรือเล่นเสียงในลำโพง

ในการตอบคำถามเดิม:

  1. มีคำถามสองข้อที่เกี่ยวข้องกับ 'ไฟล์' หรือไม่ นี่คือไฟล์ของอุปกรณ์โหนดว่ามีอยู่จริงหรือไม่และรหัสเคอร์เนลสำรองนั้นมีความหมายหรือไม่ อดีตถูกแก้ไขเช่นเดียวกับทุกอย่างในระบบไฟล์ปกติ ระบบที่ทันสมัยใช้udevหรือสิ่งที่ชอบที่จะดูเหตุการณ์ฮาร์ดแวร์โดยอัตโนมัติและสร้างและทำลายโหนดอุปกรณ์ภายใต้การ/devตาม แต่ระบบที่เก่ากว่าหรือการสร้างที่กำหนดเองแบบเบาสามารถมีโหนดอุปกรณ์ทั้งหมดของพวกเขาบนดิสก์ซึ่งสร้างขึ้นล่วงหน้า ในขณะเดียวกันเมื่อคุณอ่านไฟล์เหล่านี้คุณกำลังโทรไปยังรหัสเคอร์เนลซึ่งกำหนดโดยหมายเลขอุปกรณ์หลักและรอง หากสิ่งเหล่านี้ไม่สมเหตุสมผล (เช่นคุณกำลังพยายามอ่านอุปกรณ์บล็อกที่ไม่มีอยู่) คุณจะได้รับข้อผิดพลาด I / O บางอย่าง

  2. วิธีการทำงานของรหัสเคอร์เนลที่จะเรียกใช้สำหรับไฟล์อุปกรณ์ที่แตกต่างกันไป สำหรับระบบไฟล์เสมือนเช่น/procพวกเขาใช้ของตัวเองreadและwriteฟังก์ชั่น; เคอร์เนลเพียงแค่เรียกรหัสนั้นขึ้นอยู่กับจุดเชื่อมต่อที่อยู่ในนั้นและการใช้งานระบบแฟ้มจะดูแลส่วนที่เหลือ สำหรับไฟล์อุปกรณ์จะทำการจัดส่งตามหมายเลขอุปกรณ์หลักและรอง


ดังนั้นถ้าสมมุติว่าระบบเก่าดึงพลังงานออกมาไฟล์ใน/devนั้นจะยังอยู่ที่นั่น แต่ฉันเดาว่าพวกเขาจะถูกล้างเมื่อระบบเริ่มทำงาน
โจ

2
หากระบบเก่า (ระบบที่ไม่มีการสร้างอุปกรณ์แบบไดนามิก) ถูกปิดไม่ว่าจะปกติหรือผิดปกติโหนดอุปกรณ์จะยังคงอยู่บนดิสก์เช่นเดียวกับไฟล์ใด ๆ จากนั้นเมื่อการบูทครั้งต่อไปเกิดขึ้นพวกเขาจะยังคงอยู่บนดิสก์และคุณสามารถใช้มันได้ตามปกติ เฉพาะในระบบที่ทันสมัยเท่านั้นที่มีสิ่งใดเกิดขึ้นที่สร้างและทำลายโหนดอุปกรณ์
Tom Hunt

ดังนั้นระบบที่ทันสมัยกว่าที่ไม่ได้ใช้tmpfsจะสร้างและลบแบบไดนามิกตามที่ต้องการเช่น: bootup และ shutdown?
โจ

3
devtmpfsที่/devระบบแฟ้มในปัจจุบันลินุกซ์จะคล้ายกับแต่มีความแตกต่างบางอย่างเพื่อให้การสนับสนุนtmpfs udev(เคอร์เนลทำการสร้างโหนดอัตโนมัติบางอย่างด้วยตัวเองก่อนที่จะส่งออกudevเพื่อให้การบู๊ตมีความซับซ้อนน้อยลง) ในทุกกรณีโหนดอุปกรณ์จะใช้งานได้เฉพาะใน RAM และสร้างและทำลายแบบไดนามิกตามฮาร์ดแวร์ที่ต้องการ สันนิษฐานว่าคุณสามารถใช้udevกับดิสก์ธรรมดาได้/devแต่ฉันไม่เคยเห็นสิ่งนี้ทำและดูเหมือนจะไม่มีเหตุผลที่ดี
Tom Hunt

17

นี่คือรายการไฟล์ของ/dev/sda1บนเซิร์ฟเวอร์ Arch Linux ล่าสุดของฉัน:

% ls -li /dev/sda1
1294 brw-rw---- 1 root disk 8, 1 Nov  9 13:26 /dev/sda1

ดังนั้นรายการไดเรกทอรีใน/dev/สำหรับsdaมีหมายเลขไอโหนด 1294 มันเป็นไฟล์จริงบนดิสก์

ดูที่ขนาดไฟล์มักจะปรากฏขึ้น "8, 1" ปรากฏขึ้นแทน นี่คือหมายเลขอุปกรณ์หลักและรอง นอกจากนี้ยังบันทึก 'b' ในการอนุญาตของไฟล์

ไฟล์/usr/include/ext2fs/ext2_fs.hมีโครงสร้าง C นี้ (ส่วน):

/*
 * Structure of an inode on the disk
 */
struct ext2_inode {
    __u16   i_mode;     /* File mode */

struct นั่นแสดงให้เราเห็นโครงสร้างของดิสก์ของ inode ของไฟล์ สิ่งที่น่าสนใจมากมายอยู่ในโครงสร้างนั้น ลองดูที่มันนาน ๆ

i_modeองค์ประกอบของการstruct ext2_inodeมี 16 บิตและจะใช้เพียง 9 เพื่อผู้ใช้ / กลุ่ม / อื่น ๆ อ่าน / เขียน / ผู้สิทธิ์และอีก 3 setuid, setgid และเหนียว มี 4 บิตเพื่อแยกความแตกต่างระหว่างประเภทเช่น "ไฟล์ธรรมดา", "ลิงก์", "ไดเรกทอรี", "ชื่อไพพ์", "ซ็อกเก็ตครอบครัวยูนิกซ์" และ "อุปกรณ์บล็อก"

เคอร์เนล Linux สามารถทำตามอัลกอริทึมการค้นหาไดเรกทอรีปกติจากนั้นทำการตัดสินใจตามสิทธิ์และค่าสถานะในi_modeองค์ประกอบ สำหรับ 'b' บล็อกไฟล์อุปกรณ์สามารถค้นหาหมายเลขอุปกรณ์หลักและรองและใช้หมายเลขอุปกรณ์หลักเพื่อค้นหาตัวชี้ไปยังฟังก์ชันเคอร์เนล (ไดรเวอร์อุปกรณ์) ที่เกี่ยวข้องกับดิสก์ มักจะใช้หมายเลขอุปกรณ์รองตามที่พูดหมายเลขอุปกรณ์บัส SCSI หรือหมายเลขอุปกรณ์ EIDE หรืออะไรทำนองนั้น

การตัดสินใจอื่น ๆ เกี่ยวกับวิธีจัดการกับไฟล์ที่คล้ายกัน/proc/cpuinfoถูกสร้างขึ้นตามชนิดของระบบไฟล์ ถ้าคุณทำ:

% mount | grep proc 
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)

คุณจะเห็นว่า/procมีประเภทระบบไฟล์ของ "proc" การอ่านจากไฟล์/procทำให้เคอร์เนลทำบางอย่างที่แตกต่างกันตามชนิดของระบบไฟล์เช่นเดียวกับการเปิดไฟล์บนระบบไฟล์ ReiserFS หรือ DOS จะทำให้เคอร์เนลใช้ฟังก์ชั่นต่าง ๆ เพื่อค้นหาไฟล์และค้นหาข้อมูลของ ไฟล์


คุณแน่ใจหรือไม่ว่า "ไฟล์จริงบนดิสก์" เท่านั้นที่แสดงหมายเลข inode ฉันได้รับ4026531975 -r--r--r-- 1 root root 0 Nov 14 18:41 /proc/mdstatอย่างชัดเจนไม่ใช่ "ไฟล์จริง"
guntbert

7

ในตอนท้ายของวันพวกเขาทั้งหมดไฟล์สำหรับ Unix นั่นคือความงามของสิ่งที่เป็นนามธรรม

วิธีจัดการไฟล์โดยเคอร์เนลตอนนี้เป็นเรื่องที่แตกต่างกัน

/ proc และทุกวันนี้ / dev และ / run (aka / var / run) เป็นระบบไฟล์เสมือนใน RAM / proc เป็นอินเตอร์เฟส / windows เพื่อตัวแปรเคอร์เนลและโครงสร้าง

ผมขอแนะนำให้อ่าน Linux Kernel http://tldp.org/LDP/tlk/tlk.htmlและไดรเวอร์ของอุปกรณ์ Linux พิมพ์ครั้งที่สามhttps://lwn.net/Kernel/LDD3/

ฉันยังสนุกกับการออกแบบและการใช้งานระบบปฏิบัติการ FreeBSD http://www.amazon.com/Design-Implementation-FreeBSD-Operating-System/dp/0321968972/ref=sr_1_1

ดูที่หน้าที่เกี่ยวข้องซึ่งเกี่ยวข้องกับคำถามของคุณ

http://www.tldp.org/LDP/tlk/dd/drivers.html


ขอบคุณฉันเปลี่ยนคำถามแรกเล็กน้อยหลังจากที่คุณแสดงความคิดเห็น
โจ

อ่านความคิดเห็นล่าสุดโปรด
Rui F Ribeiro

5

นอกเหนือจากคำตอบของ @RuiFRibeiro และ @ BruceEdiger ความแตกต่างที่คุณทำไม่เหมือนกับความแตกต่างของเคอร์เนล ที่จริงแล้วคุณมีไฟล์หลายประเภท: ไฟล์ปกติ, ไดเรกทอรี, ลิงก์สัญลักษณ์, อุปกรณ์, ซ็อกเก็ต (และฉันมักจะลืมบางอย่างดังนั้นฉันจะไม่พยายามทำรายการทั้งหมด) คุณสามารถมีข้อมูลเกี่ยวกับประเภทของไฟล์ด้วยls: เป็นอักขระตัวแรกในบรรทัด ตัวอย่างเช่น:

$ls -la /dev/sda
brw-rw---- 1 root disk 8, 0 17 nov.  08:29 /dev/sda

'b' ที่สัญญาณเริ่มต้นว่าไฟล์นี้เป็นอุปกรณ์บล็อก เส้นประหมายถึงไฟล์ปกติ 'l' ลิงก์สัญลักษณ์และอื่น ๆ ข้อมูลนี้ถูกเก็บไว้ในข้อมูลเมตาของไฟล์และสามารถเข้าถึงได้ผ่านการเรียกใช้ระบบstatตัวอย่างเช่นเคอร์เนลสามารถอ่านไฟล์และลิงก์สัญลักษณ์ต่างกันได้

จากนั้นคุณสร้างความแตกต่างระหว่าง "ไฟล์จริง" ที่ชอบ/bin/bashและ "ไฟล์เสมือน" เช่นกัน/proc/cpuinfoแต่lsรายงานว่าทั้งสองเป็นไฟล์ปกติดังนั้นความแตกต่างเป็นประเภทอื่น:

ls -la /proc/cpuinfo /bin/bash
-rwxr-xr-x 1 root root  829792 24 août  10:58 /bin/bash
-r--r--r-- 1 root wheel      0 20 nov.  16:50 /proc/cpuinfo

สิ่งที่เกิดขึ้นคือพวกมันอยู่ในระบบไฟล์ต่างกัน /procเป็นจุดยึดของระบบไฟล์หลอกprocfsในขณะที่/bin/bashอยู่ในระบบไฟล์ดิสก์ปกติ เมื่อลีนุกซ์เปิดไฟล์ (มันแตกต่างกันไปขึ้นอยู่กับระบบไฟล์), มันจะเติมโครงสร้างข้อมูลfileที่มี, ในบรรดาคุณลักษณะอื่น ๆ โครงสร้างของตัวชี้ฟังก์ชั่นหลายตัวที่อธิบายวิธีการใช้ไฟล์นี้. ดังนั้นจึงสามารถใช้ลักษณะการทำงานที่แตกต่างกันสำหรับไฟล์ประเภทต่างๆ

ตัวอย่างเช่นการดำเนินการเหล่านี้โฆษณาโดย/proc/meminfo:

static int meminfo_proc_open(struct inode *inode, struct file *file)
{
    return single_open(file, meminfo_proc_show, NULL);
}

static const struct file_operations meminfo_proc_fops = {
    .open       = meminfo_proc_open,
    .read       = seq_read,
    .llseek     = seq_lseek,
    .release    = single_release,
};

หากคุณดูคำจำกัดความของmeminfo_proc_openคุณจะเห็นว่าฟังก์ชั่นนี้เติมบัฟเฟอร์ในหน่วยความจำด้วยข้อมูลที่ส่งคืนโดยฟังก์ชั่นmeminfo_proc_showซึ่งมีหน้าที่ในการรวบรวมข้อมูลเกี่ยวกับการใช้หน่วยความจำ ข้อมูลนี้สามารถอ่านได้ตามปกติ ทุกครั้งที่คุณเปิดไฟล์ฟังก์ชั่นmeminfo_proc_openจะถูกเรียกใช้และข้อมูลเกี่ยวกับหน่วยความจำจะถูกรีเฟรช


3

ไฟล์ทั้งหมดในระบบไฟล์เป็น "ของจริง" ในแง่ที่ว่าอนุญาตไฟล์ I / O เมื่อคุณเปิดไฟล์เคอร์เนลจะสร้างไฟล์ descriptor ซึ่งเป็นวัตถุ (ในแง่ของการเขียนโปรแกรมเชิงวัตถุ) ที่ทำหน้าที่เหมือนไฟล์ หากคุณอ่านไฟล์ตัวอธิบายไฟล์จะเรียกใช้งานเมธอดการอ่านซึ่งจะขอระบบไฟล์ (sysfs, ext4, nfs, ฯลฯ ) สำหรับข้อมูลจากไฟล์ ระบบไฟล์นำเสนออินเตอร์เฟสแบบอินเทอร์เฟซกับผู้ใช้และรู้ว่าต้องทำอย่างไรเพื่อจัดการอ่านและเขียน ระบบไฟล์จะขอให้เลเยอร์อื่นจัดการคำขอของพวกเขา สำหรับไฟล์ปกติว่าระบบไฟล์ ext4 สิ่งนี้จะเกี่ยวข้องกับการค้นหาในโครงสร้างข้อมูลของระบบไฟล์ (ซึ่งอาจเกี่ยวข้องกับการอ่านดิสก์) และในที่สุดการอ่านจากดิสก์ (หรือแคช) เพื่อคัดลอกข้อมูลลงในบัฟเฟอร์การอ่าน สำหรับไฟล์ในระบบ sysfs โดยทั่วไปเพียงแค่ sprintf () s บางสิ่งบางอย่างเพื่อบัฟเฟอร์ สำหรับโหนดบล็อก dev นั้นจะขอให้โปรแกรมควบคุมดิสก์อ่านบล็อกบางส่วนและคัดลอกลงในบัฟเฟอร์ (หมายเลขหลักและรองแสดงระบบไฟล์ที่ไดรเวอร์ร้องขอ)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.