في نظام التشغيل Android 12، يحلّ GKI 2.0 محلّ أداة تخصيص ION باستخدام حزم DMA-BUF للأسباب التالية:
- الأمان: بما أنّ كل كومّة DMA-BUF هي جهاز أحرف منفصل، يمكن التحكّم في الوصول
إلى كل كومّة بشكل منفصل باستخدام سياسة الأمان. لم يكن هذا الإجراء
ممكنًا باستخدام ION لأنّ تخصيص الذاكرة من أي كومّة يتطلّب الوصول فقط إلى
جهاز
/dev/ion
. - ثبات ABI: على عكس ION، فإنّ واجهة IOCTL لإطار عمل "كومات DMA-BUF" ثابتة ABI لأنّها محفوظة في نواة Linux الأساسية.
- التوحيد: يقدّم إطار عمل "كومات DMA-BUF" واجهة برمجة تطبيقات معرّفة جيدًا. أتاحت شركة ION علامات مخصّصة ومعرّفات لأجزاء من الذاكرة التي منعت تطوير إطار عمل اختباري، وذلك لأنّ طريقة تنفيذ ION لكل جهاز يمكن أن تتصرف بشكل مختلف.
تم إيقاف الإصدار android12-5.10
من "النواة الشائعة لنظام التشغيل Android"
CONFIG_ION
في 1 آذار (مارس) 2021.
خلفية
في ما يلي مقارنة موجزة بين كومدات ION وDMA-BUF.
أوجه التشابه بين إطار عمل لقطات العناصر المتعدّدة في ION وDMA-BUF
- إنّ إطارَي عمل HEAP ION وDMA-BUF هما من برامج تصدير DMA-BUF المستندة إلى HEAP.
- ويسمح كلاهما لكل كومّة بتحديد موزّعها وعمليات DMA-BUF الخاصة بها.
- يكون أداء عملية التخصيص مشابهًا لأنّ كلا المخطّطَين يحتاجان إلى IOCTL واحد فقط للتخصيص.
الاختلافات بين إطار عمل كومدات ION وDMA-BUF
مجموعات ION | أكوام 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 المتعددة
برامج تشغيل kernel التي تنفِّذ أكوام ION
تسمح كل من كومدات ION وDMA-BUF لكل كومدة بتنفيذ موزّعي عناوين الذاكرة الخاصة بها وعمليات DMA-BUF. وبالتالي، يمكنك التبديل من تنفيذ كومّة ION إلى تنفيذ كومّة DMA-BUF باستخدام مجموعة مختلفة من واجهات برمجة التطبيقات لتسجيل الكومة. يعرض هذا الجدول واجهات برمجة التطبيقات لتسجيل كومّة ION وواجهات برمجة التطبيقات المقابلة لها لكومّة DMA-BUF.
مجموعات ION | أكوام 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 مع علامات أكوام الذاكرة الخاصة. لذلك، يجب تسجيل كلّ صيغة من ملف heap
بشكلٍ فردي باستخدام واجهة برمجة التطبيقات 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 المتعددة | عناصر ذاكرة العناصر المتعدّدة في DMA-BUF |
---|---|
struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)
|
|
برامج تشغيل النواة التي تستخدم رموز DMA-BUF
لا يلزم إجراء أي تغييرات لبرامج التشغيل التي تستورد ملفات 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()
API التي تأخذ قناعًا للمساحة التخزينية ووسيطة علامة، بواجهة برمجة التطبيقاتBufferAllocator::Alloc()
API التي تأخذ اسم مساحة تخزينية بدلاً من ذلك.
يوضّح هذا الجدول هذه التغييرات من خلال عرض كيفية تنفيذ 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 بربط اسم ملف ذاكرة heap
بمَعلمات ملف ذاكرة ION heap (اسم ملف الذاكرة أو القناع والأعلام) للسماح لتلك
الواجهات باستخدام عمليات التوزيع المستندة إلى الاسم. في ما يلي مثال على التخصيص بالاستناد إلى الاسم.
تتوفّر مستندات كل واجهة برمجة تطبيقات يوفّرها
libdmabufheap
. تعرض
المكتبة
أيضًا ملف رأس لاستخدامه من خلال عملاء C.
مرجع تنفيذ Gralloc
يستخدم تطبيق Hikey960 gralloc libdmabufheap
، لذا يمكنك استخدامه كأحد مراجع تنفيذ.
إضافات ueventd المطلوبة
بالنسبة إلى أيّ مجموعات جديدة من DMA-BUF خاصة بالجهاز تم إنشاؤها، أضِف إدخالًا جديدًا إلىملفueventd.rc
الجهاز.
يوضّح مثال إعداد ueventd للتوافق مع مجموعات DMA-BUF
كيفية إجراء ذلك في ذاكرة التخزين المؤقت لنظام DMA-BUF.
إضافات sepolicy المطلوبة
أضِف أذونات سياسة الأمان (sepolicy) لتفعيل برنامج عميل مساحة المستخدم للوصول إلى ملف ذاكرة HEAP جديد في DMA-BUF. يعرِض مثال إضافة الأذونات المطلوبة أذونات سياسة الأمان التي تم إنشاؤها لبرامج مختلفة بهدف الوصول إلى ذاكرة نظام DMA-BUF.
الوصول إلى مجموعات ذاكرة المورّد من رمز الإطار
لضمان الامتثال لبروتوكول Treble، لا يمكن لرمز إطار العمل التخصيص إلا من فئات تمت الموافقة عليها مسبقًا من أكواد الموردين.
استنادًا إلى الملاحظات التي تلقّتها Google من الشركاء، حدّدت Google فئتين من مكبّرات الذاكرة الخاصة بالمورّدين التي يجب الوصول إليها من رمز إطار العمل:
- الحِزم التي تستند إلى حزمة النظام مع تحسينات الأداء الخاصة بالجهاز أو المنظومة على الرقاقة
- وحدات مخصصة لتخصيصها من الذاكرة المحمية
مجموعات الذاكرة المؤقتة المستندة إلى مجموعة الذاكرة المؤقتة للنظام مع تحسينات الأداء الخاصة بالجهاز أو المنظومة على الرقاقة
لدعم حالة الاستخدام هذه، يمكن إلغاء تنفيذ كومّة نظام كومّة DMA-BUF التلقائية.
- تم إيقاف
CONFIG_DMABUF_HEAPS_SYSTEM
فيgki_defconfig
للسماح له بأن يصبح وحدة مورِّد. - تضمن اختبارات الامتثال لنظام VTS توفُّر الحِزمة في
/dev/dma_heap/system
. وتتحقّق الاختبارات أيضًا من إمكانية تخصيص كومة الذاكرة المؤقتة من أنّه يمكن تخصيص واصف الملف الذي تم إرجاعه (fd
) من خلال مساحة المستخدم (mmapped).
تنطبق النقاط السابقة أيضًا على الصيغة غير المخزّنة من ذاكرة التخزين المؤقت للنظام، على الرغم من أنّ وجودها ليس إلزاميًا للأجهزة المتسقة تمامًا مع عمليات I/O.
مجموعات الذاكرة التي يجب تخصيصها من الذاكرة المحمية
يجب أن تكون عمليات تنفيذ "المساحة المحجوزة الآمنة" خاصة بالمورّد لأنّ "النواة المشتركة" في Android لا تتوافق مع تنفيذ "المساحة المحجوزة الآمنة" العام.
- سجِّل عمليات التنفيذ الخاصة بالمورّد على أنّها
/dev/dma_heap/system-secure<vendor-suffix>
. - إنّ عمليات تنفيذ الحِزم هذه اختيارية.
- وفي حال توفّر لقطات لأجزاء من الذاكرة، تضمن اختبارات VTS إمكانية إجراء التخصيصات منها.
- يتم منح مكوّنات إطار العمل إذن الوصول إلى هذه الحِزم لكي تتمكّن من تفعيل استخدام الحِزم من خلال واجهة HAL لبرنامج الترميز 2 أو واجهات HAL غير المرتبطة بالربط لعملية التنفيذ نفسها. ومع ذلك، لا يمكن أن تعتمد ميزات إطار عمل Android العامة على هذه الميزات بسبب اختلاف تفاصيل تنفيذها. في حال تمت إضافة تنفيذ مجمع تخزين آمن عام إلى "النواة المشتركة لنظام التشغيل Android" في المستقبل، يجب أن يستخدم ABI مختلفًا لتجنّب حدوث تعارضات مع الأجهزة التي يتم ترقيتها.
أداة تخصيص ترميز 2 لحِزم DMA-BUF
يتوفّر مخصّص تنسيق ترميز 2 لواجهة كومبوتات DMA-BUF في AOSP.
تتوفّر واجهة متجر المكوّنات التي تسمح بتحديد مَعلمات الذاكرة المحجوزة للبرامج من HAL C2 مع أداة تخصيص الذاكرة المحجوزة للبرامج 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
، عدِّل ملفات الإنشاء
لربطها بـ 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()
باستخدام اسم الحِزمة المناسب.
نوع التخصيص | ليبيون | 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: أنشئ أذونات سياسة الأمان المطلوبة لكي يتمكّن العميل من الوصول إلى كومات DMA-BUF الجديدة. أصبح العميل مجهّزًا بالكامل الآن للتخصيص من كومة الذاكرة المؤقتة DMA-BUF الجديدة.
الخطوة 6: يُرجى التحقّق من إجراء عمليات التخصيص من الذاكرة المجمّعة الجديدة في DMA-BUF من خلال مراجعة logcat.
الخطوة 7: إيقاف كومة ION my_heap
في النواة. إذا لم يكن رمز العميل
يحتاج إلى إتاحة ترقية الأجهزة (التي قد لا تتيح نواتها سوى كومدات ION
)، يمكنك أيضًا إزالة عمليات استدعاء MapNameToIonHeap()
.