نظرة عامة على A/B الافتراضية

لدى Android آليتان للتحديث: تحديثات A/B (سلسة) وتحديثات غير A/B. لتقليل تعقيد التعليمات البرمجية وتعزيز عملية التحديث، تم توحيد الآليتين في Android 11 من خلال A/B الظاهري لتوفير تحديثات سلسة لجميع الأجهزة بأقل تكلفة للتخزين. يوفر Android 12 خيار الضغط الظاهري A/B لضغط الأقسام التي تم التقاطها. في كل من Android 11 وAndroid 12، ينطبق ما يلي:

  • تعد تحديثات A/B الافتراضية سلسة مثل تحديثات A/B. تعمل تحديثات A/B الافتراضية على تقليل الوقت الذي يكون فيه الجهاز غير متصل بالإنترنت وغير قابل للاستخدام.
  • يمكن التراجع عن تحديثات A/B الافتراضية. إذا فشل تشغيل نظام التشغيل الجديد، فستعود الأجهزة تلقائيًا إلى الإصدار السابق.
  • تستخدم تحديثات A/B الافتراضية الحد الأدنى من المساحة الإضافية عن طريق تكرار الأقسام التي يستخدمها محمل التشغيل فقط. يتم أخذ لقطات للأقسام الأخرى القابلة للتحديث.

الخلفية والمصطلحات

يحدد هذا القسم المصطلحات ويصف التقنية التي تدعم A/B الظاهري.

مخطط الجهاز

Device-mapper عبارة عن طبقة كتلة افتراضية لنظام التشغيل Linux تُستخدم غالبًا في Android. مع الأقسام الديناميكية ، تكون الأقسام مثل /system عبارة عن مجموعة من الأجهزة ذات الطبقات:

  • يوجد في الجزء السفلي من المكدس القسم الفائق الفعلي (على سبيل المثال، /dev/block/by-name/super ).
  • يوجد في المنتصف جهاز dm-linear ، يحدد الكتل الموجودة في القسم الفائق التي تشكل القسم المحدد. يظهر هذا كـ /dev/block/mapper/system_[a|b] على جهاز A/B، أو /dev/block/mapper/system على جهاز غير A/B.
  • في الجزء العلوي يوجد جهاز dm-verity ، تم إنشاؤه للأقسام التي تم التحقق منها. يتحقق هذا الجهاز من توقيع الكتل الموجودة على الجهاز dm-linear بشكل صحيح. يظهر كـ /dev/block/mapper/system-verity وهو مصدر نقطة تحميل /system .

يوضح الشكل 1 الشكل الذي تبدو عليه المكدس الموجود أسفل نقطة تثبيت /system .

Partition stacking underneath system

الشكل 1. كومة تحت نقطة تحميل /النظام

dm-لقطة

يعتمد Virtual A/B على dm-snapshot ، وهي وحدة نمطية لجهاز معين لالتقاط صورة لحالة جهاز التخزين. عند استخدام dm-snapshot ، هناك أربعة أجهزة قيد التشغيل:

  • الجهاز الأساسي هو الجهاز الذي تم التقاطه. في هذه الصفحة، يكون الجهاز الأساسي دائمًا قسمًا ديناميكيًا، مثل النظام أو البائع.
  • جهاز النسخ عند الكتابة (COW)، لتسجيل التغييرات على الجهاز الأساسي. يمكن أن يكون بأي حجم، ولكن يجب أن يكون كبيرًا بما يكفي لاستيعاب جميع التغييرات التي تطرأ على الجهاز الأساسي.
  • يتم إنشاء جهاز اللقطة باستخدام هدف snapshot . تتم كتابة عمليات الكتابة إلى جهاز اللقطة إلى جهاز COW. تتم القراءة من جهاز اللقطة إما من الجهاز الأساسي أو من جهاز COW، اعتمادًا على ما إذا كانت البيانات التي يتم الوصول إليها قد تم تغييرها بواسطة اللقطة.
  • يتم إنشاء الجهاز الأصلي باستخدام هدف snapshot-origin . يقرأ إلى الجهاز الأصلي القراءة مباشرة من الجهاز الأساسي. يكتب إلى الجهاز الأصلي ويكتب مباشرة إلى الجهاز الأساسي، ولكن يتم نسخ البيانات الأصلية احتياطيًا عن طريق الكتابة إلى جهاز COW.

