استفاده از ftrace

ftrace یک ابزار اشکال زدایی برای درک آنچه در داخل هسته لینوکس می گذرد است. بخش‌های زیر عملکرد پایه ftrace، استفاده از ftrace با atrace (که رویدادهای هسته را ثبت می‌کند) و ftrace پویا را شرح می‌دهد.

برای جزئیات در مورد عملکرد پیشرفته ftrace که از systrace در دسترس نیست، به مستندات ftrace در <kernel tree>/Documentation/trace/ftrace.txt مراجعه کنید.

ثبت رویدادهای هسته با atrace

atrace ( frameworks/native/cmds/atrace ) از ftrace برای ثبت رویدادهای هسته استفاده می کند. به نوبه خود، systrace.py (یا run_systrace.py در نسخه‌های بعدی Catapult ) از adb برای اجرای atrace در دستگاه استفاده می‌کند. atrace کارهای زیر را انجام می دهد:

  • ردیابی حالت کاربر را با تنظیم یک ویژگی ( debug.atrace.tags.enableflags ) تنظیم می کند.
  • با نوشتن در گره های ftrace sysfs مناسب، عملکرد ftrace مورد نظر را فعال می کند. با این حال، از آنجایی که ftrace از ویژگی‌های بیشتری پشتیبانی می‌کند، ممکن است برخی از گره‌های sysfs را خودتان تنظیم کنید و سپس از atrace استفاده کنید.

به استثنای ردیابی زمان راه‌اندازی، برای تنظیم ویژگی روی مقدار مناسب، به استفاده از atrace تکیه کنید. این ویژگی یک بیت ماسک است و هیچ راه خوبی برای تعیین مقادیر صحیح به جز نگاه کردن به هدر مناسب (که می تواند بین نسخه های اندروید تغییر کند) وجود ندارد.

فعال کردن رویدادهای 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 بازنشانی نمی‌شوند . یک الگوی رایج برای بازگرداندن دستگاه کوالکام، فعال کردن نقاط ردیابی 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 استفاده کنید، که زمانی مفید است که شما ردیابی‌های فقط هسته را می‌خواهید (یا اگر زمان صرف کرده‌اید و ویژگی ردیابی حالت کاربر را با دست بنویسید). برای اجرای فقط 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. Dump the trace:
    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 را در همان دایرکتوری می نویسد.

رویدادهای مرتبط

اغلب مفید است که به تجسم منجنیق و گزارش ftrace به طور همزمان نگاه کنید. برای مثال، برخی از رویدادهای ftrace (مخصوصاً رویدادهای خاص فروشنده) توسط Catapult تجسم نمی شوند. با این حال، مُهرهای زمان Catapult یا به اولین رویداد در ردیابی یا به یک مهر زمانی خاص که توسط atrace ریخته شده است، مرتبط هستند، در حالی که مُهرهای زمانی ftrace خام بر اساس یک منبع ساعت مطلق خاص در هسته لینوکس هستند.

برای پیدا کردن یک رویداد ftrace داده شده از یک رویداد Catapult:

  1. گزارش خام ftrace را باز کنید. ردیابی ها در نسخه های اخیر systrace به طور پیش فرض فشرده می شوند:
    • اگر systrace خود را با --no-compress گرفته‌اید، این در فایل html در بخشی است که با BEGIN TRACE شروع می‌شود.
    • در غیر این صورت، html2trace را از درخت Catapult ( tracing/bin/html2trace ) اجرا کنید تا ردیابی از حالت فشرده خارج شود.
  2. مهر زمانی نسبی را در تجسم منجنیق پیدا کنید.
  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. مُهر زمانی جدید را جستجو کنید.

این مراحل باید شما را در رویداد (یا حداقل بسیار نزدیک به آن) قرار دهند.

با استفاده از fttrace پویا

