ระบบไฟล์เสมือนใน Linux: เหตุใดจึงต้องใช้และทำงานอย่างไร ส่วนที่ 2

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

วิธีตรวจสอบ VFS โดยใช้เครื่องมือ eBPF และ bcc

วิธีที่ง่ายที่สุดในการทำความเข้าใจว่าเคอร์เนลทำงานอย่างไรกับไฟล์ sysfs คือการดูในทางปฏิบัติ และวิธีที่ง่ายที่สุดในการรับชม ARM64 คือการใช้ eBPF eBPF (ย่อมาจาก Berkeley Packet Filter) ประกอบด้วยเครื่องเสมือนที่ทำงานอยู่ แกนกลางซึ่งผู้ใช้สิทธิพิเศษสามารถร้องขอได้ (query) จากบรรทัดคำสั่ง แหล่งที่มาของเคอร์เนลบอกผู้อ่านว่าเคอร์เนลสามารถทำอะไรได้บ้าง การรันเครื่องมือ eBPF บนระบบที่โหลดจะแสดงสิ่งที่เคอร์เนลกำลังทำอยู่จริง

ระบบไฟล์เสมือนใน Linux: เหตุใดจึงต้องใช้และทำงานอย่างไร ส่วนที่ 2

โชคดีที่การเริ่มต้นใช้งาน eBPF นั้นค่อนข้างง่ายด้วยความช่วยเหลือจากเครื่องมือต่างๆ สำเนาลับซึ่งมีจำหน่ายเป็นแพ็คเกจจากการจำหน่ายทั่วไป ลินุกซ์ และบันทึกไว้อย่างละเอียด เบอร์นาร์ด เกร็ก. เครื่องมือ bcc เป็นสคริปต์ Python ที่มีการแทรกโค้ด C เล็กน้อย ซึ่งหมายความว่าใครก็ตามที่คุ้นเคยกับทั้งสองภาษาสามารถแก้ไขได้อย่างง่ายดาย ใน bcc/tools มีสคริปต์ Python 80 สคริปต์ ซึ่งหมายความว่านักพัฒนาหรือผู้ดูแลระบบส่วนใหญ่สามารถเลือกสิ่งที่เหมาะสมสำหรับการแก้ปัญหาได้
หากต้องการทราบแนวคิดอย่างผิวเผินเป็นอย่างน้อยว่า VFS ทำงานอย่างไรบนระบบที่กำลังรันอยู่ ให้ลอง vfscount หรือ vfsstat. นี่จะแสดงสมมติว่ามีการโทรหลายสิบสาย vfs_open() และ “เพื่อนของเขา” เกิดขึ้นทุกวินาทีอย่างแท้จริง

ระบบไฟล์เสมือนใน Linux: เหตุใดจึงต้องใช้และทำงานอย่างไร ส่วนที่ 2

vfsstat.py เป็นสคริปต์ Python ที่มีการแทรกโค้ด C ซึ่งนับการเรียกใช้ฟังก์ชัน VFS เพียงอย่างเดียว

เรามายกตัวอย่างเล็กน้อยและดูว่าเกิดอะไรขึ้นเมื่อเราเสียบแฟลชไดรฟ์ USB เข้ากับคอมพิวเตอร์และระบบตรวจพบ

ระบบไฟล์เสมือนใน Linux: เหตุใดจึงต้องใช้และทำงานอย่างไร ส่วนที่ 2

การใช้ eBPF คุณสามารถดูสิ่งที่เกิดขึ้นได้ /sysเมื่อเสียบแฟลชไดรฟ์ USB ตัวอย่างที่ง่ายและซับซ้อนแสดงไว้ที่นี่

