การส่งผ่าน FUSE

Android 12 รองรับการส่งผ่าน FUSE ซึ่งช่วยลดโอเวอร์เฮดของ FUSE ให้น้อยที่สุดเพื่อให้มีประสิทธิภาพเทียบเท่ากับการเข้าถึงระบบไฟล์ที่ต่ำกว่าโดยตรง ระบบรองรับการส่งผ่าน FUSE ในเคอร์เนล android12-5.4, android12-5.10 และ android-mainline (การทดสอบเท่านั้น) ซึ่งหมายความว่าการรองรับฟีเจอร์นี้ขึ้นอยู่กับเคอร์เนลที่อุปกรณ์ใช้และเวอร์ชัน Android ที่อุปกรณ์ใช้อยู่

  • อุปกรณ์ที่อัปเกรดจาก Android 11 เป็น Android 12 ไม่สามารถ สนับสนุนการส่งผ่าน FUSE เนื่องจากเคอร์เนลสำหรับอุปกรณ์เหล่านี้ค้างและไม่สามารถย้ายไปยังเคอร์เนลที่มีการอัปเกรดอย่างเป็นทางการด้วยการเปลี่ยนแปลงการส่งผ่าน FUSE

  • อุปกรณ์ที่เปิดตัวด้วย Android 12 จะรองรับ FUSE การส่งผ่านเมื่อใช้เคอร์เนลอย่างเป็นทางการ สำหรับอุปกรณ์ดังกล่าว โค้ดเฟรมเวิร์ก Android ที่ใช้การส่งผ่าน FUSE จะฝังอยู่ในโมดูลหลักของ MediaProvider ซึ่งจะอัปเกรดโดยอัตโนมัติ อุปกรณ์ที่ไม่ได้ใช้ MediaProvider เป็นโมดูลหลัก (เช่น อุปกรณ์ Android Go) จะเข้าถึงการเปลี่ยนแปลงของ MediaProvider ได้เช่นกันเมื่อมีการแชร์แบบสาธารณะ

FUSE กับ SDCardFS

ระบบไฟล์ในพื้นที่ผู้ใช้ (FUSE) เป็นกลไกที่ช่วยให้เคอร์เนล (ไดรเวอร์ FUSE) ส่งการดำเนินการในระบบไฟล์ FUSE ไปยังโปรแกรมในพื้นที่ผู้ใช้ (Damon ของ FUSE) ซึ่งจะใช้การดำเนินการดังกล่าว Android 11 เลิกใช้งาน SDCardFS และกำหนดให้ FUSE เป็นโซลูชันเริ่มต้นสำหรับการจำลองพื้นที่เก็บข้อมูล การเปลี่ยนแปลงนี้ทำให้ Android ใช้ Dæmon FUSE ของตัวเองเพื่อขัดขวางการเข้าถึงไฟล์ บังคับใช้ฟีเจอร์ด้านความปลอดภัยและความเป็นส่วนตัวเพิ่มเติม รวมถึงจัดการไฟล์ขณะรันไทม์

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

หากต้องการลดการถดถอยเหล่านี้ แอปสามารถใช้การต่อเพื่อลดการคัดลอกข้อมูล และใช้ ContentProvider API เพื่อเข้าถึงไฟล์ระบบไฟล์ระดับล่างโดยตรง แม้ว่าจะมีการเพิ่มประสิทธิภาพเหล่านี้และการเพิ่มประสิทธิภาพอื่นๆ การดำเนินการอ่านและเขียนก็อาจลดแบนด์วิดท์เมื่อใช้ FUSE เมื่อเทียบกับการเข้าถึงโดยตรงไปยังระบบไฟล์ที่ต่ำกว่า — โดยเฉพาะอย่างยิ่งเมื่อมีการสุ่มอ่าน ซึ่งจะใช้การแคชหรืออ่านล่วงหน้าไม่ได้ และแอปที่เข้าถึงพื้นที่เก็บข้อมูลผ่านเส้นทาง /sdcard/ เดิมโดยตรงจะยังมีประสิทธิภาพลดลงอย่างเห็นได้ชัด โดยเฉพาะอย่างยิ่งเมื่อทำงานที่ต้องใช้ IO ปริมาณมาก

คำขอพื้นที่ผู้ใช้ SDcardFS

