Google is committed to advancing racial equity for Black communities. See how.
ترجمت واجهة Cloud Translation API‏ هذه الصفحة.
Switch to English

باستخدام Binder IPC

تصف هذه الصفحة التغييرات التي تم إجراؤها على برنامج تشغيل الرابط في Android 8 ، وتوفر تفاصيل حول استخدام Binder IPC ، وتسرد سياسة SELinux المطلوبة.

التغييرات على سائق الموثق

بدءًا من Android 8 ، يتواصل الآن إطار عمل Android و HALs مع بعضهما البعض باستخدام Binder. نظرًا لأن هذا الاتصال يزيد بشكل كبير من حركة مرور البيانات Binder ، يشتمل Android 8 على العديد من التحسينات المصممة للحفاظ على سرعة Binder IPC. يجب أن يندمج موردو SoC ومصنعي المعدات الأصلية مباشرةً من الفروع ذات الصلة من android-4.4 و android-4.9 والإصدارات الأحدث من kernel / المشروع المشترك .

مجالات موثق متعددة (سياقات)

مشترك 4.4 وما فوق ، بما في ذلك المنبع

لتقسيم حركة مرور الرابط بشكل واضح بين إطار العمل (مستقل عن الجهاز) ورمز البائع (الخاص بالجهاز) ، قدم Android 8 مفهوم سياق الرابط. يحتوي كل سياق رابط على عقدة الجهاز الخاصة به ومدير السياق (الخدمة) الخاص به. لا يمكنك الوصول إلى مدير السياق إلا من خلال عقدة الجهاز التي ينتمي إليها ، وعند تمرير عقدة رابط عبر سياق معين ، لا يمكن الوصول إليها من نفس السياق إلا من خلال عملية أخرى ، وبالتالي عزل المجالات تمامًا عن بعضها البعض. للحصول على تفاصيل حول الاستخدام ، راجع vndbinder و vndservicemanager .

جمع مبعثر

مشترك - 4.4 وما فوق ، بما في ذلك المنبع

في الإصدارات السابقة من Android ، تم نسخ كل جزء من البيانات في مكالمة Binder ثلاث مرات:

  • مرة واحدة لتسلسلها في Parcel في عملية الاستدعاء
  • مرة واحدة في برنامج تشغيل kernel لنسخ Parcel إلى العملية المستهدفة
  • مرة واحدة لإلغاء تسلسل Parcel في العملية المستهدفة

يستخدم Android 8 تحسين التجميع المبعثر لتقليل عدد النسخ من 3 إلى 1. بدلاً من تسلسل البيانات في Parcel أولاً ، تظل البيانات في هيكلها الأصلي وتخطيط الذاكرة ويقوم السائق على الفور بنسخها إلى العملية المستهدفة. بعد أن تكون البيانات في العملية المستهدفة ، يكون الهيكل وتخطيط الذاكرة متماثلين ويمكن قراءة البيانات دون الحاجة إلى نسخة أخرى.

قفل دقيق الحبيبات

مشترك - 4.4 وما فوق ، بما في ذلك المنبع

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

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

بعد تحديد المشكلات الصغيرة في تنفيذ القفل الدقيق ، ابتكرنا حلاً محسنًا بهندسة قفل مختلفة وأرسلنا التغييرات في جميع فروع kernel الشائعة. نواصل اختبار هذا التنفيذ على عدد كبير من الأجهزة المختلفة ؛ نظرًا لأننا غير مدركين لأي مشكلات معلقة ، فهذا هو التنفيذ الموصى به للأجهزة المشحونة بنظام Android 8.

توريث الأولوية في الوقت الحقيقي

Common-4.4 و Common-4.9 (المنبع قريبًا)

يدعم برنامج تشغيل الموثق دائمًا الميراث ذي الأولوية الجيدة. نظرًا لأن عددًا متزايدًا من العمليات في Android يتم تشغيلها بأولوية في الوقت الفعلي ، فمن المنطقي في بعض الحالات الآن أنه إذا قام مؤشر ترابط في الوقت الفعلي بإجراء مكالمة Binder ، فإن مؤشر الترابط في العملية التي تتعامل مع هذا الاستدعاء يعمل أيضًا في أولوية الوقت الحقيقي . لدعم حالات الاستخدام هذه ، ينفذ Android 8 الآن توريث الأولوية في الوقت الفعلي في برنامج تشغيل Binder.

بالإضافة إلى توريث الأولوية على مستوى المعاملة ، يسمح توريث أولوية العقدة للعقدة (كائن خدمة الموثق) بتحديد الحد الأدنى من الأولوية التي يجب عندها تنفيذ المكالمات إلى هذه العقدة. تدعم الإصدارات السابقة من Android بالفعل توريث أولوية العقدة بقيم لطيفة ، لكن Android 8 يضيف دعمًا لتوريث سياسات الجدولة في الوقت الفعلي.

تغييرات مساحة المستخدمين

يتضمن Android 8 جميع تغييرات مساحة المستخدمين المطلوبة للعمل مع برنامج تشغيل الموثق الحالي في النواة المشتركة مع استثناء واحد: التطبيق الأصلي لتعطيل توريث الأولوية في الوقت الحقيقي لـ /dev/binder استخدم ioctl . قام التطوير اللاحق بتحويل التحكم في الوراثة ذات الأولوية إلى طريقة أكثر دقة لكل وضع رابط (وليس لكل سياق). وبالتالي ، فإن ioctl ليس في فرع Android الشائع ويتم تقديمه بدلاً من ذلك في نواتنا المشتركة .

يتمثل تأثير هذا التغيير في تعطيل توريث الأولوية في الوقت الفعلي افتراضيًا لكل عقدة. وجد فريق أداء Android أنه من المفيد تمكين توريث الأولوية في الوقت الفعلي لجميع العقد في مجال hwbinder . لتحقيق نفس التأثير ، اختر هذا التغيير في مساحة المستخدمين.

SHAs للنواة المشتركة

للحصول على التغييرات اللازمة لبرنامج تشغيل Binder ، قم بالمزامنة مع SHA المناسب:

  • عام 3.18
    cc8b90c121de ANDROID: Binder: لا تتحقق من أذونات prio عند الاستعادة.
  • عام - 4.4
    76b376eac7a2 ANDROID: Binder: لا تتحقق من أذونات prio عند الاستعادة.
  • عام 4.9
    ecd972d4f9b5 ANDROID: Binder: لا تتحقق من أذونات prio عند الاستعادة.

باستخدام Binder IPC

من الناحية التاريخية ، استخدمت عمليات البائعين اتصال بين عمليات الربط (IPC) للتواصل. في Android 8 ، تصبح عقدة الجهاز /dev/binder حصرية لعمليات إطار العمل ، مما يعني أن عمليات البائع لم تعد قادرة على الوصول إليها. يمكن لعمليات البائع الوصول إلى /dev/hwbinder ، ولكن يجب تحويل واجهات AIDL الخاصة بهم لاستخدام HIDL. بالنسبة للبائعين الذين يرغبون في الاستمرار في استخدام واجهات AIDL بين عمليات البائعين ، فإن Android يدعم Binder IPC كما هو موضح أدناه.

فندبيندر

يدعم Android 8 مجالًا جديدًا يستخدمه البائعون ، ويمكن الوصول إليه باستخدام /dev/vndbinder بدلاً من /dev/binder . مع إضافة /dev/vndbinder ، أصبح لدى Android الآن نطاقات IPC الثلاثة التالية:

مجال IPC وصف
/dev/binder IPC بين عمليات الإطار / التطبيق مع واجهات AIDL
/dev/hwbinder IPC بين عمليات الإطار / البائع مع واجهات HIDL
IPC بين عمليات البائع مع واجهات HIDL
/dev/vndbinder IPC بين عمليات البائع / البائع باستخدام واجهات AIDL

لكي يظهر /dev/vndbinder ، تأكد من تعيين عنصر تكوين kernel CONFIG_ANDROID_BINDER_DEVICES على "binder,hwbinder,vndbinder" (هذا هو "binder,hwbinder,vndbinder" الافتراضي في أشجار kernel الشائعة في Android).

عادةً ، لا تفتح عمليات البائع برنامج تشغيل الموثق مباشرةً وبدلاً من ذلك ترتبط libbinder ، والتي تفتح برنامج تشغيل Binder. تؤدي إضافة طريقة لـ ::android::ProcessState() تحديد برنامج تشغيل الموثق لـ libbinder . يجب أن تستدعي عمليات البائع هذه الطريقة قبل استدعاء ProcessState, IPCThreadState أو قبل إجراء أي مكالمات Binder بشكل عام. للاستخدام ، قم بإجراء المكالمة التالية بعد العملية main() لعملية البائع (العميل والخادم):

ProcessState::initWithDriver("/dev/vndbinder");

vndservicemanager

في السابق ، تم تسجيل خدمات الموثق لدى servicemanager ، حيث يمكن استرجاعها من خلال عمليات أخرى. في Android 8 ، يتم استخدام servicemanager الآن حصريًا من خلال عمليات الإطار والتطبيق ولم يعد بإمكان عمليات البائع الوصول إليه.

ومع ذلك ، يمكن الآن لخدمات البائعين استخدام vndservicemanager ، وهو مثيل جديد من vndservicemanager servicemanager يستخدم /dev/vndbinder بدلاً من /dev/binder والذي تم إنشاؤه من نفس المصادر مثل Framework servicemanager . لا تحتاج عمليات البائع إلى إجراء تغييرات للتحدث إلى vndservicemanager ؛ عند فتح عملية البائع / dev/vndbinder ، dev/vndbinder عمليات البحث عن الخدمة تلقائيًا إلى vndservicemanager .

يتم تضمين vndservicemanager الثنائي vndservicemanager في ملفات makefiles لجهاز Android الافتراضي.

سياسة SELinux

تحتاج عمليات البائع التي تريد استخدام وظيفة Binder للتواصل مع بعضها البعض إلى ما يلي:

  1. الوصول إلى /dev/vndbinder .
  2. vndservicemanager {transfer, call} vndservicemanager إلى vndservicemanager .
  3. binder_call(A, B) لأي مجال بائع A يريد الاتصال بمجال البائع B عبر واجهة رابط البائع.
  4. إذن {add, find} services في vndservicemanager .

للوفاء بالمتطلبات 1 و 2 ، استخدم الماكرو vndbinder_use() :

vndbinder_use(some_vendor_process_domain);

للوفاء بالمتطلب 3 ، يمكن أن binder_call(A, B) لعمليات البائع A و B التي تحتاج إلى التحدث عبر الموثق في مكانه ، ولا يحتاج إلى إعادة التسمية.

للوفاء بالمتطلب 4 ، يجب إجراء تغييرات في طريقة التعامل مع أسماء الخدمة وتسميات الخدمة والقواعد.

للحصول على تفاصيل حول SELinux ، راجع Linux المحسّن للأمان في Android . للحصول على تفاصيل حول SELinux في Android 8.0 ، راجع SELinux لنظام Android 8.0 .

أسماء الخدمة

في السابق ، كان البائع يعالج أسماء الخدمات المسجلة في ملف service_contexts وأضاف القواعد المقابلة للوصول إلى هذا الملف. مثال على ملف service_contexts من device/google/marlin/sepolicy :

AtCmdFwd                              u:object_r:atfwd_service:s0
cneservice                            u:object_r:cne_service:s0
qti.ims.connectionmanagerservice      u:object_r:imscm_service:s0
rcs                                   u:object_r:radio_service:s0
uce                                   u:object_r:uce_service:s0
vendor.qcom.PeripheralManager         u:object_r:per_mgr_service:s0

في Android 8 ، يقوم vndservicemanager بتحميل ملف vndservice_contexts بدلاً من ذلك. يجب إضافة خدمات البائع التي تنتقل إلى vndservicemanager (والموجودة بالفعل في ملف service_contexts القديم) إلى ملف vndservice_contexts الجديد.

تسميات الخدمة

في السابق ، تم تعريف تسميات الخدمة مثل u:object_r:atfwd_service:s0 في ملف service.te . مثال:

type atfwd_service,      service_manager_type;

في Android 8 ، يجب عليك تغيير النوع إلى vndservice_manager_type ونقل القاعدة إلى ملف vndservice.te . مثال:

type atfwd_service,      vndservice_manager_type;

قواعد مدير الخدمة

في السابق ، كانت القواعد تمنح المجالات إمكانية الوصول لإضافة أو العثور على خدمات من servicemanager . مثال:

allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;

في Android 8 ، يمكن أن تظل هذه القواعد سارية وتستخدم نفس الفئة. مثال:

allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;