ในตัวอย่างที่แสดงข้างต้น bcc เครื่องมือ ติดตาม.py พิมพ์ข้อความเมื่อรันคำสั่ง sysfs_create_files(). เราเห็นสิ่งนั้น sysfs_create_files() เปิดตัวโดยใช้ kworker สตรีมเพื่อตอบสนองต่อความจริงที่ว่าใส่แฟลชไดรฟ์แล้ว แต่ไฟล์ใดที่ถูกสร้างขึ้น? ตัวอย่างที่สองแสดงให้เห็นถึงพลังของ eBPF ที่นี่ trace.py พิมพ์เคอร์เนล backtrace (-K ตัวเลือก) และชื่อของไฟล์ที่สร้างขึ้น sysfs_create_files(). การแทรกคำสั่งเดี่ยวคือโค้ด C ที่มีสตริงรูปแบบที่จดจำได้ง่ายซึ่งจัดทำโดยสคริปต์ Python ที่รัน LLVM คอมไพเลอร์ทันเวลา. มันรวบรวมบรรทัดนี้และดำเนินการในเครื่องเสมือนภายในเคอร์เนล ลายเซ็นฟังก์ชั่นเต็มรูปแบบ sysfs_create_files () ต้องทำซ้ำในคำสั่งที่สองเพื่อให้สตริงรูปแบบสามารถอ้างอิงถึงพารามิเตอร์ตัวใดตัวหนึ่งได้ ข้อผิดพลาดในโค้ด C ส่วนนี้ส่งผลให้เกิดข้อผิดพลาดที่จดจำได้จากคอมไพเลอร์ C ตัวอย่างเช่น หากละเว้นพารามิเตอร์ -l คุณจะเห็นข้อความ "ไม่สามารถคอมไพล์ข้อความ BPF" นักพัฒนาที่คุ้นเคยกับ C และ Python จะพบเครื่องมือเหล่านี้ bcc ง่ายต่อการขยายและเปลี่ยนแปลง

เมื่อเสียบไดรฟ์ USB เคอร์เนล backtrace จะแสดงว่า PID 7711 เป็นเธรด kworkerที่สร้างไฟล์ «events» в sysfs. ตามสายจาก sysfs_remove_files() จะแสดงว่าการถอดไดรฟ์ส่งผลให้ไฟล์ถูกลบ eventsซึ่งสอดคล้องกับแนวคิดทั่วไปของการนับอ้างอิง ขณะเดียวกันก็ชม. sysfs_create_link () ด้วย eBPF ขณะเสียบไดรฟ์ USB จะแสดงว่ามีการสร้างลิงก์สัญลักษณ์อย่างน้อย 48 รายการ

แล้วไฟล์เหตุการณ์มีไว้เพื่ออะไร? การใช้งาน กล้องส่องทางไกล สำหรับการค้นหา __อุปกรณ์_เพิ่ม_ดิสก์()แสดงว่าเกิดจากอะไร disk_add_events ()และอย่างใดอย่างหนึ่ง "media_change"หรือ "eject_request" สามารถบันทึกลงในไฟล์เหตุการณ์ได้ ที่นี่เลเยอร์บล็อกเคอร์เนลแจ้งให้ผู้ใช้ทราบว่ามี "ดิสก์" ปรากฏขึ้นและดีดออก โปรดทราบว่าวิธีการวิจัยนี้ให้ข้อมูลที่เป็นประโยชน์เพียงใดโดยการใส่ไดรฟ์ USB เมื่อเปรียบเทียบกับการพยายามค้นหาว่าสิ่งต่างๆ ทำงานจากแหล่งที่มาเพียงอย่างเดียวได้อย่างไร

ระบบไฟล์รูทแบบอ่านอย่างเดียวเปิดใช้งานอุปกรณ์ฝังตัว

แน่นอนว่าไม่มีใครปิดเซิร์ฟเวอร์หรือคอมพิวเตอร์ของตนโดยการดึงปลั๊กออกจากเต้ารับ แต่ทำไม? เนื่องจากระบบไฟล์ที่ติดตั้งบนอุปกรณ์จัดเก็บข้อมูลทางกายภาพอาจมีการเขียนล่าช้า และโครงสร้างข้อมูลที่บันทึกสถานะอาจไม่ซิงโครไนซ์กับการเขียนไปยังที่จัดเก็บข้อมูล เมื่อสิ่งนี้เกิดขึ้น เจ้าของระบบต้องรอจนกระทั่งการบู๊ตครั้งถัดไปจึงจะเปิดใช้งานยูทิลิตี้ได้ fsck filesystem-recovery และในกรณีที่เลวร้ายที่สุดคือการสูญเสียข้อมูล

อย่างไรก็ตาม เราทุกคนทราบดีว่าอุปกรณ์ IoT จำนวนมาก รวมถึงเราเตอร์ ตัวควบคุมอุณหภูมิ และรถยนต์ ต่างใช้ Linux ในปัจจุบัน อุปกรณ์เหล่านี้จำนวนมากมีส่วนติดต่อผู้ใช้เพียงเล็กน้อยหรือไม่มีเลย และไม่มีวิธีใดที่จะปิด "หมดจด" ลองนึกภาพการสตาร์ทรถโดยที่แบตเตอรี่หมดในขณะที่มีไฟจ่ายให้กับชุดควบคุม ลินุกซ์ กระโดดขึ้นลงอย่างต่อเนื่อง เป็นยังไงบ้างที่ระบบบูทได้ไม่นาน fsckในที่สุดเครื่องยนต์ก็เริ่มทำงานเมื่อใด? และคำตอบนั้นง่าย อุปกรณ์ฝังตัวอาศัยระบบไฟล์รูท สำหรับการอ่านเท่านั้น (ยาก ro-rootfs (ระบบไฟล์รูทแบบอ่านอย่างเดียว))

