عبور 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) الذي ينفذ العمليات التي تتم على نظام ملفات 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 → Page cache/Storage.

FUSE Passthrough SDcardFS

الشكل 1: طلبات مساحة المستخدم في SDcardFS

طلبات مساحة عمل FUSE

تم استخدام FUSE في البداية لتفعيل محاكاة مساحة التخزين والسماح للتطبيقات باستخدام مساحة التخزين الداخلية أو بطاقة SD الخارجية بشكل شفاف. يؤدي استخدام FUSE إلى زيادة بعض النفقات العامة لأنّ كل طلب من مساحة المستخدم يتبع المسار: مساحة المستخدم → نظام الملفات الافتراضي (VFS) → برنامج تشغيل FUSE → برنامج FUSE الخدمي → نظام الملفات الافتراضي (VFS) → ext4 → ذاكرة التخزين المؤقت للصفحات/مساحة التخزين.

مصهر عبور 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.

تحدث العمليات الواردة أعلاه للقراءة/الكتابة وread-iter/write-iter في الملفات العامة وعمليات القراءة/الكتابة في الملفات التي تم تعيين الذاكرة لها. يبقى عبور 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