عبور 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 في وحدة mainline لتطبيق MediaProvider، والتي تتم ترقيتها تلقائيًا. يمكن للأجهزة التي لا تُنفِّذ MediaProvider كأحد وحدات الإصدار العلني (مثل أجهزة Android Go) أيضًا الوصول إلى تغييرات MediaProvider عند مشاركتها علنًا.

‫FUSE مقارنةً بـ SDCardFS

نظام الملفات في مساحة المستخدم (FUSE) هو آلية تسمح لنظام التشغيل (النواة) بمنح العقد الخارجية (برنامج تشغيل FUSE) إلى برنامج مساحة المستخدم (الخادم الدائم FUSE) الذي ينفذ العمليات التي يتم إجراؤها على نظام ملفات FUSE. وقد أوقف نظام التشغيل Android 11 نهائيًا مكتبة برمجة التطبيقات SDCardFS وجعل من FUSE التلقائي الحلّ لمحاكاة مساحة التخزين. كجزء من هذا التغيير، نفَّذ نظام التشغيل Android خدمة FUSE الخادمية الخاصة به لمنع الوصول إلى الملفات وفرض ميزات أمان وخصوصية إضافية ومعالجة الملفات أثناء التشغيل.

على الرغم من أنّ FUSE يحقّق أداءً جيدًا عند التعامل مع المعلومات القابلة للتخزين المؤقت، مثل الصفحات أو السمات، إلا أنّه يؤدي إلى تراجع الأداء عند الوصول إلى وحدة التخزين الخارجية، ويظهر ذلك بشكلٍ خاص في الأجهزة المنخفضة ومتوسطة المستوى. تحدث هذه التراجعات بسبب سلسلة من المكوّنات التي تتعاون في تنفيذ نظام ملفات FUSE، بالإضافة إلى عمليات تبديل متعددة من مساحة kernel إلى مساحة المستخدم في الاتصالات بين برنامج تشغيل FUSE وبرنامج FUSE العميل (مقارنةً بالوصول المباشر إلى نظام الملفات الأصغر حجمًا والذي يتم تنفيذه بالكامل في kernel).

للحدّ من هذه التراجعات، يمكن للتطبيقات استخدام الربط لمحاولة تقليل نسخ البيانات واستخدام ContentProvider API للوصول مباشرةً إلى ملفات نظام الملفات ذات المستوى الأدنى. حتى مع هذه التحسينات والتحسينات الأخرى، قد ينخفض معدل نقل البيانات في عمليات القراءة والكتابة عند استخدام FUSE مقارنةً بالوصول المباشر إلى نظام الملفات المنخفض ،  خاصةً مع عمليات القراءة العشوائية، حيث لا يمكن مساعدة ميزة التخزين المؤقت أو القراءة المسبقة. وتستمر التطبيقات التي تَستخدم /sdcard/ للوصول مباشرةً إلى مساحة التخزين في التعرّض لانخفاض ملحوظ في الأداء، خاصةً عند تنفيذ عمليات تتطلّب قدرًا كبيرًا من عمليات I/O.

طلبات مساحة المستخدم في SDcardFS

يمكن أن يؤدي استخدام SDcardFS إلى تسريع عملية محاكاة مساحة التخزين والتحقّق من الأذونات في FUSE من خلال إزالة طلب مساحة المستخدم من النواة. تتّبع طلبات Userspace المسار التالي: Userspace → 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 الخفي (لأنّ ذلك سيؤدي فقط إلى نقل البيانات من مكان إلى آخر).

باستخدام ميزة "النقل المباشر" في FUSE، يمكن لبرنامج FUSE الخفي الذي يعالج طلبًا مفتوحًا إرسال إشعار إلى برنامج تشغيل FUSE بأنّ العملية مسموح بها وأنّه يمكن إعادة توجيه جميع طلبات القراءة والكتابة التالية مباشرةً إلى نظام الملفات الأدنى. ويؤدي ذلك إلى تجنُّب التحميل الزائد العميق الناتج عن انتظار برنامج FUSE الخدمي في مساحة المستخدم للردّ على طلبات برنامج FUSE السائق.

في ما يلي مقارنة بين طلبات FUSE وطلبات تمرير FUSE.

مقارنة بين تقنية FUSE Passthrough

الشكل 3: طلب FUSE مقابل طلب تمرير FUSE

عندما ينفِّذ تطبيق عملية وصول إلى نظام ملفات FUSE، تحدث العمليات التالية:

  1. يعالج برنامج تشغيل FUSE الطلب ويضيفه إلى قائمة الانتظار، ثم يعرضه على العميل الدائم لـ FUSE الذي يعالج نظام ملفات FUSE من خلال مثيل اتصال محدّد في ملف /dev/fuse الذي لا يمكن للعميل الدائم لـ FUSE قراءة محتوياته.

  2. عندما يتلقّى الخادم الدائم لبروتوكول FUSE طلبًا لفتح ملف، يقرّر ما إذا كان ينبغي أن يكون أسلوب "تمرير البيانات" في FUSE متاحًا لهذا الملف المحدّد. إذا كان العميل متاحًا، ينفذ ما يلي:

    1. إرسال إشعار إلى برنامج تشغيل FUSE بهذا الطلب

    2. تفعِّل هذه القيمة ميزة FUSE passthrough للملف باستخدام FUSE_DEV_IOC_PASSTHROUGH_OPEN ioctl، والتي يجب تنفيذها على /dev/fuse وصف الملف الذي تم فتحه.

  3. تتلقّى دالة ioctl (كمَعلمة) بنية بيانات تحتوي على ما يلي:

    • وصف الملف لملف نظام الملفات الأصغر الذي يمثّل الهدف لاستخدام ميزة النقل المباشر

    • المعرّف الفريد لطلب FUSE الذي تتم معالجته حاليًا (يجب أن يكون مفتوحًا أو مفتوحًا وقيد الإنشاء).

    • حقول إضافية يمكن تركها فارغة ومخصّصة لعمليات التنفيذ القادمة

  4. إذا تمكّن ioctl من إكمال طلب الفتح، يُكمل برنامج FUSE الخدمي طلب الفتح، ويعالج ملف FUSE الردّ من برنامج FUSE الخدمي، وتتم إضافة إشارة إلى ملف ملف system الأدنى إلى ملف 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 passthrough قيد الاستخدام.

تتضمّن مجموعة أدوات اختبار التوافق (CTS) لنظام التشغيل Android 12 CtsStorageTest، والتي تشمل الاختبارات التي تؤدي إلى تفعيل ميزة FUSE passthrough. لإجراء الاختبار يدويًا، استخدِم ملف ‎atest كما هو موضّح أدناه:

atest CtsStorageTest