การใช้ SDcardFS ช่วยเพิ่มความเร็วในการจําลองพื้นที่เก็บข้อมูลและการตรวจสอบสิทธิ์ของ FUSE ได้ด้วยการนําการเรียกใช้พื้นที่ผู้ใช้ออกจากเคอร์เนล คำขอพื้นที่ผู้ใช้จะไปตามเส้นทาง ดังนี้ พื้นที่ผู้ใช้ → VFS → sdcardfs → VFS → ext4 → แคชหน้าเว็บ/พื้นที่เก็บข้อมูล

FUSE Passthrough SDcardFS

รูปที่ 1 คำขอพื้นที่ผู้ใช้ SDcardFS

คำขอพื้นที่ผู้ใช้ FUSE

เดิม FUSE ใช้เพื่อเปิดใช้การจําลองพื้นที่เก็บข้อมูลและอนุญาตให้แอปใช้พื้นที่เก็บข้อมูลภายในหรือการ์ด SD ภายนอกอย่างโปร่งใส การใช้ FUSE จะทำให้เกิดค่าใช้จ่ายเพิ่มเติมเนื่องจากคำขอแต่ละรายการในพื้นที่ผู้ใช้จะเป็นไปตามเส้นทางต่อไปนี้ พื้นที่ผู้ใช้ → VFS → ไดร์เวอร์ FUSE → ดีมอน FUSE → VFS → ext4 → แคชหน้าเว็บ/พื้นที่เก็บข้อมูล

FUSE Passthrough FUSE

รูปที่ 2 คำขอพื้นที่ผู้ใช้ FUSE

คำขอการส่งผ่าน FUSE

ระบบจะตรวจสอบสิทธิ์การเข้าถึงไฟล์ส่วนใหญ่เมื่อเปิดไฟล์ โดยจะมีการตรวจสอบสิทธิ์เพิ่มเติมเมื่ออ่านและเขียนไฟล์นั้น ในบางกรณี ระบบอาจทราบเมื่อเปิดไฟล์ว่าแอปที่ขอมีสิทธิ์เข้าถึงไฟล์ที่ขออย่างเต็มรูปแบบแล้ว ระบบจึงไม่จำเป็นต้องส่งต่อการอ่านและเขียนคำขอจากไดรเวอร์ FUSE ไปยัง FUSE daemon ต่อไป (เนื่องจากการดำเนินการดังกล่าวจะย้ายข้อมูลจากที่หนึ่งไปยังอีกที่หนึ่งเท่านั้น)

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

การเปรียบเทียบคําขอ FUSE กับคําขอ FUSE Passthrough แสดงอยู่ด้านล่าง

การเปรียบเทียบการแสดงผลผ่าน FUSE

รูปที่ 3 คำขอ FUSE เทียบกับคำขอการส่งผ่าน FUSE

เมื่อแอปทำการเข้าถึงระบบไฟล์ FUSE ระบบจะดำเนินการต่อไปนี้

  1. ไดรเวอร์ FUSE จะจัดการและกำหนดคิวคำขอ จากนั้นจะแสดงคำขอไปยัง Daemon FUSE ที่จัดการระบบไฟล์ FUSE นั้นผ่านอินสแตนซ์การเชื่อมต่อที่เจาะจงในไฟล์ /dev/fuse ซึ่ง Daemon ของ FUSE ถูกบล็อกไม่ให้อ่าน

  2. เมื่อเดมอน FUSE ได้รับคําขอเปิดไฟล์ ก็จะตัดสินใจว่าควรใช้การส่งผ่าน FUSE สําหรับไฟล์นั้นหรือไม่ หากพร้อมใช้งาน โปรแกรมเดรัมจะดำเนินการต่อไปนี้

    1. แจ้งไดรเวอร์ FUSE เกี่ยวกับคำขอนี้

    2. เปิดใช้การส่งผ่าน FUSE สำหรับไฟล์โดยใช้ FUSE_DEV_IOC_PASSTHROUGH_OPEN ioctl ซึ่งต้องดำเนินการกับตัวระบุไฟล์ของ /dev/fuse ที่เปิดอยู่

  3. Ioctl จะรับ (เป็นพารามิเตอร์) โครงสร้างข้อมูลที่มีสิ่งต่อไปนี้

    • ตัวระบุไฟล์ของไฟล์ระบบไฟล์ที่ต่ำกว่าซึ่งเป็นเป้าหมายของฟีเจอร์การส่งผ่าน

    • ตัวระบุที่ไม่ซ้ำกันของคำขอ FUSE ที่กำลังจัดการอยู่ (ต้องเปิดหรือสร้างและเปิด)

    • ฟิลด์เพิ่มเติมที่ปล่อยว่างไว้ได้และมีไว้สําหรับการใช้งานในอนาคต

  4. หาก ioctl ดำเนินการสำเร็จ โปรแกรม DASH ของ FUSE จะดำเนินการตามคำขอที่เปิดอยู่ให้เสร็จสมบูรณ์ โปรแกรมควบคุม FUSE จะจัดการการตอบกลับของโปรแกรม DASH ของ FUSE และระบบจะเพิ่มการอ้างอิงไปยังไฟล์ระบบระดับล่างลงในไฟล์ FUSE ภายในเคอร์เนล เมื่อแอปส่งคำขอการดำเนินการอ่าน/เขียนในไฟล์ FUSE โปรแกรมควบคุม FUSE จะตรวจสอบว่ามีไฟล์ระบบไฟล์ที่ต่ำกว่าซึ่งอ้างอิงถึงหรือไม่

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

    • หากไม่มีข้อมูลอ้างอิง โปรแกรมควบคุมจะส่งต่อคำขอไปยัง FUSE ไดมอน