Device mapping for dm-snapshot

الشكل 2. تعيين الجهاز للقطة dm

لقطات مضغوطة

في نظام التشغيل Android 12 والإصدارات الأحدث، نظرًا لأن متطلبات المساحة على قسم /data يمكن أن تكون عالية، يمكنك تمكين اللقطات المضغوطة في الإصدار الخاص بك لتلبية متطلبات المساحة الأعلى لقسم /data .

يتم إنشاء لقطات A/B المضغوطة الافتراضية بناءً على المكونات التالية المتوفرة في نظام التشغيل Android 12 والإصدارات الأحدث:

  • dm-user ، وحدة kernel مشابهة لـ FUSE تسمح لمساحة المستخدمين بتنفيذ أجهزة الحظر.
  • snapuserd ، برنامج خفي لمساحة المستخدمين لتنفيذ تنسيق لقطة جديد.

هذه المكونات تمكن الضغط. يتم عرض التغييرات الضرورية الأخرى التي تم إجراؤها لتنفيذ إمكانات اللقطات المضغوطة في الأقسام التالية: تنسيق COW للقطات المضغوطة و dm-user و Snapuserd .

تنسيق COW للقطات المضغوطة

في نظام التشغيل Android 12 والإصدارات الأحدث، تستخدم اللقطات المضغوطة تنسيق COW. على غرار تنسيق kernel المدمج المستخدم للقطات غير المضغوطة، يحتوي تنسيق COW للقطات المضغوطة على أقسام بديلة من بيانات التعريف والبيانات. البيانات الوصفية للتنسيق الأصلي مسموحة فقط لعمليات الاستبدال : استبدل الكتلة X في الصورة الأساسية بمحتويات الكتلة Y في اللقطة. يعد تنسيق اللقطات المضغوطة COW أكثر تعبيرًا ويدعم العمليات التالية:

  • النسخ : يجب استبدال الكتلة X في الجهاز الأساسي بالمجموعة Y في الجهاز الأساسي.
  • استبدال : يجب استبدال الكتلة X الموجودة في الجهاز الأساسي بمحتويات الكتلة Y في اللقطة. كل من هذه الكتل مضغوطة بـ gz.
  • الصفر : يجب استبدال الكتلة X الموجودة في الجهاز الأساسي بجميع الأصفار.
  • XOR : يقوم جهاز COW بتخزين بايتات XOR المضغوطة بين الكتلة X والكتلة Y. (متوفر في Android 13 والإصدارات الأحدث.)

تتكون تحديثات OTA الكاملة من عمليات الاستبدال والصفر فقط. يمكن أن تحتوي تحديثات OTA المتزايدة أيضًا على عمليات نسخ .

مستخدم dm في Android 12

تمكن وحدة kernel dm-user userspace من تنفيذ أجهزة كتلة مخطط الجهاز. يقوم إدخال جدول dm-user بإنشاء جهاز متنوع ضمن /dev/dm-user/<control-name> . يمكن لعملية userspace استطلاع الجهاز لتلقي طلبات القراءة والكتابة من النواة. يحتوي كل طلب على مخزن مؤقت مرتبط بمساحة المستخدم إما لملءه (للقراءة) أو نشره (للكتابة).

توفر وحدة kernel dm-user واجهة جديدة مرئية للمستخدم للنواة والتي لا تشكل جزءًا من قاعدة كود kernel.org الأولية. وحتى يتم ذلك، تحتفظ Google بالحق في تعديل واجهة dm-user في Android.

snapuserd

يقوم مكون مساحة المستخدم snapuserd إلى dm-user بتطبيق ضغط A/B الظاهري.

في الإصدار غير المضغوط من Virtual A/B، (إما في Android 11 والإصدارات الأقدم، أو في Android 12 بدون خيار اللقطة المضغوطة)، يعد جهاز COW ملفًا أوليًا. عند تمكين الضغط، يعمل COW بدلاً من ذلك كجهاز dm-user ، وهو متصل بمثيل البرنامج snapuserd .

لا تستخدم النواة تنسيق COW الجديد. لذلك يقوم مكون snapuserd بترجمة الطلبات بين تنسيق Android COW وتنسيق kernel المدمج:

Snapuserd component translating requests between Android COW format and kernel built-in format

الشكل 3. رسم تخطيطي لتدفق snapuserd كمترجم بين تنسيقات Android وKernel COW

لا تحدث هذه الترجمة وإلغاء الضغط على القرص مطلقًا. يعترض مكون snapuserd عمليات القراءة والكتابة لـ COW التي تحدث في kernel، وينفذها باستخدام تنسيق Android COW.

ضغط XOR

بالنسبة للأجهزة التي تعمل بنظام التشغيل Android 13 والإصدارات الأحدث، تعمل ميزة ضغط XOR، التي يتم تمكينها افتراضيًا، على تمكين لقطات مساحة المستخدم من تخزين بايتات XOR المضغوطة بين الكتل القديمة والكتل الجديدة. عندما يتم تغيير عدد قليل فقط من وحدات البايت في الكتلة في تحديث Virtual A/B، يستخدم نظام تخزين ضغط XOR مساحة أقل من نظام التخزين الافتراضي لأن اللقطات لا تخزن بايتات كاملة بحجم 4K. يعد هذا الانخفاض في حجم اللقطة ممكنًا لأن بيانات XOR تحتوي على العديد من الأصفار ويكون ضغطها أسهل من بيانات الكتلة الأولية. على أجهزة Pixel، يؤدي ضغط XOR إلى تقليل حجم اللقطة بنسبة تتراوح بين 25% إلى 40%.

بالنسبة للأجهزة التي تقوم بالترقية إلى Android 13 والإصدارات الأحدث، يجب تمكين ضغط XOR. لمزيد من التفاصيل، راجع ضغط XOR .

عمليات ضغط A/B الافتراضية

يوفر هذا القسم تفاصيل حول عملية ضغط Virtual A/B المستخدمة في Android 13 وAndroid 12.

قراءة البيانات الوصفية (Android 12)

يتم إنشاء البيانات التعريفية بواسطة البرنامج الخفي snapuserd . البيانات التعريفية هي في المقام الأول تعيين لمعرفين، كل منهما 8 بايت، يمثلان القطاعات المراد دمجها. في dm-snapshot يطلق عليه disk_exception .

struct disk_exception {
    uint64_t old_chunk;
    uint64_t new_chunk;
};

يتم استخدام استثناء القرص عندما يتم استبدال جزء قديم من البيانات بجزء جديد.

يقرأ البرنامج snapuserd ملف COW الداخلي من خلال مكتبة COW ويقوم بإنشاء بيانات التعريف لكل عملية من عمليات COW الموجودة في ملف COW.

تبدأ عمليات قراءة البيانات التعريفية من dm-snapshot في النواة عند إنشاء جهاز dm- snapshot .

يوفر الشكل أدناه مخططًا تسلسليًا لمسار الإدخال/الإخراج لبناء البيانات التعريفية.

Sequence diagram, IO path for metadata construction

الشكل 4. تدفق التسلسل لمسار الإدخال/الإخراج في بناء البيانات التعريفية

الدمج (أندرويد 12)

بمجرد اكتمال عملية التمهيد، يضع محرك التحديث علامة على الفتحة باعتبارها تمهيدًا ناجحًا ويبدأ الدمج عن طريق تحويل هدف dm-snapshot إلى هدف dm-snapshot-merge .

يتنقل dm-snapshot عبر البيانات التعريفية ويبدأ عملية إدخال/إخراج مدمجة لكل استثناء من القرص. يتم عرض نظرة عامة عالية المستوى لمسار الإدخال/الإخراج للدمج أدناه.

Merge IO path

الشكل 5. نظرة عامة على مسار دمج الإدخال/الإخراج

إذا تمت إعادة تشغيل الجهاز أثناء عملية الدمج، فسيتم استئناف الدمج عند إعادة التشغيل التالية، وسيتم إكمال الدمج.

طبقات مخطط الجهاز

بالنسبة للأجهزة التي تعمل بنظام التشغيل Android 13 والإصدارات الأحدث، يتم تنفيذ عمليات دمج اللقطات واللقطات في ضغط A/B الظاهري بواسطة مكون مساحة المستخدم snapuserd . بالنسبة للأجهزة التي تقوم بالترقية إلى Android 13 والإصدارات الأحدث، يجب تمكين هذه الميزة. للحصول على التفاصيل، راجع دمج مساحة المستخدم .

فيما يلي وصف لعملية ضغط A/B الظاهري:

  1. يقوم إطار العمل بتثبيت قسم /system من جهاز dm-verity ، والذي يتم تكديسه أعلى جهاز dm-user . وهذا يعني أنه يتم توجيه كل إدخال/إخراج من نظام الملفات الجذر إلى dm-user .
  2. يقوم dm-user بتوجيه الإدخال/الإخراج إلى البرنامج الخفي لمساحة المستخدم snapuserd ، والذي يعالج طلب الإدخال/الإخراج.
  3. عند اكتمال عملية الدمج، يقوم إطار العمل بطي dm-verity أعلى dm-linear ( system_base ) ويزيل dm-user .

عملية ضغط A/B الافتراضية

الشكل 6. عملية ضغط A/B الافتراضية

يمكن مقاطعة عملية دمج اللقطات. إذا تمت إعادة تشغيل الجهاز أثناء عملية الدمج، فسيتم استئناف عملية الدمج بعد إعادة التشغيل.

التحولات الأولية

عند التشغيل باستخدام لقطات مضغوطة، يجب أن يبدأ init في المرحلة الأولى snapuserd لتركيب الأقسام. وهذا يطرح مشكلة: عندما يتم تحميل sepolicy وفرضه، يتم وضع snapuserd في سياق خاطئ، وتفشل طلبات القراءة الخاصة به، مع رفض selinux.

لمعالجة هذه المشكلة، يتم إجراء انتقالات snapuserd في خطوة القفل باستخدام init ، كما يلي:

  1. تقوم المرحلة الأولى init بتشغيل snapuserd من قرص ذاكرة الوصول العشوائي، وتحفظ واصف ملف مفتوح فيه في متغير بيئة.
  2. تقوم المرحلة الأولى init بتحويل نظام الملفات الجذر إلى قسم النظام، ثم تنفيذ نسخة النظام من init .
  3. تقرأ نسخة النظام من init sepolicy المدمجة في سلسلة.
  4. يقوم Init باستدعاء mlock() على جميع الصفحات المدعومة بنظام ext4. ثم يقوم بعد ذلك بإلغاء تنشيط جميع جداول مخطط الأجهزة لأجهزة اللقطات، ويوقف snapuserd . بعد ذلك يُمنع القراءة من الأقسام، لأن ذلك يسبب حالة توقف تام.
  5. باستخدام الواصف المفتوح لنسخة ramdisk من snapuserd ، يقوم init بإعادة تشغيل البرنامج الخفي باستخدام سياق selinux الصحيح. تتم إعادة تنشيط جداول مخطط الجهاز لأجهزة اللقطات.
  6. يستدعي الحرف الأول munlockall() - من الآمن إجراء عملية الإدخال/الإخراج مرة أخرى.

استخدام الفضاء

يوفر الجدول التالي مقارنة بين استخدام المساحة لآليات OTA المختلفة باستخدام أحجام نظام تشغيل Pixel وOTA.

تأثير الحجم غير أ/ب أ/ب الظاهري أ/ب افتراضي أ/ب (مضغوط)
صورة المصنع الأصلية 4.5 جيجابايت سوبر (صورة 3.8 جيجا + 700 ميجا محفوظة) 1 9 جيجابايت سوبر (3.8 جيجا + 700 ميجا محفوظة، لفتحتين) 4.5 جيجابايت سوبر (صورة 3.8 جيجا + 700 ميجا محفوظة) 4.5 جيجابايت سوبر (صورة 3.8 جيجا + 700 ميجا محفوظة)
أقسام ثابتة أخرى /مخبأ لا أحد لا أحد لا أحد
مساحة تخزين إضافية أثناء OTA (يتم إرجاع المساحة بعد تطبيق OTA) 1.4 جيجابايت على / البيانات 0 3.8 جيجابايت 2 على / البيانات 2.1 جيجابايت 2 على / البيانات
إجمالي مساحة التخزين المطلوبة لتطبيق OTA 5.9 جيجابايت 3 (سوبر وبيانات) 9 جيجا (سوبر) 8.3 جيجابايت 3 (سوبر وبيانات) 6.6 جيجا 3 (سوبر و داتا)

1 يشير إلى التخطيط المفترض بناءً على تعيين البكسل.

2 يفترض أن صورة النظام الجديد بنفس حجم الصورة الأصلية.

3 متطلبات المساحة عابرة حتى إعادة التشغيل.

لتنفيذ Virtual A/B، أو لاستخدام إمكانات اللقطات المضغوطة، راجع تنفيذ Virtual A/B