การปล่อยผ่าน FUSE

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

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

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

FUSE กับ SDCardFS

ระบบไฟล์ใน Userspace (FUSE) เป็นกลไกที่ อนุญาตให้เคอร์เนล (ไดรเวอร์ FUSE) ส่งต่อการดำเนินการที่ทำในระบบไฟล์ FUSE ไปยังโปรแกรม Userspace (FUSE Daemon) ซึ่งจะใช้การดำเนินการ ดังกล่าว Android 11 เลิกใช้งาน SDCardFS และทำให้ FUSE เป็นโซลูชันเริ่มต้น สำหรับการจำลองพื้นที่เก็บข้อมูล การเปลี่ยนแปลงนี้ทำให้ Android ต้องใช้ daemon 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

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

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

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

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

การเปรียบเทียบคำขอ FUSE และคำขอส่งผ่าน FUSE แสดงอยู่ด้านล่าง

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

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

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

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

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

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

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

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

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

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

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

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

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

    • หากไม่มีข้อมูลอ้างอิง ไดรเวอร์จะส่งต่อคำขอไปยัง FUSE daemon

การดำเนินการข้างต้นจะเกิดขึ้นสำหรับการอ่าน/เขียนและการอ่าน-วนซ้ำ/เขียน-วนซ้ำในไฟล์ทั่วไป และการดำเนินการอ่าน/เขียนในไฟล์ที่แมปหน่วยความจำ การส่งผ่าน 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 หากต้องการเรียกใช้การทดสอบด้วยตนเอง ให้ใช้ atest ดังที่แสดงด้านล่าง

atest CtsStorageTest