การดำเนินการข้างต้นจะเกิดขึ้นกับ โปรดอ่าน/เขียนและอ่านและเขียนบนไฟล์ทั่วไปและการดำเนินการอ่าน/เขียนในไฟล์ที่แมปด้วยหน่วยความจำ การส่งผ่าน FUSE สำหรับไฟล์หนึ่งๆ จะยังคงอยู่จนกว่าไฟล์นั้นจะปิด

ใช้การส่งผ่าน FUSE

หากต้องการเปิดใช้การส่งผ่าน FUSE ในอุปกรณ์ที่ใช้ Android 12 ให้เพิ่มบรรทัดต่อไปนี้ลงในไฟล์ $ANDROID_BUILD_TOP/device/…/device.mk ของอุปกรณ์เป้าหมาย

# Use FUSE passthrough
PRODUCT_PRODUCT_PROPERTIES += \
    persist.sys.fuse.passthrough.enable=true

หากต้องการปิดใช้การส่งผ่าน FUSE ให้ข้ามการเปลี่ยนแปลงการกำหนดค่าข้างต้นหรือตั้งค่า persist.sys.fuse.passthrough.enable เป็น false หากคุณเคยเปิดใช้การส่งผ่าน FUSE ไว้ การปิดใช้ฟีเจอร์นี้จะป้องกันไม่ให้อุปกรณ์ใช้การส่งผ่าน FUSE แต่อุปกรณ์จะยังคงทำงานได้

หากต้องการเปิด/ปิดใช้การส่งผ่าน FUSE โดยไม่แฟลชอุปกรณ์ ให้เปลี่ยนพร็อพเพอร์ตี้ของระบบโดยใช้คำสั่ง ADB โปรดดูตัวอย่างด้านล่าง

adb root
adb shell setprop persist.sys.fuse.passthrough.enable {true,false}
adb reboot

หากต้องการความช่วยเหลือเพิ่มเติม โปรดดูการใช้งานข้อมูลอ้างอิง

ตรวจสอบการส่งผ่าน FUSE

หากต้องการตรวจสอบว่า MediaProvider ใช้การส่งผ่าน FUSE ให้ตรวจสอบlogcatเพื่อหาข้อความการแก้ไขข้อบกพร่อง เช่น

adb logcat FuseDaemon:V \*:S
--------- beginning of main
03-02 12:09:57.833  3499  3773 I FuseDaemon: Using FUSE passthrough
03-02 12:09:57.833  3499  3773 I FuseDaemon: Starting fuse...

รายการ FuseDaemon: Using FUSE passthrough ในบันทึกช่วยให้มั่นใจได้ว่ามีการใช้ FUSE ผ่าน

CTS ของ Android 12 มี CtsStorageTest ซึ่งรวมถึงการทดสอบที่ทริกเกอร์การส่งผ่าน FUSE หากต้องการทำการทดสอบด้วยตนเอง ให้ใช้ annotate ดังที่แสดงด้านล่าง

atest CtsStorageTest