باستخدام ftrace

ftrace هي أداة تصحيح الأخطاء لفهم ما يجري داخل نواة Linux. توضح الأقسام التالية بالتفصيل وظيفة ftrace الأساسية، واستخدام ftrace مع atrace (الذي يلتقط أحداث kernel)، وftrace الديناميكي.

للحصول على تفاصيل حول وظيفة ftrace المتقدمة التي لا تتوفر من systrace، راجع وثائق ftrace على <kernel tree>/Documentation/trace/ftrace.txt .

التقاط أحداث النواة باستخدام atrace

يستخدم atrace ( frameworks/native/cmds/atrace ) ftrace لالتقاط أحداث kernel. بدوره، يستخدم systrace.py (أو run_systrace.py في الإصدارات اللاحقة من Catapult ) adb لتشغيل atrace على الجهاز. يقوم atrace بما يلي:

  • يقوم بإعداد تتبع وضع المستخدم عن طريق تعيين خاصية ( debug.atrace.tags.enableflags ).
  • لتمكين وظيفة ftrace المطلوبة عن طريق الكتابة إلى عقد ftrace sysfs المناسبة. ومع ذلك، نظرًا لأن ftrace يدعم المزيد من الميزات، فيمكنك تعيين بعض عقد sysfs بنفسك ثم استخدام atrace.

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

تمكين أحداث ftrace

توجد عقد ftrace sysfs في /sys/kernel/tracing ويتم تقسيم أحداث التتبع إلى فئات في /sys/kernel/tracing/events .

لتمكين الأحداث على أساس كل فئة، استخدم:

echo 1 > /sys/kernel/tracing/events/irq/enable

لتمكين الأحداث على أساس كل حدث، استخدم:

echo 1 > /sys/kernel/tracing/events/sched/sched_wakeup/enable

إذا تم تمكين الأحداث الإضافية عن طريق الكتابة إلى عقد sysfs، فلن تتم إعادة تعيينها بواسطة atrace. أحد الأنماط الشائعة لإحضار جهاز Qualcomm هو تمكين نقاط التتبع kgsl (GPU) و mdss (خط أنابيب العرض) ثم استخدام atrace أو systrace :

adb shell "echo 1 > /sys/kernel/tracing/events/mdss/enable"
adb shell "echo 1 > /sys/kernel/tracing/events/kgsl/enable"
./systrace.py sched freq idle am wm gfx view binder_driver irq workq ss sync -t 10 -b 96000 -o full_trace.html

يمكنك أيضًا استخدام ftrace بدون atrace أو systrace، وهو أمر مفيد عندما تريد تتبعات kernel فقط (أو إذا كنت قد أخذت وقتًا لكتابة خاصية التتبع لوضع المستخدم يدويًا). لتشغيل ftrace فقط:

  1. قم بتعيين حجم المخزن المؤقت على قيمة كبيرة بما يكفي لتتبعك:
    echo 96000 > /sys/kernel/tracing/buffer_size_kb
    
  2. تمكين التتبع:
    echo 1 > /sys/kernel/tracing/tracing_on
    
  3. قم بإجراء الاختبار، ثم قم بتعطيل التتبع:
    echo 0 > /sys/kernel/tracing/tracing_on
    
  4. تفريغ التتبع:
    cat /sys/kernel/tracing/trace > /data/local/tmp/trace_output
    

يعطي Trace_output التتبع في شكل نص. لتصوره باستخدام Catapult، احصل على مستودع Catapult من GitHub وقم بتشغيل Trace2html:

catapult/tracing/bin/trace2html ~/path/to/trace_file

بشكل افتراضي، يقوم هذا بكتابة trace_file.html في نفس الدليل.

الأحداث المترابطة

غالبًا ما يكون من المفيد النظر إلى تصور Catapult وسجل ftrace في وقت واحد؛ على سبيل المثال، بعض أحداث ftrace (خاصة الأحداث الخاصة بالبائع) لا يتم تصورها بواسطة Catapult. ومع ذلك، فإن الطوابع الزمنية لـ Catapult تتعلق إما بالحدث الأول في التتبع أو بطابع زمني محدد تم تفريغه بواسطة atrace، بينما تعتمد الطوابع الزمنية الأولية لـ ftrace على مصدر ساعة مطلق محدد في Linux kernel.

للعثور على حدث ftrace معين من حدث Catapult:

  1. افتح سجل ftrace الخام. يتم ضغط الآثار الموجودة في الإصدارات الأخيرة من systrace افتراضيًا:
    • إذا قمت بالتقاط systrace الخاص بك باستخدام --no-compress ، فهذا موجود في ملف html في القسم الذي يبدأ بـ BEGIN TRACE.
    • إذا لم يكن الأمر كذلك، فقم بتشغيل html2trace من شجرة Catapult ( tracing/bin/html2trace ) لإلغاء ضغط التتبع.
  2. ابحث عن الطابع الزمني النسبي في تصور Catapult.
  3. ابحث عن سطر في بداية التتبع يحتوي على tracing_mark_sync . يجب أن يبدو مثل هذا:
    <5134>-5134  (-----) [003] ...1    68.104349: tracing_mark_write: trace_event_clock_sync: parent_ts=68.104286
    

    إذا لم يكن هذا الخط موجودًا (أو إذا استخدمت ftrace بدون atrace)، فستكون التوقيتات نسبية من الحدث الأول في سجل ftrace.
    1. أضف الطابع الزمني النسبي (بالمللي ثانية) إلى القيمة الموجودة في parent_ts (بالثواني).
    2. ابحث عن الطابع الزمني الجديد.

يجب أن تضعك هذه الخطوات في الحدث (أو على الأقل قريبًا جدًا منه).

باستخدام ftrace الديناميكي

عندما لا يكون systrace وftrace القياسي كافيين، فهناك حل أخير متاح: Dynamic ftrace . يتضمن ftrace الديناميكي إعادة كتابة كود kernel بعد التمهيد، ونتيجة لذلك فهو غير متوفر في نواة الإنتاج لأسباب أمنية. ومع ذلك، فإن كل خطأ صعب في الأداء في عامي 2015 و2016 كان في النهاية سببًا جذريًا باستخدام ftrace الديناميكي. إنه قوي بشكل خاص لتصحيح أخطاء حالات النوم غير المنقطعة لأنه يمكنك الحصول على تتبع المكدس في النواة في كل مرة تضغط فيها على الوظيفة التي تؤدي إلى نوم غير متقطع. يمكنك أيضًا تصحيح أخطاء الأقسام مع تعطيل المقاطعات والإجراءات الوقائية، وهو ما يمكن أن يكون مفيدًا جدًا لإثبات المشكلات.

لتشغيل ftrace الديناميكي، قم بتحرير defconfig الخاص بالنواة:

  1. قم بإزالة CONFIG_STRICT_MEMORY_RWX (إذا كان موجودًا). إذا كنت تستخدم الإصدار 3.18 أو الأحدث وarm64، فهذا ليس موجودًا.
  2. أضف ما يلي: CONFIG_DYNAMIC_FTRACE=y وCONFIG_FUNCTION_TRACER=y وCONFIG_IRQSOFF_TRACER=y وCONFIG_FUNCTION_PROFILER=y وCONFIG_PREEMPT_TRACER=y
  3. إعادة بناء وتمهيد النواة الجديدة.
  4. قم بتشغيل ما يلي للتحقق من أدوات التتبع المتاحة:
    cat /sys/kernel/tracing/available_tracers
    
  5. قم بتأكيد الأمر بإرجاع function ، irqsoff ، و preemptoff ، و preemptirqsoff .
  6. قم بتشغيل ما يلي للتأكد من عمل ftrace الديناميكي:
    cat /sys/kernel/tracing/available_filter_functions | grep <a function you care about>
    

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

يعد ملف تعريف الوظيفة هو الخيار الأفضل لمشكلات الأداء وغالبًا ما يستخدم لمعرفة مكان استدعاء الوظيفة.


إذا لم تكن البيانات الواردة من ملف تعريف الدالة محددة بدرجة كافية، فيمكنك دمج نقاط تتبع ftrace مع ملف تعريف الدالة. يمكن تمكين أحداث ftrace بنفس الطريقة المعتادة تمامًا، وسيتم تشذيرها مع التتبع الخاص بك. يعد هذا أمرًا رائعًا إذا كان هناك نوم طويل غير متقطع في بعض الأحيان في وظيفة معينة تريد تصحيحها: قم بتعيين مرشح ftrace على الوظيفة التي تريدها، وقم بتمكين نقاط التتبع، وقم بالتتبع. يمكنك تحليل التتبع الناتج باستخدام trace2html ، والعثور على الحدث الذي تريده، ثم الحصول على آثار المكدس القريبة في التتبع الأولي.

باستخدام قفلستات

في بعض الأحيان، لا يكون ftrace كافيًا وتحتاج حقًا إلى تصحيح ما يبدو أنه تنافس على قفل kernel. هناك خيار آخر للنواة يستحق التجربة: CONFIG_LOCK_STAT . يعد هذا هو الملاذ الأخير لأنه من الصعب للغاية العمل على أجهزة Android لأنه يؤدي إلى تضخيم حجم النواة بما يتجاوز ما تستطيع معظم الأجهزة التعامل معه.

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


إذا كان بإمكانك تشغيل النواة باستخدام خيار التكوين، فإن تتبع القفل يشبه ftrace:

  1. تمكين التتبع:
    echo 1 > /proc/sys/kernel/lock_stat
    
  2. قم بإجراء الاختبار الخاص بك.
  3. تعطيل التتبع:
    echo 0 > /proc/sys/kernel/lock_stat
    
  4. تفريغ التتبع الخاص بك:
    cat /proc/lock_stat > /data/local/tmp/lock_stat
    

للمساعدة في تفسير المخرجات الناتجة، راجع وثائق lockstat على <kernel>/Documentation/locking/lockstat.txt .

استخدام نقاط تتبع البائع

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

  { "gfx",        "Graphics",         ATRACE_TAG_GRAPHICS, {
        { OPT,      "events/mdss/enable" },
        { OPT,      "events/sde/enable" },
        { OPT,      "events/mali_systrace/enable" },
    } },

نقاط التتبع قابلة للتوسيع بواسطة خدمة HAL مما يسمح لك بإضافة نقاط/فئات تتبع خاصة بالجهاز. تم دمج نقاط التتبع مع perfetto، وatrace/systrace، وتطبيق تتبع النظام على الجهاز.

واجهات برمجة التطبيقات (APIs) لتنفيذ نقاط التتبع/الفئات هي:

  • تنشئ listCategories() (فئات vec<TracingCategory>);
  • يُنشئ تمكين الفئات (فئات vec<string>) (حالة الحالة) ؛
  • يُنشئ DisableAllCategories () (حالة الحالة) ؛
لمزيد من المعلومات، راجع تعريف HAL ​​والتنفيذ الافتراضي في AOSP :