گذرگاه FUSE

‫Android 12 از FUSE passthrough پشتیبانی می‌کند که سربار FUSE را به‌حداقل می‌رساند تا عملکردی مشابه دسترسی مستقیم به سیستم فایل پایین‌تر حاصل شود. گذردهی FUSE در هسته‌های android12-5.4، android12-5.10، و android-mainline (فقط آزمایش) پشتیبانی می‌شود، که یعنی پشتیبانی از این ویژگی به هسته استفاده‌شده توسط دستگاه و نسخه Android درحال اجرای دستگاه بستگی دارد:

  • دستگاه‌هایی که از Android 11 به Android 12 ارتقا می‌یابند نمی‌توانند از FUSE passthrough پشتیبانی کنند زیرا هسته‌های این دستگاه‌ها ثابت هستند و نمی‌توانند به هسته‌ای منتقل شوند که به‌طور رسمی با تغییرات FUSE passthrough ارتقا یافته است.

  • دستگاه‌هایی که با Android 12 عرضه می‌شوند می‌توانند از FUSE پشتیبانی کنند. برای چنین دستگاه‌هایی، کد چارچوب Android که گذردهی FUSE را پیاده‌سازی می‌کند در مدول اصلی MediaProvider جاسازی شده است که به‌طور خودکار ارتقا می‌یابد. دستگاه‌هایی که MediaProvider را به‌عنوان ماژول خط اصلی پیاده‌سازی نمی‌کنند (برای مثال، دستگاه‌های Android Go)، می‌توانند به تغییرات MediaProvider نیز دسترسی داشته باشند زیرا به‌صورت عمومی هم‌رسانی می‌شوند.

‫FUSE دربرابر SDCardFS

سیستم فایل در فضای کاربر (FUSE) سازوکاری است که به‌وسیله آن عملیات انجام‌شده در سیستم فایل FUSE توسط هسته (دراور FUSE) به برنامه فضای کاربر (دیو FUSE) برون‌سپاری می‌شود، و این برنامه عملیات را پیاده‌سازی می‌کند. ‫Android 11 SDCardFS را منسوخ کرد و FUSE را به‌عنوان راه‌حل پیش‌فرض برای شبیه‌سازی فضای ذخیره‌سازی قرار داد. به‌عنوان بخشی از این تغییر، Android کارگزار FUSE خود را برای رهگیری دسترسی‌های فایل، اعمال ویژگی‌های امنیت و حریم خصوصی اضافی، و دستکاری فایل‌ها در زمان اجرا پیاده‌سازی کرد.

اگرچه FUSE هنگام کار با اطلاعات قابل‌ذخیره در حافظه نهان مثل صفحه‌ها یا مشخصه‌ها عملکرد خوبی دارد، اما هنگام دسترسی به فضای ذخیره‌سازی خارجی، به‌ویژه در دستگاه‌های میان‌رده و پایین‌رده، پسرفت عملکردی ایجاد می‌کند. این پسرفت‌ها ناشی از زنجیره‌ای از عناصر است که در پیاده‌سازی سیستم فایل FUSE با هم همکاری می‌کنند، و همچنین چندین تغییر از فضای هسته به فضای کاربر در ارتباطات بین درایور FUSE و دیمون FUSE (در مقایسه با دسترسی مستقیم به سیستم فایل پایین‌تر که ساده‌تر است و کاملاً در هسته پیاده‌سازی شده است).

برای کاهش این پس‌رفت‌ها، برنامه‌ها می‌توانند از پیوند برای کاهش کپی کردن داده‌ها استفاده کنند و از ContentProvider API برای دسترسی مستقیم به فایل‌های سیستم فایل پایین‌تر استفاده کنند. حتی با این بهینه‌سازی‌های دیگر، هنگام استفاده از FUSE در مقایسه با دسترسی مستقیم به سیستم فایل پایین‌تر، ممکن است پهنای باند عملیات خواندن و نوشتن کاهش یابد — به‌ویژه در عملیات خواندن تصادفی، که در آن هیچ حافظه نهان یا پیش‌خوانی نمی‌تواند کمک کند. و برنامه‌هایی که مستقیماً ازطریق مسیر قدیمی /sdcard/ به فضای ذخیره‌سازی دسترسی دارند همچنان با افت محسوس عملکرد مواجه خواهند بود، به‌ویژه هنگام انجام عملیات ورودی/خروجی سنگین.

درخواست‌های فضای کاربر SDcardFS

استفاده از SDcardFS می‌تواند با برداشتن فراخوانی فضای کاربر از هسته، شبیه‌سازی فضای ذخیره‌سازی و بررسی اجازه‌های FUSE را سرعت بخشد. درخواست‌های فضای کاربر از مسیر زیر پیروی می‌کنند: فضای کاربر → VFS → sdcardfs → VFS → ext4 → حافظه نهان صفحه/فضای ذخیره‌سازی.