ro-rootfs ให้ประโยชน์มากมายที่ไม่ชัดเจนกว่าความถูกต้อง ข้อดีประการหนึ่งคือมัลแวร์ไม่สามารถเขียนถึงได้ /usr หรือ /libหากไม่มีกระบวนการ Linux สามารถเขียนที่นั่นได้ อีกประการหนึ่งคือระบบไฟล์ที่ไม่เปลี่ยนรูปแบบส่วนใหญ่มีความสำคัญอย่างยิ่งต่อการสนับสนุนภาคสนามของอุปกรณ์ระยะไกล เนื่องจากบุคลากรฝ่ายสนับสนุนอาศัยระบบท้องถิ่นซึ่งมีชื่อเหมือนกันกับระบบภาคสนาม บางทีประโยชน์ที่สำคัญที่สุด (แต่ร้ายกาจที่สุด) ก็คือ ro-rootfs บังคับให้นักพัฒนาตัดสินใจว่าออบเจ็กต์ระบบใดที่จะไม่เปลี่ยนรูปในขั้นตอนการออกแบบของระบบ การทำงานกับ ro-rootfs อาจเป็นเรื่องที่น่าอึดอัดใจและเจ็บปวด เนื่องจากตัวแปร const มักจะอยู่ในภาษาการเขียนโปรแกรม แต่ประโยชน์ของตัวแปรเหล่านี้จะช่วยพิสูจน์ค่าใช้จ่ายเพิ่มเติมได้อย่างง่ายดาย

การสร้าง rootfs อ่านอย่างเดียวต้องใช้ความพยายามเป็นพิเศษสำหรับนักพัฒนาแบบฝัง และนี่คือจุดที่ VFS เข้ามามีบทบาท Linux กำหนดให้ไฟล์ต้องอยู่ใน /var สามารถเขียนได้ และนอกจากนี้ แอปพลิเคชันยอดนิยมจำนวนมากที่ใช้ระบบฝังตัวจะพยายามสร้างการกำหนดค่า dot-files в $HOME. วิธีแก้ปัญหาหนึ่งสำหรับไฟล์การกำหนดค่าในโฮมไดเร็กตอรี่คือการสร้างล่วงหน้าและสร้างไฟล์เหล่านั้น rootfs. สำหรับ /var วิธีหนึ่งที่เป็นไปได้คือติดตั้งบนพาร์ติชันที่เขียนได้แยกต่างหากในขณะที่ / ติดตั้งแบบอ่านอย่างเดียว อีกทางเลือกหนึ่งที่ได้รับความนิยมคือการใช้การผูกหรือการซ้อนทับ

ตัวยึดแบบเชื่อมโยงและวางซ้อนกันได้ ใช้งานโดยคอนเทนเนอร์

การดำเนินการคำสั่ง man mount เป็นวิธีที่ดีที่สุดในการเรียนรู้เกี่ยวกับการเมานต์แบบผูกและซ้อนทับได้ ซึ่งช่วยให้นักพัฒนาและผู้ดูแลระบบสามารถสร้างระบบไฟล์ในพาธหนึ่งแล้วเปิดเผยไปยังแอปพลิเคชันในอีกพาธหนึ่ง สำหรับระบบฝังตัว นี่หมายถึงความสามารถในการจัดเก็บไฟล์ /var บนแฟลชไดรฟ์แบบอ่านอย่างเดียว แต่มีเส้นทางการซ้อนทับหรือลิงก์ที่เชื่อมโยงได้ tmpfs в /var เมื่อโหลดจะช่วยให้แอปพลิเคชันสามารถเขียนบันทึกที่นั่นได้ (เขียนลวก ๆ) ครั้งต่อไปที่คุณเปิดการเปลี่ยนแปลงไปที่ /var จะหายไป การติดตั้งแบบซ้อนทับจะสร้างความสัมพันธ์ระหว่างกัน tmpfs และระบบไฟล์ที่ซ่อนอยู่และช่วยให้คุณทำการเปลี่ยนแปลงที่ชัดเจนกับไฟล์ที่มีอยู่ในนั้น ro-tootf ในขณะที่การเมานต์แบบผูกมัดสามารถทำให้อันใหม่ว่างเปล่าได้ tmpfs โฟลเดอร์ที่มองเห็นได้ว่าเขียนได้ ro-rootfs วิธี ในขณะที่ overlayfs นี่คือสิ่งที่ถูกต้อง (proper) ประเภทระบบไฟล์ มีการปรับใช้การเมานต์แบบผูกได้ เนมสเปซ VFS.

จากคำอธิบายของโอเวอร์เลย์และตัวยึดแบบเชื่อมต่อได้ ไม่มีใครแปลกใจเลย คอนเทนเนอร์ลินุกซ์ มีการใช้อย่างแข็งขัน มาดูกันว่าเกิดอะไรขึ้นเมื่อเราใช้ systemd-nspawn เพื่อรันคอนเทนเนอร์โดยใช้เครื่องมือ mountsnoop จาก bcc.

โทรศัพท์ system-nspawn เริ่มคอนเทนเนอร์ขณะทำงาน mountsnoop.py.

มาดูกันว่าเกิดอะไรขึ้น:

ยิง mountsnoop ในขณะที่คอนเทนเนอร์กำลัง "บูท" แสดงว่ารันไทม์ของคอนเทนเนอร์นั้นขึ้นอยู่กับการเมานต์ที่กำลังเชื่อมโยงอย่างมาก (แสดงเฉพาะจุดเริ่มต้นของเอาต์พุตแบบยาวเท่านั้น)

ที่นี่ systemd-nspawn ให้ไฟล์ที่เลือกมา procfs и sysfs โฮสต์ไปยังคอนเทนเนอร์เป็นเส้นทางไปยังคอนเทนเนอร์นั้น rootfs... นอกเหนือจาก MS_BIND แฟล็กที่ตั้งค่าการโยงการเมาท์ แฟล็กอื่น ๆ บนการเมาท์จะกำหนดความสัมพันธ์ระหว่างการเปลี่ยนแปลงในเนมสเปซโฮสต์และคอนเทนเนอร์ ตัวอย่างเช่น การเมานต์ที่เชื่อมโยงสามารถข้ามการเปลี่ยนแปลงไปได้ /proc и /sys ลงในคอนเทนเนอร์หรือซ่อนไว้ตามการโทร

ข้อสรุป

การทำความเข้าใจการทำงานภายในของ Linux อาจดูเหมือนเป็นงานที่เป็นไปไม่ได้ เนื่องจากตัวเคอร์เนลเองประกอบด้วยโค้ดจำนวนมหาศาล โดยละทิ้งแอปพลิเคชันพื้นที่ผู้ใช้ Linux และอินเทอร์เฟซการเรียกระบบในไลบรารี C เช่น glibc. วิธีหนึ่งในการสร้างความคืบหน้าคือการอ่านซอร์สโค้ดของระบบย่อยเคอร์เนลเดียว โดยเน้นที่การทำความเข้าใจการเรียกระบบและส่วนหัวของพื้นที่ผู้ใช้ รวมถึงอินเทอร์เฟซเคอร์เนลภายในหลัก เช่น ตาราง file_operations. การทำงานของไฟล์มีหลักการ "ทุกอย่างเป็นไฟล์" ทำให้การจัดการไฟล์เป็นเรื่องสนุกเป็นพิเศษ ไฟล์ต้นฉบับเคอร์เนล C ในไดเร็กทอรีระดับบนสุด fs/ นำเสนอการนำระบบไฟล์เสมือนไปใช้ ซึ่งเป็นเลเยอร์ wrapper ที่ให้ความเข้ากันได้ในวงกว้างและค่อนข้างง่ายระหว่างระบบไฟล์ยอดนิยมและอุปกรณ์จัดเก็บข้อมูล การลิงก์และการติดตั้งแบบโอเวอร์เลย์ผ่านเนมสเปซ Linux ถือเป็นความมหัศจรรย์ของ VFS ที่ทำให้การสร้างคอนเทนเนอร์แบบอ่านอย่างเดียวและระบบไฟล์รูทเป็นไปได้ เมื่อรวมกับการตรวจสอบซอร์สโค้ด เครื่องมือหลักของ eBPF และอินเทอร์เฟซ bcc
ทำให้การสำรวจแกนหลักง่ายกว่าที่เคย

เพื่อน ๆ เขียนบทความนี้มีประโยชน์กับคุณไหม? บางทีคุณอาจมีความคิดเห็นหรือข้อสังเกต? และผู้ที่สนใจหลักสูตร Linux Administrator วันเปิดเทอมซึ่งจะจัดขึ้นในวันที่ 18 เมษายน

ส่วนแรก.

ที่มา: will.com

เพิ่มความคิดเห็น