في نظام التشغيل Android 12، يحلّ GKI 2.0 محلّ أداة تخصيص ION باستخدام مجموعات DMA-BUF للأسباب التالية:
- الأمان: بما أنّ كل كومة DMA-BUF هي جهاز أحرف منفصل، يمكن التحكّم في الوصول إلى كل كومة بشكل منفصل باستخدام sepolicy. لم يكن ذلك ممكنًا باستخدام ION لأنّ التخصيص من أي كومة كان يتطلّب فقط الوصول إلى جهاز
/dev/ion
. - توافق واجهة التطبيق الثنائية (ABI): بخلاف ION، تتوافق واجهة IOCTL لإطار عمل حزم DMA-BUF مع واجهة التطبيق الثنائية لأنّه يتم صيانتها في نواة Linux الرئيسية.
- التوحيد: يوفّر إطار عمل أكوام DMA-BUF واجهة برمجة تطبيقات موحّدة ومحدّدة جيدًا. سمحت ION بالعلامات المخصّصة ومعرّفات الذاكرة المؤقتة التي منعت تطوير إطار عمل مشترك للاختبار، لأنّ تنفيذ ION على كل جهاز يمكن أن يختلف.
تم إيقاف فرع android12-5.10
من النواة المشتركة لنظام التشغيل Android
CONFIG_ION
في 1 مارس 2021.
الخلفية
في ما يلي مقارنة موجزة بين أكوام ION وأكوام DMA-BUF.
أوجه التشابه بين إطار عمل ION وDMA-BUF heaps
- إنّ إطارَي عمل ION وDMA-BUF هما أدوات تصدير DMA-BUF مستندة إلى الذاكرة المكدّسة.
- يتيح كلاهما لكل كومة تحديد أداة التخصيص وعمليات DMA-BUF الخاصة بها.
- يكون أداء التخصيص متشابهًا لأنّ كلا المخططَين يحتاجان إلى IOCTL واحد للتخصيص.
الاختلافات بين إطار عمل أكوام ION وDMA-BUF
ION heaps | مجموعات DMA-BUF |
---|---|
يتم إجراء جميع عمليات تخصيص ION باستخدام /dev/ion .
|
كل كومة DMA-BUF هي جهاز أحرف متوفر في /dev/dma_heap/<heap_name> .
|
يتوافق ION مع العلامات الخاصة بالذاكرة المؤقتة. | لا تتوافق أكوام DMA-BUF مع العلامات الخاصة بالأكوام. بدلاً من ذلك، يتم إجراء كل نوع مختلف من عمليات التخصيص من كومة مختلفة. على سبيل المثال، إنّ صيغ ذاكرة التخزين المؤقت وذاكرة التخزين المؤقت غير المخزّنة مؤقتًا لنظام الذاكرة المكدّسة هي ذاكرات مكدّسة منفصلة تقع في /dev/dma_heap/system و/dev/dma_heap/system_uncached .
|
يجب تحديد معرّف/قناع الذاكرة المؤقتة والعلامات للتخصيص. | يُستخدَم اسم الذاكرة المؤقتة للتخصيص. |
تدرج الأقسام التالية المكوّنات التي تتعامل مع ION وتوضّح كيفية نقلها إلى إطار عمل أكوام DMA-BUF.
نقل برامج تشغيل النواة من ION إلى أكوام DMA-BUF
برامج تشغيل النواة التي تنفّذ أكوام ION
تتيح كلّ من حزمتَي ION وDMA-BUF لكل حزمة تنفيذ أدوات التخصيص وعمليات DMA-BUF الخاصة بها. وبالتالي، يمكنك التبديل من تنفيذ حزمة ION إلى تنفيذ حزمة DMA-BUF باستخدام مجموعة مختلفة من واجهات برمجة التطبيقات لتسجيل الحزمة. يعرض هذا الجدول واجهات برمجة التطبيقات الخاصة بتسجيل مساحة التخزين المؤقت ION ومساحات التخزين المؤقت DMA-BUF المكافئة لها.
ION heaps | مجموعات DMA-BUF |
---|---|
void ion_device_add_heap(struct ion_heap *heap)
|
struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
|
void ion_device_remove_heap(struct ion_heap *heap)
|
void dma_heap_put(struct dma_heap *heap);
|
لا تتوافق أكوام DMA-BUF مع العلامات الخاصة بالأكوام. لذا، يجب تسجيل كل صيغة من صيغ الذاكرة المؤقتة بشكل منفصل باستخدام واجهة برمجة التطبيقات dma_heap_add()
. لتسهيل مشاركة الرموز، ننصحك بتسجيل جميع أشكال الذاكرة المؤقتة نفسها ضمن برنامج التشغيل نفسه.
يوضّح مثال dma-buf: system_heap عملية تنفيذ المتغيرات المخزّنة مؤقتًا وغير المخزّنة مؤقتًا لمساحة التخزين المؤقت في النظام.
استخدِم dma-buf: heaps: example template لإنشاء مجموعة DMA-BUF من البداية.
برامج تشغيل النواة التي تخصّص مباشرةً من حِزم ION
يوفّر إطار عمل أكوام DMA-BUF أيضًا واجهة تخصيص للعملاء داخل النواة. بدلاً من تحديد قناع الذاكرة المؤقتة وعلاماتها لاختيار نوع التخصيص، تستخدم الواجهة التي توفّرها الذاكرات المؤقتة DMA-BUF اسم الذاكرة المؤقتة كإدخال.
يوضّح ما يلي واجهة برمجة التطبيقات لتخصيص ION داخل النواة وواجهات برمجة التطبيقات المكافئة لتخصيص الذاكرة المجمّعة DMA-BUF. يمكن لبرامج تشغيل النواة استخدام واجهة برمجة التطبيقات dma_heap_find()
للاستعلام عن توفّر كومة. تعرض واجهة برمجة التطبيقات مؤشرًا إلى مثيل من
struct dma_heap، والذي يمكن بعد ذلك تمريره كمعلَمة إلى واجهة برمجة التطبيقات
dma_heap_buffer_alloc()
.
ION heaps | مجموعات DMA-BUF |
---|---|
struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)
|
|
برامج تشغيل النواة التي تستخدم DMA-BUFs
لا يلزم إجراء أي تغييرات على برامج التشغيل التي تستورد فقط DMA-BUF، لأنّ المخزن المؤقت المخصّص من كومة ION يتصرف تمامًا مثل المخزن المؤقت المخصّص من كومة DMA-BUF مكافئة.
نقل برامج ION في مساحة المستخدم إلى أكوام DMA-BUF
لتسهيل عملية الانتقال على برامج ION التي تعمل في مساحة المستخدم، تتوفّر مكتبة تجريدية باسم
libdmabufheap
. يتيح libdmabufheap
إمكانية التخصيص في حزم DMA-BUF
وحزم ION. يتحقّق أولاً مما إذا كان هناك كومة DMA-BUF بالاسم المحدّد، وإذا لم يكن هناك كومة، يتم الرجوع إلى كومة ION مكافئة، إذا كانت متوفرة.
على العملاء إعداد عنصر BufferAllocator
أثناء عملية الإعداد بدلاً من فتح /dev/ion using
ion_open()
. ويرجع ذلك إلى أنّ واصفات الملفات التي يتم إنشاؤها من خلال فتح /dev/ion
و/dev/dma_heap/<heap_name>
تتم إدارتها داخليًا بواسطة العنصر BufferAllocator
.
للانتقال من libion
إلى libdmabufheap
، عدِّل سلوك العملاء على النحو التالي:
- تتبَّع اسم الذاكرة المؤقتة التي سيتم استخدامها للتخصيص بدلاً من معرّف/قناع العنوان الرئيسي وعلامة الذاكرة المؤقتة.
- استبدِل واجهة برمجة التطبيقات
ion_alloc_fd()
التي تتلقّى قناعًا للذاكرة المكدّسة ووسيط علامة، بواجهة برمجة التطبيقاتBufferAllocator::Alloc()
التي تتلقّى اسم ذاكرة مكدّسة بدلاً من ذلك.
يوضّح هذا الجدول هذه التغييرات من خلال عرض كيفية تنفيذ libion
وlibdmabufheap
عملية تخصيص غير مخزّنة مؤقتًا لمساحة في الذاكرة المخصّصة للنظام.
نوع التخصيص | libion | libdmabufheap |
---|---|---|
التخصيص المخزّن مؤقتًا من الذاكرة الرئيسية للنظام | ion_alloc_fd(ionfd, size, 0, ION_HEAP_SYSTEM, ION_FLAG_CACHED, &fd)
|
allocator->Alloc("system", size)
|
التخصيص غير المخزّن مؤقتًا من مجموعة البيانات المؤقتة للنظام | ion_alloc_fd(ionfd, size, 0, ION_HEAP_SYSTEM, 0, &fd)
|
allocator->Alloc("system-uncached", size)
|
إنّ
متغير كومة النظام غير المخزّن مؤقتًا
في انتظار الموافقة من المصدر، ولكنّه يشكّل جزءًا من فرع android12-5.10
.
ولإتاحة ترقية الأجهزة، يسمح MapNameToIonHeap()
API بربط اسم الذاكرة المؤقتة بمعلَمات الذاكرة المؤقتة ION (اسم الذاكرة المؤقتة أو القناع والعلامات) للسماح لهذه الواجهات باستخدام عمليات التخصيص المستندة إلى الاسم. في ما يلي مثال على التخصيص المستند إلى الاسم.
تتوفّر مستندات كل واجهة برمجة تطبيقات يعرضها
libdmabufheap
. توفّر
المكتبة
أيضًا ملف عنوان يمكن أن تستخدمه برامج C.
التنفيذ المرجعي لـ Gralloc
يستخدم تنفيذ gralloc في Hikey960 libdmabufheap
، لذا يمكنك استخدامه كـ
تنفيذ مرجعي.
الإضافات المطلوبة إلى ueventd
بالنسبة إلى أي حِزم DMA-BUF جديدة خاصة بالجهاز يتم إنشاؤها، أضِف إدخالاً جديدًا إلى ملف ueventd.rc
الخاص بالجهاز.
يوضّح مثال إعداد ueventd لدعم أكوام DMA-BUF كيفية تنفيذ ذلك لكومة نظام DMA-BUF.
الإضافات المطلوبة إلى sepolicy
أضِف أذونات sepolicy للسماح لأحد برامج العميل في مساحة المستخدم بالوصول إلى مجموعة جديدة من DMA-BUF. يوضّح مثال إضافة الأذونات المطلوبة أذونات sepolicy التي تم إنشاؤها لبرامج مختلفة للوصول إلى مساحة التخزين المؤقت لنظام DMA-BUF.
الوصول إلى حِزم المورّدين من رمز إطار العمل
لضمان التوافق مع Treble، لا يمكن لرمز إطار العمل التخصيص إلا من فئات معتمدة مسبقًا من حِزم المورّدين.
استنادًا إلى الملاحظات الواردة من الشركاء، حدّدت Google فئتَين من حِزم المورّدين التي يجب الوصول إليها من رمز إطار العمل:
- حِزم تستند إلى حزمة النظام مع تحسينات الأداء الخاصة بالجهاز أو المنظومة على الرقاقة (SoC).
- مساحات التخزين التي سيتم تخصيصها من الذاكرة المحمية
حِزم تستند إلى حزمة النظام مع تحسينات الأداء الخاصة بالجهاز أو المنظومة على الرقاقة (SoC)
ولإتاحة حالة الاستخدام هذه، يمكن إلغاء تنفيذ الذاكرة المؤقتة التلقائية DMA-BUF في النظام.
- يتم إيقاف
CONFIG_DMABUF_HEAPS_SYSTEM
فيgki_defconfig
ليكون وحدة مورِّد. - تضمن اختبارات الامتثال لنظام VTS توفّر الكومة في
/dev/dma_heap/system
. تتحقّق الاختبارات أيضًا من إمكانية تخصيص الذاكرة المؤقتة من الذاكرة، ومن إمكانية ربط واصف الملف الذي تم عرضه (fd
) بالذاكرة (mmapped) من مساحة المستخدم.
تنطبق النقاط السابقة أيضًا على المتغير غير المخزّن مؤقتًا لمساحة التخزين المؤقت للنظام، على الرغم من أنّ وجوده ليس إلزاميًا للأجهزة المتوافقة تمامًا مع عمليات الإدخال والإخراج.
المساحات المخصّصة للذاكرة المحمية
يجب أن تكون عمليات تنفيذ الذاكرة المؤقتة الآمنة خاصة بالمورّد لأنّ نواة Android المشتركة لا تتوافق مع عملية تنفيذ عامة للذاكرة المؤقتة الآمنة.
- سجِّل عمليات التنفيذ الخاصة بالمورّد على أنّها
/dev/dma_heap/system-secure<vendor-suffix>
. - تكون عمليات تنفيذ الكومة هذه اختيارية.
- إذا كانت الحزم موجودة، تضمن اختبارات VTS إمكانية إجراء عمليات تخصيص منها.
- يتم توفير إمكانية الوصول إلى هذه الذاكرات المجمّعة لمكوّنات إطار العمل حتى تتمكّن من تفعيل استخدام الذاكرات المجمّعة من خلال Codec2 HAL/non-binderized، وHALs التي تعمل في العملية نفسها. ومع ذلك، لا يمكن أن تعتمد ميزات إطار عمل Android العامة عليها بسبب اختلاف تفاصيل التنفيذ. إذا تمت إضافة تنفيذ عام لـ "كومة آمنة" إلى "نواة Android المشتركة" في المستقبل، يجب أن تستخدم واجهة ثنائية مختلفة لتجنُّب حدوث تعارضات عند ترقية الأجهزة.
أداة تخصيص برنامج الترميز 2 لمجموعات DMA-BUF
يتوفّر في AOSP مخصّص codec2 لمساحات الذاكرة المؤقتة DMA-BUF الخاصة بالواجهة.
تتوفّر واجهة متجر المكوّنات التي تتيح تحديد مَعلمات الذاكرة المؤقتة من C2 HAL مع أداة تخصيص الذاكرة المؤقتة C2 DMA-BUF.
نموذج لتدفّق الانتقال لمجموعة ION
لتسهيل عملية الانتقال من ION إلى أكوام DMA-BUF، يتيح libdmabufheap
التبديل بين أكوام الذاكرة واحدًا تلو الآخر. توضّح الخطوات التالية سير عمل مقترَحًا
لنقل حزمة ION غير قديمة باسم my_heap
تتوافق مع علامة واحدة،
وهي ION_FLAG_MY_FLAG
.
الخطوة 1: إنشاء مكافئات لمساحة ION في إطار عمل DMA-BUF في هذا المثال، بما أنّ حزمة ION my_heap
تتيح استخدام العلامة ION_FLAG_MY_FLAG
، نسجّل حزمتَي DMA-BUF على النحو التالي:
- يتطابق سلوك
my_heap
تمامًا مع سلوك حزمة ION مع إيقاف العلامةION_FLAG_MY_FLAG
. - يتطابق سلوك
my_heap_special
تمامًا مع سلوك حزمة ION مع تفعيل العلامةION_FLAG_MY_FLAG
.
الخطوة 2: أنشئ تغييرات ueventd لحزمتَي my_heap
وmy_heap_special
الجديدتَين من DMA-BUF. في هذه المرحلة، تظهر الذاكرات المؤقتة على النحو التالي:
/dev/dma_heap/my_heap
و/dev/dma_heap/my_heap_special
، مع
الأذونات المقصودة.
الخطوة 3: بالنسبة إلى العملاء الذين يخصّصون من my_heap
، عدِّل ملفات makefile الخاصة بهم
لربطها بـ libdmabufheap
. أثناء عملية تهيئة العميل، أنشئ مثيلاً لكائن BufferAllocator
واستخدِم واجهة برمجة التطبيقات MapNameToIonHeap()
لربط تركيبة <ION heap name/mask, flag>
بأسماء أكوام DMA-BUF المكافئة.
مثلاً:
allocator->MapNameToIonHeap("my_heap_special" /* name of DMA-BUF heap */, "my_heap" /* name of the ION heap */, ION_FLAG_MY_FLAG /* ion flags */ )
بدلاً من استخدام واجهة برمجة التطبيقات MapNameToIonHeap()
مع مَعلمتَي الاسم والعلامة، يمكنك إنشاء عملية الربط من <ION heap mask, flag>
إلى أسماء مكدّس DMA-BUF المكافئ من خلال ضبط مَعلمة اسم مكدّس ION على قيمة فارغة.
الخطوة 4: استبدِل استدعاءات ion_alloc_fd()
بـ BufferAllocator::Alloc()
باستخدام اسم الذاكرة المؤقتة المناسب.
نوع التخصيص | libion | libdmabufheap |
---|---|---|
تخصيص من my_heap مع إزالة العلامة ION_FLAG_MY_FLAG
|
ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP, 0, &fd)
|
allocator->Alloc("my_heap", size)
|
تخصيص من my_heap مع ضبط العلامة
ION_FLAG_MY_FLAG
|
ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP,
ION_FLAG_MY_FLAG, &fd)
|
allocator->Alloc("my_heap_special", size)
|
في هذه المرحلة، يكون البرنامج الوكيل صالحًا للاستخدام، ولكنّه لا يزال يخصّص الذاكرة من حزمة ION لأنّه لا يملك أذونات sepolicy المطلوبة لفتح حزمة DMA-BUF.
الخطوة 5: إنشاء أذونات sepolicy المطلوبة ليتمكّن البرنامج من الوصول إلى مساحات الذاكرة المؤقتة الجديدة DMA-BUF. أصبح العميل الآن مجهّزًا بالكامل لتخصيص الذاكرة من مجموعة DMA-BUF الجديدة.
الخطوة 6: تأكَّد من أنّ عمليات التخصيص تتم من حزمة DMA-BUF الجديدة من خلال فحص logcat.
الخطوة 7: أوقِف حزمة ION my_heap
في النواة. إذا لم يكن رمز العميل بحاجة إلى إتاحة ترقية الأجهزة (التي قد لا تتيح إلا حزم ION)، يمكنك أيضًا إزالة استدعاءات MapNameToIonHeap()
.