FUSE Passthrough SDcardFS

شکل ۱. درخواست‌های فضای کاربر SDcardFS

درخواست‌های فضای کاربر FUSE

FUSE در ابتدا برای فعال کردن شبیه‌سازی فضای ذخیره‌سازی و اجازه دادن به برنامه‌ها برای استفاده شفاف از فضای ذخیره‌سازی داخلی یا کارت SD خارجی استفاده می‌شد. استفاده از FUSE به‌دلیل اینکه هر درخواست فضای کاربر مسیر زیر را دنبال می‌کند، سربار ایجاد می‌کند: فضای کاربر → VFS → درایور FUSE → دیمون FUSE → VFS → ext4 → حافظه نهان صفحه/فضای ذخیره‌سازی.

FUSE Passthrough FUSE

شکل ۲. درخواست‌های فضای کاربر FUSE

درخواست‌های عبور FUSE

بیشتر اجازه‌های دسترسی به فایل هنگام باز کردن فایل بررسی می‌شوند و بررسی‌های اضافی اجازه‌ها هنگام خواندن از آن فایل و نوشتن در آن انجام می‌شود. در برخی موارد، هنگام باز کردن فایل می‌توان فهمید که برنامه درخواست‌کننده دسترسی کامل به فایل درخواستی دارد، بنابراین سیستم نیازی به ادامه بازارسال درخواست‌های خواندن و نوشتن از درایور FUSE به شبح FUSE ندارد (زیرا این کار فقط داده‌ها را از جایی به جای دیگر منتقل می‌کند).

با عبور FUSE، کارگزار FUSE که درخواست باز را مدیریت می‌کند می‌تواند به گرداننده FUSE اطلاع دهد که عملیات مجاز است و همه درخواست‌های خواندن و نوشتن بعدی می‌توانند مستقیماً به سیستم فایل پایین‌تر ارسال شوند. این کار از سربار اضافی انتظار برای پاسخ شبح FUSE فضای کاربر به درخواست‌های درایور FUSE جلوگیری می‌کند.

مقایسه درخواست‌های FUSE و FUSE passthrough در زیر نشان داده شده است.

مقایسه گذرگاه FUSE

شکل ۳. درخواست FUSE دربرابر درخواست عبور FUSE

وقتی برنامه‌ای دسترسی به سیستم فایل FUSE را انجام می‌دهد، عملیات زیر رخ می‌دهد:

  1. گرداننده FUSE درخواست را مدیریت و صف‌بندی می‌کند، سپس آن را به دیمون FUSE ارائه می‌دهد که آن سیستم فایل FUSE را ازطریق نمونه اتصال خاصی در فایل /dev/fuse مدیریت می‌کند، که دیمون FUSE از خواندن آن مسدود شده است.

  2. وقتی کارگزار FUSE درخواستی برای باز کردن فایل دریافت می‌کند، تصمیم می‌گیرد که آیا گذردهی FUSE برای آن فایل خاص دردسترس باشد یا نه. اگر دردسترس باشد، مخفی:

    1. درایور FUSE را از این درخواست مطلع می‌کند.

    2. گذردهی FUSE را برای فایل بااستفاده از FUSE_DEV_IOC_PASSTHROUGH_OPEN ioctl فعال می‌کند، که باید روی توصیف‌گر فایل /dev/fuse بازشده انجام شود.

  3. ‫ioctl ساختار داده‌ای را (به‌عنوان پارامتر) دریافت می‌کند که حاوی موارد زیر است:

    • توصیف‌گر فایل سیستم فایل پایین‌تر که هدف ویژگی عبور است.

    • شناسه یکتای درخواست FUSE که درحال‌حاضر درحال رسیدگی است (باید باز یا ایجاد و باز باشد).

    • فیلدهای اضافی که می‌توانند خالی بمانند و برای پیاده‌سازی‌های آینده درنظر گرفته شده‌اند.

  4. اگر ioctl موفق شود، شبح FUSE درخواست باز را تکمیل می‌کند، درایور FUSE پاسخ شبح 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 passthrough را فعال کرده‌اید، غیرفعال کردن آن مانع از استفاده دستگاه از FUSE passthrough می‌شود اما دستگاه همچنان کار می‌کند.

برای فعال/غیرفعال کردن عبور 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 درحال استفاده است.

«مجموعه آزمون سازگاری Android 12» شامل CtsStorageTest است که شامل آزمون‌هایی است که عبور FUSE را راه‌اندازی می‌کنند. برای اجرای دستی آزمایش، از atest همان‌طور که در زیر نشان داده شده است استفاده کنید:

atest CtsStorageTest