وقتی systrace و ftrace استاندارد کافی نیستند، آخرین راه‌حل موجود است: dynamic ftrace . Ftrace پویا شامل بازنویسی کد هسته پس از راه‌اندازی می‌شود و در نتیجه به دلایل امنیتی در هسته‌های تولیدی موجود نیست. با این حال، تک تک باگ‌های عملکردی دشوار در سال‌های 2015 و 2016 در نهایت با استفاده از fttrace پویا به وجود آمدند. این به ویژه برای اشکال زدایی خواب های بی وقفه قدرتمند است زیرا هر بار که عملکردی را که باعث ایجاد خواب بدون وقفه می شود ضربه بزنید، می توانید یک stack trace در هسته دریافت کنید. همچنین می‌توانید بخش‌هایی را که وقفه‌ها و پیش‌پرداخت‌ها غیرفعال هستند اشکال‌زدایی کنید، که می‌تواند برای اثبات مسائل بسیار مفید باشد.

برای روشن کردن fttrace پویا، 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. موارد زیر را اجرا کنید تا مطمئن شوید fttrace پویا کار می کند:
    cat /sys/kernel/tracing/available_filter_functions | grep <a function you care about>
    

پس از انجام این مراحل، fttrace پویا، نمایه ساز تابع، پروفایلر irqsoff و نمایه ساز preemptoff را در دسترس دارید. ما قویاً توصیه می کنیم اسناد ftrace در مورد این موضوعات را قبل از استفاده از آنها بخوانید زیرا قدرتمند اما پیچیده هستند. irqsoff و preemptoff در درجه اول برای تأیید اینکه رانندگان ممکن است وقفه ها یا preemption را برای مدت طولانی خاموش بگذارند مفید هستند.

نمایه ساز تابع بهترین گزینه برای مسائل مربوط به عملکرد است و اغلب برای یافتن مکان فراخوانی یک تابع استفاده می شود.


اگر داده های تابع پروفایلر به اندازه کافی خاص نیست، می توانید نقاط ردیابی ftrace را با نمایه ساز تابع ترکیب کنید. رویدادهای ftrace را می توان دقیقاً به همان روش معمول فعال کرد و با ردیابی شما تداخل پیدا می کند. اگر گهگاه یک خواب بدون وقفه طولانی در یک تابع خاص وجود داشته باشد که می‌خواهید اشکال‌زدایی کنید، عالی است: فیلتر ftrace را روی تابعی که می‌خواهید تنظیم کنید، نقاط ردیابی را فعال کنید، ردیابی کنید. می‌توانید ردیابی به‌دست‌آمده را با trace2html تجزیه کنید، رویدادی را که می‌خواهید پیدا کنید، سپس ردیابی‌های پشته نزدیک را در ردیابی خام دریافت کنید.

با استفاده از lockstat

گاهی اوقات، ftrace کافی نیست و شما واقعاً نیاز به اشکال زدایی دارید که به نظر می رسد مناقشه قفل هسته است. یک گزینه هسته دیگر وجود دارد که ارزش امتحان کردن دارد: CONFIG_LOCK_STAT . این آخرین راه حل است، زیرا کار کردن بر روی دستگاه های اندرویدی بسیار دشوار است زیرا اندازه هسته را فراتر از آن چیزی است که اکثر دستگاه ها می توانند تحمل کنند.

با این حال، lockstat از زیرساخت قفل اشکال زدایی استفاده می کند که برای بسیاری از برنامه های کاربردی دیگر مفید است. هرکسی که روی بالا بردن دستگاه کار می‌کند باید راهی پیدا کند تا آن گزینه روی هر دستگاهی کار کند، زیرا زمانی می‌رسد که فکر می‌کنید «اگر فقط می‌توانستم LOCK_STAT را روشن کنم، می‌توانم به جای اینکه مشکل را در پنج دقیقه تأیید یا رد کنم. پنج روز."


اگر بتوانید یک هسته را با گزینه config بوت کنید، lock tracing شبیه 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 و برنامه ردیابی سیستم روی دستگاه یکپارچه شده اند.

API ها برای پیاده سازی نقاط/دسته ها عبارتند از:

  • listCategories() دسته بندی (vec<TracingCategory>) را ایجاد می کند.
  • enableCategories(vec<string> category) ایجاد می کند (وضعیت وضعیت).
  • disableAllCategories() ایجاد می کند (وضعیت وضعیت)؛
برای اطلاعات بیشتر، به تعریف HAL ​​و پیاده سازی پیش فرض در AOSP مراجعه کنید: