Scroll to navigation

perf_event_open(2) System Calls Manual perf_event_open(2)

الاسم

perf_event_open - إعداد مراقبة الأداء

المكتبة

مكتبة سي المعيارية (libc، -lc)

موجز

#include <linux/perf_event.h>    /* تعريف ثوابت PERF_* */
#include <linux/hw_breakpoint.h> /* تعريف ثوابت HW_* */
#include <sys/syscall.h>         /* تعريف ثوابت SYS_* */
#include <unistd.h>
int syscall(SYS_perf_event_open, struct perf_event_attr *attr,
            pid_t pid, int cpu, int group_fd, unsigned long flags);

ملاحظة: لا توفر glibc غلافاً للدالة perf_event_open()، مما يستوجب استخدام syscall(2).

الوصف

بناءً على قائمة من المعلمات، تعيد perf_event_open() واصف ملف لاستخدامه في استدعاءات النظام اللاحقة (read(2)، وmmap(2)، وprctl(2)، وfcntl(2)، وغيرها).

يُنشئ استدعاء perf_event_open() واصف ملف يتيح قياس معلومات الأداء. يقابل كل واصف ملف حدثاً واحداً يُقاس؛ ويمكن تجميع هذه الواصفات معاً لقياس أحداث متعددة في وقت واحد.

يمكن تفعيل الأحداث وتعطيلها بطريقتين: عبر ioctl(2) وعبر prctl(2). عندما يُعطّل الحدث، فإنه لا يحسب أو يولد حالات طفح، ولكنه يستمر في الوجود ويحافظ على قيمة عداده.

تأتي الأحداث بنوعين: معدودة وأخذ عينات. الحدث المعدود هو الذي يُستخدم لعد العدد الإجمالي للأحداث التي تقع. بصفة عامة، تُجمع نتائج الأحداث المعدودة باستدعاء read(2). أما حدث أخذ العينات فيكتب القياسات بصفة دورية إلى مخبأ يمكن الوصول إليه عبر mmap(2).

المعطيات

تسمح المعطيات pid وcpu بتحديد العملية ووحدة المعالجة المركزية المراد مراقبتها:

يقيس هذا العملية/الخيط المستدعي على أي وحدة معالجة مركزية.
يقيس هذا العملية/الخيط المستدعي فقط عند تشغيلها على وحدة المعالجة المركزية المحددة.
يقيس هذا العملية/الخيط المحدد على أي وحدة معالجة مركزية.
يقيس هذا العملية/الخيط المحدد فقط عند تشغيلها على وحدة المعالجة المركزية المحددة.
يقيس هذا جميع العمليات/الخيوط على وحدة المعالجة المركزية المحددة. يتطلب هذا صلاحية CAP_PERFMON (منذ لينكس 5.8) أو CAP_SYS_ADMIN أو قيمة أقل من 1 في الملف /proc/sys/kernel/perf_event_paranoid.
هذا الإعداد غير صالح وسيعيد خطأ.

عندما تكون قيمة pid أكبر من الصفر، فإن الإذن بإجراء هذا الاستدعاء للنظام تحكمه صلاحية CAP_PERFMON (منذ لينكس 5.9) وفحص وضع وصول ptrace PTRACE_MODE_READ_REALCREDS في إصدارات لينكس القديمة؛ انظر ptrace(2).

يسمح المعطى group_fd بإنشاء مجموعات أحداث. تحتوي مجموعة الأحداث على حدث واحد يكون هو قائد المجموعة. يُنشأ القائد أولاً مع تعيين group_fd = -1. تُنشأ بقية أعضاء المجموعة باستدعاءات perf_event_open() لاحقة مع تعيين group_fd ليكون واصف الملف لقائد المجموعة. (يُنشأ الحدث المنفرد مع تعيين group_fd = -1 ويُعد مجموعة من عضو واحد فقط.) تُجدول مجموعة الأحداث على وحدة المعالجة المركزية كوحدة واحدة: لن توضع على وحدة المعالجة إلا إذا أمكن وضع جميع أحداث المجموعة عليها. وهذا يعني أن قيم الأحداث الأعضاء يمكن مقارنتها بشكل ذي معنى —جمعها، أو قسمتها (للحصول على نسب)، وما إلى ذلك— مع بعضها البعض، لأنها عدت أحداثاً لنفس المجموعة من التعليمات المنفذة.

يُشكَّل المعطى flags بدمج صفر أو أكثر من القيم التالية باستخدام معامل OR المنطقي:

يُفعل هذا العلم خاصية الغلق عند التنفيذ (close-on-exec) لواصف ملف الحدث المنشأ، بحيث يُغلق واصف الملف آلياً عند استدعاء execve(2). إن ضبط أعلام الغلق عند التنفيذ وقت الإنشاء، بدلاً من القيام بذلك لاحقًا عبر fcntl(2)، يتجنب ظروف السباق المحتملة حيث يستدعي خيط الاستدعاء perf_event_open() و fcntl(2) في نفس الوقت الذي يستدعي فيه خيط آخر fork(2) ثم execve(2).
يخبر هذا العلم الحدث بتجاهل معلمة group_fd باستثناء غرض إعداد إعادة توجيه المخرجات باستخدام علم PERF_FLAG_FD_OUTPUT.
يعيد هذا العلم توجيه مخرجات العينات للحدث ليتم تضمينها بدلاً من ذلك في مخبأ mmap للحدث المحدد بواسطة group_fd.
يفعل هذا العلم مراقبة النظام بالكامل لكل حاوية. الحاوية هي تجريد يعزل مجموعة من الموارد للتحكم الدقيق (وحدات المعالجة، والذاكرة، إلخ). في هذا الوضع، يُقاس الحدث فقط إذا كان الخيط الذي يعمل على وحدة المعالجة المراقبة ينتمي إلى الحاوية المخصصة (cgroup). تُحدد cgroup بتمرير واصف ملف مفتوح على دليلها في نظام ملفات cgroupfs. على سبيل المثال، إذا كانت cgroup المراد مراقبتها تسمى test، فيجب تمرير واصف ملف مفتوح على /dev/cgroup/test (بافتراض أن cgroupfs موصول على /dev/cgroup) كمعلمة pid. تتوفر مراقبة cgroup فقط لأحداث النظام بالكامل، وبالتالي قد تتطلب صلاحيات إضافية.

توفر بنية perf_event_attr معلومات ضبط مفصلة للحدث الجاري إنشاؤه.


struct perf_event_attr {

__u32 type; /* نوع الحدث */
__u32 size; /* حجم بنية السمات */
__u64 config; /* الضبط الخاص بالنوع */
union {
__u64 sample_period; /* فترة أخذ العينات */
__u64 sample_freq; /* تردد أخذ العينات */
};
__u64 sample_type; /* يحدد القيم المضمنة في العينة */
__u64 read_format; /* يحدد القيم المعادة في القراءة */
__u64 disabled : 1, /* معطل مبدئياً */
inherit : 1, /* يرثه الأبناء */
pinned : 1, /* يجب أن يكون دائماً على وحدة مراقبة الأداء (PMU) */
exclusive : 1, /* المجموعة الوحيدة على PMU */
exclude_user : 1, /* لا تحسب المستخدم */
exclude_kernel : 1, /* لا تحسب النواة */
exclude_hv : 1, /* لا تحسب المراقب الفائق */
exclude_idle : 1, /* لا تحسب عند الخمول */
mmap : 1, /* تضمين بيانات mmap */
comm : 1, /* تضمين بيانات comm */
freq : 1, /* استخدام التردد وليس الفترة */
inherit_stat : 1, /* عد لكل مهمة */
enable_on_exec : 1, /* التنفيذ التالي يفعله */
task : 1, /* تتبع التفريع/الخروج */
watermark : 1, /* علامة الاستيقاظ المائية */
precise_ip : 2, /* قيد الانزلاق */
mmap_data : 1, /* بيانات mmap غير التنفيذية */
sample_id_all : 1, /* معرف العينة لجميع الأحداث */
exclude_host : 1, /* لا تحسب في المضيف */
exclude_guest : 1, /* لا تحسب في الضيف */
exclude_callchain_kernel : 1,
/* استثناء سلاسل استدعاء النواة */
exclude_callchain_user : 1,
/* استثناء سلاسل استدعاء المستخدم */
mmap2 : 1, /* تضمين mmap مع بيانات inode */
comm_exec : 1, /* وسم أحداث comm الناتجة عن التنفيذ */
use_clockid : 1, /* استخدام clockid لحقول الوقت */
context_switch : 1, /* بيانات تبديل السياق */
write_backward : 1, /* كتابة المخبأ الحلقي من النهاية إلى البداية */
namespaces : 1, /* تضمين بيانات مساحات الأسماء */
ksymbol : 1, /* تضمين أحداث ksymbol */
bpf_event : 1, /* تضمين أحداث bpf */
aux_output : 1, /* توليد سجلات AUX بدلاً من الأحداث */
cgroup : 1, /* تضمين أحداث cgroup */
text_poke : 1, /* تضمين أحداث تعديل النص */
build_id : 1, /* استخدام معرف البناء في أحداث mmap2 */
inherit_thread : 1, /* يرث الأبناء فقط إذا استُخدم CLONE_THREAD */
remove_on_exec : 1, /* يُزال الحدث من المهمة عند التنفيذ */
sigtrap : 1, /* إرسال SIGTRAP متزامن عند الحدث */
__reserved_1 : 26;
union {
__u32 wakeup_events; /* الاستيقاظ كل n حدث */
__u32 wakeup_watermark; /* البايتات قبل الاستيقاظ */
};
__u32 bp_type; /* نوع نقطة التوقف */
union {
__u64 bp_addr; /* عنوان نقطة التوقف */
__u64 kprobe_func; /* لـ perf_kprobe */
__u64 uprobe_path; /* لـ perf_uprobe */
__u64 config1; /* امتداد لـ config */
};
union {
__u64 bp_len; /* حجم نقطة التوقف */
__u64 kprobe_addr; /* مع kprobe_func == NULL */
__u64 probe_offset; /* لـ perf_[k,u]probe */
__u64 config2; /* امتداد لـ config1 */
};
__u64 branch_sample_type; /* نوع عينة التفرع */
__u64 sample_regs_user; /* سجلات المستخدم لتفريغها عند العينات */
__u32 sample_stack_user; /* حجم المكدس لتفريغه عند العينات */
__s32 clockid; /* الساعة المستخدمة لحقول الوقت */
__u64 sample_regs_intr; /* السجلات لتفريغها عند العينات */
__u32 aux_watermark; /* بايتات aux قبل الاستيقاظ */
__u16 sample_max_stack; /* أقصى عدد من الإطارات في سلسلة الاستدعاء */
__u16 __reserved_2; /* موازاة إلى u64 */
__u32 aux_sample_size; /* أقصى حجم لعينة aux */
__u32 __reserved_3; /* موازاة إلى u64 */
__u64 sig_data; /* بيانات المستخدم لـ sigtrap */ };

وُصفت حقول بنية perf_event_attr بمزيد من التفصيل أدناه:

يحدد هذا الحقل نوع الحدث العام. ويأخذ إحدى القيم التالية:
يشير هذا إلى أحد أحداث العتاد "المعممة" التي توفرها النواة. انظر تعريف حقل config لمزيد من التفاصيل.
يشير هذا إلى أحد الأحداث المعرفة برمجياً التي توفرها النواة (حتى لو لم يتوفر دعم عتادي).
يشير هذا إلى نقطة تتبع توفرها البنية التحتية لنقاط تتبع النواة.
يشير هذا إلى حدث في خبيئة العتاد. وله ترميز خاص مشروح في تعريف حقل config.
يشير هذا إلى حدث "خام" خاص بالتنفيذ في حقل config.
يشير هذا إلى نقطة توقف عتادية كما توفرها وحدة المعالجة المركزية. يمكن أن تكون نقاط التوقف عمليات وصول للقراءة/الكتابة إلى عنوان ما، وكذلك تنفيذ لعنوان تعليمة.
وحدة مراقبة أداء (PMU) ديناميكية
منذ لينكس 2.6.38، يمكن لـ perf_event_open() دعم وحدات PMU متعددة. لتفعيل ذلك، يمكن استخدام قيمة تصدرها النواة في حقل type للإشارة إلى وحدة PMU المراد استخدامها. يمكن العثور على القيمة المطلوب استخدامها في نظام ملفات sysfs: يوجد دليل فرعي لكل مثيل PMU تحت /sys/bus/event_source/devices. يوجد في كل دليل فرعي ملف type محتواه عدد صحيح يمكن استخدامه في حقل type. على سبيل المثال، يحتوي /sys/bus/event_source/devices/cpu/type على قيمة وحدة PMU لنواة وحدة المعالجة المركزية، وهي عادة 4.
تنشئ وحدتا PMU الديناميكيتان هاتان kprobe/uprobe وتربطانه بواصف الملف الناتج عن perf_event_open. وسيُحذف kprobe/uprobe عند حذف واصف الملف. انظر الحقول kprobe_func وuprobe_path وkprobe_addr وprobe_offset لمزيد من التفاصيل.
حجم بنية perf_event_attr للتوافقية الأمامية والخلفية. اضبط هذا باستخدام sizeof(struct perf_event_attr) للسماح للنواة برؤية حجم البنية وقت التصريف.
عُيّن التعريف ذو الصلة PERF_ATTR_SIZE_VER0 إلى 64؛ وكان هذا حجم أول بنية نُشرت. وPERF_ATTR_SIZE_VER1 هو 72، ويقابل إضافة نقاط التوقف في لينكس 2.6.33. وPERF_ATTR_SIZE_VER2 هو 80 ويقابل إضافة أخذ عينات التفرع في لينكس 3.4. وPERF_ATTR_SIZE_VER3 هو 96 ويقابل إضافة sample_regs_user و sample_stack_user في لينكس 3.7. وPERF_ATTR_SIZE_VER4 هو 104 ويقابل إضافة sample_regs_intr في لينكس 3.19. وPERF_ATTR_SIZE_VER5 هو 112 ويقابل إضافة aux_watermark في لينكس 4.1.
يحدد هذا الحدث الذي تريده، بالاشتراك مع حقل type. كما تُؤخذ الحقول config1 وconfig2 في الاعتبار في الحالات التي لا يكفي فيها 64 بتاً لتحديد الحدث بشكل كامل. يعتمد ترميز هذه الحقول على نوع الحدث.
توجد طرق متنوعة لضبط حقل config تعتمد على قيمة حقل type الموصوف سابقاً. وفيما يلي الإعدادات المختلفة الممكنة لـ config مقسمة حسب type.
إذا كان type هو PERF_TYPE_HARDWARE، فإننا نقيس أحد أحداث وحدة المعالجة المركزية العتادية الموحدة. ليست كل هذه الأحداث متاحة في جميع المنصات. اضبط config على أحد الخيارات التالية:
إجمالي الدورات. كن حذرًا مما يحدث أثناء تغيير تردد وحدة المعالجة المركزية.
التعليمات المتقاعدة. كن حذرًا، فقد تتأثر هذه بمشكلات متنوعة، وأبرزها عدادات المقاطعات العتادية.
الوصول إلى الخبيئة. يشير هذا عادةً إلى الوصول إلى خبيئة المستوى الأخير ولكن قد يختلف ذلك حسب وحدة المعالجة المركزية لديك. قد يتضمن هذا الجلب المسبق ورسائل التماسك؛ ومرة أخرى، يعتمد هذا على تصميم وحدة المعالجة المركزية لديك.
إخفاقات الخبيئة. يشير هذا عادةً إلى إخفاقات خبيئة المستوى الأخير؛ ويُقصد استخدامه بالاقتران مع حدث PERF_COUNT_HW_CACHE_REFERENCES لحساب معدلات إخفاق الخبيئة.
تعليمات التفرع المتقاعدة. قبل لينكس 2.6.35، كان هذا يستخدم الحدث الخاطئ على معالجات AMD.
تعليمات التفرع التي أُسيء التنبؤ بها.
دورات الناقل، والتي يمكن أن تختلف عن إجمالي الدورات.
الدورات المتوقفة أثناء الإصدار.
الدورات المتوقفة أثناء التقاعد.
إجمالي الدورات؛ لا يتأثر بتغيير تردد وحدة المعالجة المركزية.
إذا كان type هو PERF_TYPE_SOFTWARE، فإننا نقيس أحداث البرمجيات التي توفرها النواة. اضبط config على أحد الخيارات التالية:
يبلغ هذا عن ساعة وحدة المعالجة المركزية، وهي مؤقت عالي الدقة لكل معالج.
يبلغ هذا عن عدد دورات الساعة الخاصة بالمهمة التي تعمل.
يبلغ هذا عن عدد إخفاقات الصفحة.
يحسب هذا تبديلات السياق. حتى لينكس 2.6.34، أُبلغ عن كل هذه كأحداث في مساحة المستخدم، وبعد ذلك أُبلغ عنها كأحداث تقع في النواة.
يبلغ هذا عن عدد المرات التي انتقلت فيها العملية إلى وحدة معالجة مركزية جديدة.
يحسب هذا عدد إخفاقات الصفحة الصغرى. لم تتطلب هذه إدخالاً/إخراجاً للقرص لمعالجتها.
يحسب هذا عدد إخفاقات الصفحة الكبرى. تطلبت هذه إدخالاً/إخراجاً للقرص لمعالجتها.
يحسب هذا عدد أخطاء المحاذاة. تحدث هذه عند إجراء عمليات وصول غير محاذية للذاكرة؛ تستطيع النواة معالجة هذه الأخطاء ولكن ذلك يقلل من الأداء. يحدث هذا فقط في بعض المعماريات (أبداً على x86).
يحسب هذا عدد أخطاء المحاكاة. تصيد النواة أحياناً التعليمات غير المنفذة وتحاكيها لمساحة المستخدم. يمكن أن يؤثر هذا سلباً على الأداء.
هذا حدث نائِب لا يحسب شيئاً. يجب ربط أنواع سجلات العينات المعلوماتية مثل mmap أو comm بحدث نشط. يسمح هذا الحدث الوهمي بجمع مثل هذه السجلات دون الحاجة لحدث حاسِب.
يُستخدم هذا لتوليد بيانات عينات خام من BPF. يمكن لبرامج BPF الكتابة في هذا الحدث باستخدام المساعد bpf_perf_event_output.
يحسب هذا تبديلات السياق لمهمة في مجموعة تحكم (cgroup) مختلفة. بمعنى آخر، إذا كانت المهمة التالية في نفس مجموعة التحكم، فلن يُحسب التبديل.

إذا كان type هو PERF_TYPE_TRACEPOINT، فإننا نقيس نقاط تتبع النواة. يمكن الحصول على القيمة المستخدمة في config من مسار debugfs tracing/events/*/*/id إذا وُجد ftrace مفعلاً في النواة.

إذا كان type هو PERF_TYPE_HW_CACHE، فإننا نقيس حدث خبيئة وحدة معالجة مركزية عتادية. لحساب قيمة config المناسبة، استخدم المعادلة التالية:


config = (perf_hw_cache_id) |

(perf_hw_cache_op_id << 8) |
(perf_hw_cache_op_result_id << 16);

حيث perf_hw_cache_id هو واحد من:

لقياس خبيئة البيانات من المستوى 1
لقياس خبيئة التعليمات من المستوى 1
لقياس خبيئة المستوى الأخير
لقياس مخزن الترجمة المؤقت للبيانات (Data TLB)
لقياس مخزن الترجمة المؤقت للتعليمات (Instruction TLB)
لقياس وحدة التنبؤ بالتفرع
لقياس عمليات الوصول إلى الذاكرة المحلية

و perf_hw_cache_op_id هو واحد من:

لعمليات الوصول المخصصة للقراءة
لعمليات الوصول المخصصة للكتابة
لعمليات وصول الجلب المسبق

ويكون perf_hw_cache_op_result_id واحدًا مما يلي:

لقياس عمليات الوصول
لقياس الإخفاقات

إذا كان type هو PERF_TYPE_RAW، فستكون هناك حاجة إلى قيمة config "خام" مخصصة. تدعم معظم وحدات المعالجة المركزية أحداثًا لا تغطيها الأحداث "المعممة". هذه الأحداث محددة حسب التنفيذ؛ راجع دليل وحدة المعالجة المركزية (على سبيل المثال، وثائق Intel المجلد 3B، أو دليل مطور النواة و BIOS من AMD). يمكن استخدام مكتبة libpfm4 للترجمة من الاسم الموجود في الأدلة المعمارية إلى القيمة الست عشرية الخام التي يتوقعها perf_event_open() في هذا الحقل.

إذا كان type هو PERF_TYPE_BREAKPOINT، فاترك config مضبوطًا على الصفر. تُضبط معلماته في أماكن أخرى.

إذا كان type هو kprobe أو uprobe، فاضبط retprobe (البت 0 من config، راجع /sys/bus/event_source/devices/[k,u]probe/format/retprobe) لأجل kretprobe/uretprobe. راجع الحقول kprobe_func و uprobe_path و kprobe_addr و probe_offset لمزيد من التفاصيل.

تصف هذه الحقول kprobe/uprobe لوحدات PMU الديناميكية kprobe و uprobe. بالنسبة لـ kprobe: استخدم kprobe_func و probe_offset، أو استخدم kprobe_addr واترك kprobe_func كـ NULL. بالنسبة لـ uprobe: استخدم uprobe_path و probe_offset.
حدث "أخذ العينات" هو حدث يولد إشعار تجاوز السعة كل N من الأحداث، حيث تُعطى N بواسطة sample_period. يكون لحدث أخذ العينات sample_period أكبر من 0. وعند حدوث تجاوز للسعة، تُسجل البيانات المطلوبة في ذاكرة mmap الوسيطة. يتحكم الحقل sample_type في البيانات التي تُسجل عند كل تجاوز للسعة.
يمكن استخدام sample_freq إذا كنت ترغب في استخدام التردد بدلاً من الفترة. في هذه الحالة، تضبط علامة freq. ستقوم النواة بضبط فترة أخذ العينات لمحاولة تحقيق المعدل المطلوب. معدل الضبط هو تكة المؤقت.
تحدد البتات المختلفة في هذا الحقل القيم التي يجب تضمينها في العينة. ستُسجل في ذاكرة وسيطة حلقية، وهي متاحة لمساحة المستخدم باستخدام mmap(2). الترتيب الذي تُحفظ به القيم في العينة موثق في القسم الفرعي تخطيط MMAP أدناه؛ وليس ترتيب enum perf_event_sample_format.
يسجل مؤشر التعليمات.
يسجل معرفات العملية والمسار.
يسجل طابعًا زمنيًا.
يسجل عنوانًا، إذا كان ذلك متاحًا.
تسجيل قيم العداد لجميع الأحداث في مجموعة، وليس فقط قائد المجموعة.
يسجل سلسلة الاستدعاء (تتبع الكومة الخلفي).
يسجل معرفًا فريدًا لقائد مجموعة الأحداث المفتوحة.
يسجل رقم وحدة المعالجة المركزية.
يسجل فترة أخذ العينات الحالية.
يسجل معرفًا فريدًا للحدث المفتوح. على عكس PERF_SAMPLE_ID، يُعاد المعرف الفعلي، وليس قائد المجموعة. هذا المعرف هو نفسه الذي يعيده PERF_FORMAT_ID.
يسجل بيانات إضافية، إذا كان ذلك متاحًا. عادة ما تُعاد بواسطة أحداث نقطة التتبع.
يوفر هذا سجلاً للفروع الحديثة، كما توفره أجهزة أخذ عينات الفروع في وحدة المعالجة المركزية (مثل Intel Last Branch Record). لا تدعم كل الأجهزة هذه الميزة.
راجع حقل branch_sample_type لمعرفة كيفية تصفية الفروع التي يتم الإبلاغ عنها.
يسجل حالة سجل وحدة المعالجة المركزية الحالية على مستوى المستخدم (القيم الموجودة في العملية قبل استدعاء النواة).
يسجل كومة مستوى المستخدم، مما يسمح بفك الكومة.
يسجل قيمة وزن توفرها الأجهزة تعبر عن مدى تكلفة الحدث الذي تم أخذ عينة منه. يتيح ذلك للأجهزة إبراز الأحداث المكلفة في التشكيلة.
يسجل مصدر البيانات: من أين أتت البيانات المرتبطة بالتعليمات التي تم أخذ عينة منها في هرمية الذاكرة. يتوفر هذا فقط إذا كانت الأجهزة الأساسية تدعم هذه الميزة.
يضع قيمة SAMPLE_ID في موضع ثابت في السجل، إما في البداية (لأحداث العينة) أو في النهاية (إذا كان حدثًا ليس عينة).
كان هذا ضروريًا لأن دفق العينات قد يحتوي على سجلات من مصادر أحداث مختلفة مع إعدادات sample_type مختلفة. لم يكن من الممكن تحليل دفق الأحداث بشكل صحيح لأن تنسيق السجل كان مطلوبًا للعثور على SAMPLE_ID، ولكن تعذر العثور على التنسيق دون معرفة الحدث الذي تنتمي إليه العينة (مما يسبب تبعية دائرية).
يجعل إعداد PERF_SAMPLE_IDENTIFIER دفق الأحداث قابلاً للتحليل دائمًا عن طريق وضع SAMPLE_ID في موقع ثابت، على الرغم من أن ذلك يعني وجود قيم SAMPLE_ID مكررة في السجلات.
يسجل أسباب أحداث إجهاض الذاكرة التعاملية (على سبيل المثال، من دعم الذاكرة التعاملية Intel TSX).
يجب أن يكون إعداد precise_ip أكبر من 0 ويجب قياس حدث إجهاض الذاكرة التعاملية وإلا لن تُسجل أي قيم. لاحظ أيضًا أن بعض قياسات perf_event، مثل عد الدورات المأخوذ عينات منها، قد تسبب إجهاضات خارجية (عن طريق التسبب في مقاطعة أثناء المعاملة).
يسجل مجموعة فرعية من حالة سجل وحدة المعالجة المركزية الحالية كما هو محدد بواسطة sample_regs_intr. على عكس PERF_SAMPLE_REGS_USER، ستعيد قيم السجلات حالة سجل النواة إذا حدث التجاوز أثناء تشغيل كود النواة. إذا كانت وحدة المعالجة المركزية تدعم أخذ عينات الأجهزة لحالة السجل (أي، PEBS على Intel x86) وضُبط precise_ip على قيمة أعلى من الصفر، فإن قيم السجل المعادة هي تلك التي التقطتها الأجهزة في وقت تقاعد التعليمة التي أُخذ عينة منها.
يسجل العنوان الفيزيائي للبيانات كما في PERF_SAMPLE_ADDR.
يسجل معرف cgroup (perf_event) للعملية. يتوافق هذا مع حقل id في حدث PERF_RECORD_CGROUP.
يسجل حجم صفحة البيانات كما في PERF_SAMPLE_ADDR.
يسجل حجم صفحة ip كما في PERF_SAMPLE_IP.
يسجل قيم الوزن التي توفرها العتاد كما في PERF_SAMPLE_WEIGHT، ولكن يمكنه تمثيل قيم متعددة في بنية (struct). يتشارك هذا الحقل نفس المساحة مع PERF_SAMPLE_WEIGHT، لذا يمكن للمستخدمين تطبيق أحدهما وليس كلاهما. له التنسيق التالي ويعتمد معنى كل حقل على تطبيق العتاد.


union perf_sample_weight {

u64 full; /* PERF_SAMPLE_WEIGHT */
struct { /* PERF_SAMPLE_WEIGHT_STRUCT */
u32 var1_dw;
u16 var2_w;
u16 var3_w;
}; };

يحدد هذا الحقل تنسيق البيانات التي يعيدها read(2) في واصف ملف perf_event_open().
يضيف حقل time_enabled بطول 64 بت. يمكن استخدامه لحساب الإجماليات المقدرة إذا كانت وحدة مراقبة الأداء (PMU) مفرطة الالتزام ويحدث تعدد إرسال.
يضيف حقل time_running بطول 64 بت. يمكن استخدامه لحساب الإجماليات المقدرة إذا كانت وحدة مراقبة الأداء (PMU) مفرطة الالتزام ويحدث تعدد إرسال.
يضيف قيمة فريدة بطول 64 بت تقابل مجموعة الأحداث.
يسمح بقراءة جميع قيم العدادات في مجموعة أحداث بعملية قراءة واحدة.
يضيف قيمة بطول 64 بت تمثل عدد العينات المفقودة لهذا الحدث. لن يكون لهذا معنى إلا عند ضبط sample_period أو sample_freq.
تحدد بتة disabled ما إذا كان العداد سيبدأ معطلاً أم مفعلاً. إذا عُطل، يمكن تفعيل الحدث لاحقًا بواسطة ioctl(2) أو prctl(2) أو enable_on_exec.
عند إنشاء مجموعة أحداث، يُهيأ قائد المجموعة عادةً مع ضبط disabled على 1، وتُهيأ أي أحداث تابعة مع ضبط disabled على 0. وبالرغم من كون disabled بقيمة 0، لن تبدأ الأحداث التابعة حتى يُفعل قائد المجموعة.
تحدد بتة inherit وجوب قيام هذا العداد بعد أحداث المهام التابعة بالإضافة إلى المهمة المحددة. ينطبق هذا فقط على التوابع الجدد، وليس على أي توابع موجودين وقت إنشاء العداد (ولا على أي توابع جدد لتوابع موجودين).
لا تعمل الوراثة (Inherit) مع بعض تركيبات قيم read_format، مثل PERF_FORMAT_GROUP. بالإضافة إلى ذلك، فإن استخدامها مع cpu == -1 يمنع إنشاء مخزن mmap الدائري المستخدم لتسجيل الأحداث غير المتزامنة في نمط أخذ العينات.
تحدد بتة pinned وجوب بقاء العداد دائماً على المعالج إن أمكن ذلك. تنطبق فقط على العدادات العتادية وعلى قادة المجموعات فقط. إذا تعذر وضع عداد مثبت على المعالج (مثلاً لعدم كفاية العدادات العتادية أو بسبب تعارض مع حدث آخر)، ينتقل العداد إلى حالة 'خطأ'، حيث تعيد عمليات القراءة نهاية الملف (أي يعيد read(2) القيمة 0) حتى يُفعل العداد أو يُعطل لاحقًا.
تحدد بتة exclusive أنه عندما تكون مجموعة هذا العداد على المعالج، يجب أن تكون هي المجموعة الوحيدة التي تستخدم عدادات المعالج. قد يسمح هذا مستقبلاً لبرامج المراقبة بدعم ميزات وحدة مراقبة الأداء (PMU) التي تتطلب العمل بمفردها حتى لا تشوش على العدادات العتادية الأخرى.
لاحظ أن العديد من المواقف غير المتوقعة قد تمنع الأحداث التي ضُبطت فيها بتة exclusive من العمل نهائياً. يتضمن ذلك أي مستخدمين يشغلون قياساً على مستوى النظام، بالإضافة إلى أي استخدام للنواة لعدادات الأداء (بما في ذلك واجهة مؤقت مراقب NMI المفعلة عادةً).
إذا ضُبطت هذه البتة، يستثني العد الأحداث التي تقع في مساحة المستخدم.
إذا ضُبطت هذه البتة، يستثني العد الأحداث التي تقع في مساحة النواة.
إذا ضُبطت هذه البتة، يستثني العد الأحداث التي تقع في مشرف الأجهزة الافتراضية (hypervisor). هذا مخصص أساساً لوحدات مراقبة الأداء (PMUs) التي تدعم ذلك ذاتياً (مثل POWER). يلزم دعم إضافي للتعامل مع قياسات مشرف الأجهزة الافتراضية في معظم الأجهزة.
إذا ضُبطت، لا يُعد عندما يشغل المعالج مهمة الخمول. برغم أنه يمكن تفعيل هذا حالياً لأي نوع حدث، إلا أنه يُتجاهل لجميع الأحداث باستثناء الأحداث البرمجية.
تفعل بتة mmap توليد عينات PERF_RECORD_MMAP لكل استدعاء mmap(2) يكون فيه PROT_EXEC مضبوطاً. يسمح هذا للأدوات بملاحظة التعليمات البرمجية التنفيذية الجديدة التي تُربط ببرنامج ما (مثل المكتبات المشتركة الديناميكية) بحيث يمكن ربط العناوين بالتعليمات البرمجية الأصلية.
تفعل بتة comm تتبع اسم أمر العملية كما يُعدل بواسطة استدعاءات النظام execve(2) و prctl(PR_SET_NAME) بالإضافة إلى الكتابة في /proc/self/comm. إذا ضُبط علم comm_exec أيضًا بنجاح (ممكن منذ لينكس 3.16)، يمكن استخدام العلم المتنوع PERF_RECORD_MISC_COMM_EXEC للتمييز بين حالة execve(2) والحالات الأخرى.
إذا ضُبطت هذه البتة، يُستخدم sample_frequency وليس sample_period عند إعداد فاصل أخذ العينات الزمني.
تفعل هذه البتة حفظ أعداد الأحداث عند تبديل السياق للمهام الموروثة. لا يكون لهذا معنى إلا إذا كان حقل inherit مضبوطاً.
إذا ضُبطت هذه البتة، يُفعل العداد آلياً بعد استدعاء execve(2).
إذا ضُبطت هذه البتة، تُدرج إشعارات التفريع/الخروج في المخزن الدائري.
إذا ضُبطت، يقع إشعار فيض عند تجاوز حدود wakeup_watermark. وإلا، تقع إشعارات الفيض بعد عينات wakeup_events.
يتحكم هذا في مقدار الانزلاق (skid). الانزلاق هو عدد التعليمات المنفذة بين وقوع حدث مهم وتمكن النواة من التوقف وتسجيل الحدث. الانزلاق الأصغر أفضل ويسمح بتقرير أكثر دقة عن أي الأحداث يقابل أي التعليمات، ولكن غالباً ما يكون العتاد محدوداً في مدى صغر هذا المقدار.
القيم الممكنة لهذا الحقل هي كالتالي:
0
يمكن لـ SAMPLE_IP أن يحصل على انزلاق تعسفي.
1
يجب أن يكون لـ SAMPLE_IP انزلاق ثابت.
2
طُلب أن يكون لـ SAMPLE_IP انزلاق بقيمة 0.
3
يجب أن يكون لـ SAMPLE_IP انزلاق بقيمة 0. انظر أيضًا وصف PERF_RECORD_MISC_EXACT_IP.
هذا هو نظير حقل mmap. يفعل توليد عينات PERF_RECORD_MMAP لاستدعاءات mmap(2) التي ليس فيها PROT_EXEC مضبوطاً (على سبيل المثال البيانات وذاكرة SysV المشتركة).
إذا ضُبطت، يمكن بالإضافة إلى ذلك تضمين TID و TIME و ID و STREAM_ID و CPU في السجلات التي ليست من نوع PERF_RECORD_SAMPLE إذا اختير sample_type المقابل.
إذا حدد PERF_SAMPLE_IDENTIFIER، تُدرج قيمة ID إضافية كآخر قيمة لتسهيل تحليل تدفق السجلات. قد يؤدي هذا إلى ظهور قيمة id مرتين.
يوصف التخطيط بهذه البنية الوهمية:

struct sample_id {

{ u32 pid, tid; } /* if PERF_SAMPLE_TID set */
{ u64 time; } /* if PERF_SAMPLE_TIME set */
{ u64 id; } /* if PERF_SAMPLE_ID set */
{ u64 stream_id;} /* if PERF_SAMPLE_STREAM_ID set */
{ u32 cpu, res; } /* if PERF_SAMPLE_CPU set */
{ u64 id; } /* if PERF_SAMPLE_IDENTIFIER set */ };

عند إجراء قياسات تتضمن عمليات تشغل مثيلات الأجهزة الافتراضية (أي التي نفذت KVM_RUN ioctl(2))، لا تُقاس إلا الأحداث التي تقع داخل مثيلة ضيف. لا يكون لهذا معنى إلا خارج الضيوف؛ هذا الإعداد لا يغير الأعداد المجموعة داخل الضيف. حالياً، هذه الوظيفة مقتصرة على x86 فقط.
عند إجراء قياسات تتضمن عمليات تشغل مثيلات الأجهزة الافتراضية (أي التي نفذت KVM_RUN ioctl(2))، لا تُقاس الأحداث التي تقع داخل مثيلات الضيف. لا يكون لهذا معنى إلا خارج الضيوف؛ هذا الإعداد لا يغير الأعداد المجموعة داخل الضيف. حالياً، هذه الوظيفة مقتصرة على x86 فقط.
لا تُدرج تسلسلات استدعاء النواة.
لا تُدرج تسلسلات استدعاء المستخدم.
ولّد سجل mmap تنفيذيًّا ممتدًّا يحتوي على معلومات إضافية كافية لتمييز التعيينات المشتركة بشكل فريد. يجب أيضًا ضبط علم mmap ليعمل هذا.
هذا علم لاكتشاف الميزات فحسب، ولا يغير سلوك النواة. إذا ضُبط هذا العلم بنجاح، فعند تمكين comm، سيُضبط علم PERF_RECORD_MISC_COMM_EXEC في حقل misc لترويسة سجل comm إذا كان حدث إعادة التسمية المُبلغ عنه ناتجًا عن استدعاء execve(2). يتيح هذا للأدوات التمييز بين الأنواع المختلفة لإعادة تسمية العمليات.
يسمح هذا باختيار أي ساعة لينكس داخلية تُستخدم عند توليد الطوابع الزمنية عبر حقل clockid. يمكن أن يسهل هذا ربط أوقات عينات الأداء (perf) بالطوابع الزمنية التي تولدها أدوات أخرى.
يُمكّن هذا توليد سجلات PERF_RECORD_SWITCH عند حدوث تبديل سياق. كما يُمكّن توليد سجلات PERF_RECORD_SWITCH_CPU_WIDE عند أخذ العينات في وضع CPU-wide. هذه الوظيفة هي إضافة إلى نقاط التتبع (tracepoint) وأحداث البرمجيات الموجودة لقياس تبديلات السياق. ميزة هذه الطريقة هي أنها ستعطي معلومات كاملة حتى مع إعدادات perf_event_paranoid الصارمة.
يؤدي هذا إلى كتابة المخزن المؤقت الحلقي (ring buffer) من النهاية إلى البداية. هذا لدعم القراءة من مخزن مؤقت حلقي قابل للكتابة فوقه.
يُمكّن هذا توليد سجلات PERF_RECORD_NAMESPACES عندما تدخل مهمة ما في مساحة أسماء جديدة. كل مساحة أسماء لها مزيج من أرقام الأجهزة وأرقام العقد الفهرسية (inode).
يُمكّن هذا توليد سجلات PERF_RECORD_KSYMBOL عند تسجيل رموز نواة جديدة أو إلغاء تسجيلها. يُستخدم هذا لتحليل وظائف النواة الديناميكية مثل eBPF.
يُمكّن هذا توليد سجلات PERF_RECORD_BPF_EVENT عند تحميل برنامج eBPF أو إلغاء تحميله.
يسمح هذا للأحداث العادية (غير AUX) بتوليد بيانات لأحداث AUX إذا كان العتاد يدعم ذلك.
يُمكّن هذا توليد سجلات PERF_RECORD_CGROUP عند إنشاء (وتنشيط) مجموعة تحكم (cgroup) جديدة.
يُمكّن هذا توليد سجلات PERF_RECORD_TEXT_POKE عندما يطرأ تغيير على نص النواة (أي الكود المتمور أو المعدل ذاتيًّا).
يغير هذا محتويات PERF_RECORD_MMAP2 لتحتوي على معرف بناء (build-id) بدلًا من أرقام الأجهزة والعقد الفهرسية (inode).
يعطل هذا توريث الحدث لعملية فرعية. فقط الخيوط الجديدة في نفس العملية (التي تُنسخ باستخدام CLONE_THREAD) هي من سيرث الحدث.
يغلق هذا الحدث عندما يبدأ صورة عملية جديدة بواسطة execve(2).
يُمكّن هذا تسليم إشارة SIGTRAP المتزامنة عند فيض الحدث.
تحدد هذه الوحدة (union) عدد العينات (wakeup_events) أو البايتات (wakeup_watermark) التي تحدث قبل حدوث إشعار بالفيض. ويُختار أيهما يُستخدم بواسطة علم بت watermark.
يعد wakeup_events أنواع سجلات PERF_RECORD_SAMPLE فقط. لتلقي إشعار بالفيض لجميع أنواع PERF_RECORD اختر watermark واضبط wakeup_watermark على 1.
قبل لينكس 3.0، كان ضبط wakeup_events على 0 يؤدي لعدم وجود إشعارات فيض؛ النوى الأحدث تعامل 0 معاملة 1.
يختار هذا نوع نقطة التوقف. وهو واحد من:
لا توجد نقطة توقف.
العّد عند قراءة موقع الذاكرة.
العّد عند الكتابة في موقع الذاكرة.
العّد عند قراءة أو الكتابة في موقع الذاكرة.
العّد عند تنفيذ كود في موقع الذاكرة.

يمكن دمج القيم عبر أو (OR) المنطقية، ولكن دمج HW_BREAKPOINT_R أو HW_BREAKPOINT_W مع HW_BREAKPOINT_X غير مسموح به.

هذا هو عنوان نقطة التوقف. بالنسبة لنقاط توقف التنفيذ، هذا هو عنوان الذاكرة للتعليمة المعنية؛ بالنسبة لنقاط توقف القراءة والكتابة، فهو عنوان الذاكرة لموقع الذاكرة المعني.
يُستخدم config1 لضبط الأحداث التي تحتاج إلى سجل إضافي أو التي لا تتناسب مع حقل config العادي. تستخدم أحداث OFFCORE_EVENTS الخام على معالجات Nehalem/Westmere/SandyBridge هذا الحقل في نواة لينكس 3.3 والإصدارات الأحدث.
bp_len هو حجم نقطة التوقف التي تُقاس إذا كان type هو PERF_TYPE_BREAKPOINT. الخيارات هي HW_BREAKPOINT_LEN_1، و HW_BREAKPOINT_LEN_2، و HW_BREAKPOINT_LEN_4، و HW_BREAKPOINT_LEN_8. لنقطة توقف تنفيذ، اضبط هذا على sizeof(long).
config2 هو امتداد إضافي لحقل config1.
إذا مُكّن PERF_SAMPLE_BRANCH_STACK، فهذا يحدد الفروع التي يجب تضمينها في سجل الفروع.
الجزء الأول من القيمة هو مستوى الامتياز، وهو مزيج من إحدى القيم المدرجة أدناه. إذا لم يضبط المستخدم مستوى الامتياز صراحةً، فستستخدم النواة مستوى امتياز الحدث. لا يلزم تطابق مستويات امتياز الحدث والفرع.
هدف الفرع في مساحة المستخدم.
هدف الفرع في مساحة النواة.
هدف الفرع في المفرط (hypervisor).
قيمة ملائمة هي نتاج دمج القيم الثلاث السابقة باستخدام معامل OR المنطقي.

بالإضافة إلى قيمة الامتياز، يجب ضبط بت واحد على الأقل من البتات التالية.

أي نوع من أنواع الفروع.
أي فرع استدعاء (يشمل الاستدعاءات المباشرة، والاستدعاءات غير المباشرة، والقفزات البعيدة).
الاستدعاءات غير المباشرة.
الاستدعاءات المباشرة.
أي فرع عودة.
القفزات غير المباشرة.
الفروع الشرطية.
إجهاضات الذاكرة التحويلية.
فرع داخل معاملة ذاكرة تحويلية.
فرع ليس في معاملة ذاكرة تحويلية. PERF_SAMPLE_BRANCH_CALL_STACK (منذ لينكس 4.1) الفرع جزء من مكدس استدعاء مُولّد عتاديًا. يتطلب هذا دعمًا عتاديًا، لا يتوفر حاليًا إلا في معالجات Intel x86 من عائلة Haswell أو أحدث.
يحدد قناع البتات هذا مجموعة سجلات وحدة المعالجة المركزية الخاصة بالمستخدم لتفريغها عند أخذ العينات. تخطيط قناع السجلات خاص بالبنية المعمارية وموصوف في ملف ترويسة النواة arch/ARCH/include/uapi/asm/perf_regs.h.
يحدد هذا حجم مكدس المستخدم المراد تفريغه إذا حُدد PERF_SAMPLE_STACK_USER.
إذا ضُبط use_clockid، يختار هذا الحقل أي مؤقت لينكس داخلي سيُستخدم للطوابع الزمنية. المؤقتات المتاحة مُعرفة في linux/time.h، مع دعم CLOCK_MONOTONIC و CLOCK_MONOTONIC_RAW و CLOCK_REALTIME و CLOCK_BOOTTIME و CLOCK_TAI حاليًا.
يحدد هذا مقدار البيانات المطلوبة لإطلاق عينة PERF_RECORD_AUX.
عندما يتضمن sample_type القيمة PERF_SAMPLE_CALLCHAIN، يحدد هذا الحقل عدد إطارات المكدس التي سيُبلغ عنها عند توليد سلسلة الاستدعاءات.
عند ضبط علامة PERF_SAMPLE_AUX، حدد الحجم المطلوب لبيانات AUX. لاحظ أنه قد يتم الحصول على بيانات أصغر من الحجم المحدد.
ستُنسخ هذه البيانات إلى معالج إشارات المستخدم (عبر si_perf في siginfo_t) لإزالة اللبس حول أي حدث أطلق الإشارة.

قراءة النتائج

بمجرد فتح واصف ملف perf_event_open()، يمكن قراءة قيم الأحداث من واصف الملف. القيم الموجودة هناك يحددها حقل read_format في بنية attr عند وقت الفتح.

إذا حاولت القراءة في مخزن مؤقت ليس كبيرًا بما يكفي لاحتواء البيانات، فستنتج الخطأ ENOSPC.

إليك تخطيط البيانات التي تعيدها عملية القراءة:

إذا حُدد PERF_FORMAT_GROUP للسماح بقراءة جميع الأحداث في مجموعة دفعة واحدة:

struct read_format {

u64 nr; /* عدد الأحداث */
u64 time_enabled; /* إذا حُدد PERF_FORMAT_TOTAL_TIME_ENABLED */
u64 time_running; /* إذا حُدد PERF_FORMAT_TOTAL_TIME_RUNNING */
struct {
u64 value; /* قيمة الحدث */
u64 id; /* إذا حُدد PERF_FORMAT_ID */
u64 lost; /* إذا حُدد PERF_FORMAT_LOST */
} values[nr]; };

إذا لم يُحدد PERF_FORMAT_GROUP:

struct read_format {

u64 value; /* قيمة الحدث */
u64 time_enabled; /* إذا حُدد PERF_FORMAT_TOTAL_TIME_ENABLED */
u64 time_running; /* إذا حُدد PERF_FORMAT_TOTAL_TIME_RUNNING */
u64 id; /* إذا حُدد PERF_FORMAT_ID */
u64 lost; /* إذا حُدد PERF_FORMAT_LOST */ };

القيم المقروءة هي كما يلي:

عدد الأحداث في واصف الملف هذا. متاح فقط إذا حُدد PERF_FORMAT_GROUP.
إجمالي الوقت الذي كان فيه الحدث مُمكنًا وقيد التشغيل. عادة ما تكون هذه القيم متماثلة. يحدث تعدد الإرسال (Multiplexing) إذا كان عدد الأحداث أكثر من عدد فتحات عداد PMU المتاحة. في هذه الحالة، تعمل الأحداث لجزء من الوقت فقط، ويمكن استخدام قيم time_enabled و time_running لقياس قيمة تقديرية للعدد.
قيمة غير موقعة بطول 64 بت تحتوي على نتيجة العداد.
قيمة فريدة عالميًا لهذا الحدث المعين؛ تظهر فقط إذا حُدد PERF_FORMAT_ID في read_format.
عدد العينات المفقودة لهذا الحدث؛ تظهر فقط إذا حُدد PERF_FORMAT_LOST في read_format.

تخطيط MMAP

عند استخدام perf_event_open() في وضع أخذ العينات، تُسجل الأحداث غير المتزامنة (مثل تجاوز العداد أو تتبع mmap لـ PROT_EXEC) في مخزن حلقي مؤقت. يُنشأ هذا المخزن الحلقي المؤقت ويُوصَل إليه عبر mmap(2).

يجب أن يكون حجم mmap هو 1+2^n صفحة، حيث تكون الصفحة الأولى صفحة بيانات وصفية (struct perf_event_mmap_page) تحتوي على معلومات متنوعة مثل مكان رأس المخزن الحلقي المؤقت.

قبل لينكس 2.6.39، كانت هناك علة تعني أنه يجب عليك تخصيص مخزن حلقي مؤقت لـ mmap عند أخذ العينات حتى لو لم تكن تخطط للوصول إليه.

بنية أول صفحة بيانات وصفية لـ mmap هي كما يلي:


struct perf_event_mmap_page {

__u32 version; /* رقم إصدار هذه البنية */
__u32 compat_version; /* أدنى إصدار تتوافق معه */
__u32 lock; /* قفل تسلسلي (seqlock) للمزامنة */
__u32 index; /* معرف عداد العتاد */
__s64 offset; /* يُضاف إلى قيمة عداد العتاد */
__u64 time_enabled; /* وقت نشاط الحدث */
__u64 time_running; /* وقت وجود الحدث على وحدة المعالجة المركزية */
union {
__u64 capabilities;
struct {
__u64 cap_usr_time / cap_usr_rdpmc / cap_bit0 : 1,
cap_bit0_is_deprecated : 1,
cap_user_rdpmc : 1,
cap_user_time : 1,
cap_user_time_zero : 1,
};
};
__u16 pmc_width;
__u16 time_shift;
__u32 time_mult;
__u64 time_offset;
__u64 __reserved[120]; /* حشو حتى 1 كيلوبايت */
__u64 data_head; /* الرأس في قسم البيانات */
__u64 data_tail; /* الذيل المكتوب من مساحة المستخدم */
__u64 data_offset; /* مكان بدء المخزن المؤقت */
__u64 data_size; /* حجم مخزن البيانات المؤقت */
__u64 aux_head;
__u64 aux_tail;
__u64 aux_offset;
__u64 aux_size; }

تصف القائمة التالية الحقول في بنية perf_event_mmap_page بمزيد من التفصيل:

الإصدار
رقم إصدار هذه البنية.
إصدار_التوافق
أدنى إصدار تتوافق معه هذه البنية.
القفل
قفل تسلسلي (seqlock) للمزامنة.
معرف فريد لعدادات العتاد.
عند استخدام rdpmc للقراءات، يجب إضافة قيمة offset هذه إلى القيمة التي تعيدها rdpmc للحصول على إجمالي عدد الأحداث الحالي.
الوقت الذي كان فيه الحدث نشطًا.
الوقت الذي كان فيه الحدث قيد التشغيل.
وُجدت علة في تعريف cap_usr_time و cap_usr_rdpmc من لينكس 3.4 حتى لينكس 3.11. عُرّف كلا البتين للإشارة إلى الموقع نفسه، لذا كان من المستحيل معرفة ما إذا كان قد ضُبط cap_usr_time أو cap_usr_rdpmc فعليًا.
بدءًا من لينكس 3.12، غُيرت أسماؤها إلى cap_bit0 وينبغي عليك استخدام حقول cap_user_time و cap_user_rdpmc بدلًا منها.
إذا ضُبط هذا البت، فإنه يشير إلى أن النواة تدعم بتات cap_user_time و cap_user_rdpmc المفصولة بشكل سليم.
إذا لم يُضبط، فإنه يشير إلى نواة قديمة حيث ترتبط cap_usr_time و cap_usr_rdpmc بالبت نفسه وبالتالي يجب استخدام كلتا الميزتين بحذر.
إذا كان العتاد يدعم قراءة عدادات الأداء من مساحة المستخدم دون استدعاء نظام (هذه هي تعليمة "rdpmc" على x86)، فيمكن استخدام الشيفرة التالية لإجراء القراءة:

u32 seq, time_mult, time_shift, idx, width;
u64 count, enabled, running;
u64 cyc, time_offset;
do {

seq = pc->lock;
barrier();
enabled = pc->time_enabled;
running = pc->time_running;
if (pc->cap_usr_time && enabled != running) {
cyc = rdtsc();
time_offset = pc->time_offset;
time_mult = pc->time_mult;
time_shift = pc->time_shift;
}
idx = pc->index;
count = pc->offset;
if (pc->cap_usr_rdpmc && idx) {
width = pc->pmc_width;
count += rdpmc(idx - 1);
}
barrier(); } while (pc->lock != seq);

يشير هذا البت إلى أن العتاد يحتوي على عداد طابع زمني ثابت لا يتوقف (TSC على x86).
يشير إلى وجود time_zero الذي يسمح بربط قيم الطابع الزمني بساعة العتاد.
في حال وجود cap_usr_rdpmc، يوفر هذا الحقل عرض البت للقيمة المقروءة باستخدام rdpmc أو تعليمة مكافئة. يمكن استخدام هذا لتوسيع إشارة النتيجة مثل:

pmc <<= 64 - pmc_width;
pmc >>= 64 - pmc_width;  // إزاحة يمين مع إشارة
count += pmc;
    

في حال وجود cap_usr_time، يمكن استخدام هذه الحقول لحساب فارق الوقت منذ time_enabled (بالنانوثانية) باستخدام rdtsc أو ما شابه.

u64 quot, rem;
u64 delta;
quot  = cyc >> time_shift;
rem   = cyc & (((u64)1 << time_shift) - 1);
delta = time_offset + quot * time_mult +

((rem * time_mult) >> time_shift);

حيث تُقرأ time_offset و time_mult و time_shift و cyc في حلقة seqcount الموضحة أعلاه. يمكن بعد ذلك إضافة هذا الفارق (delta) إلى الوقت المُمكّن (enabled) والمشغل المحتمل (running) (إذا وُجد idx)، مما يحسن القياس:

enabled += delta;
if (idx)

running += delta; quot = count / running; rem = count % running; count = quot * enabled + (rem * enabled) / running;

إذا ضُبط cap_usr_time_zero، فيمكن حساب ساعة العتاد (عداد الطابع الزمني TSC على x86) من قيم time_zero و time_mult و time_shift:

time = timestamp - time_zero;
quot = time / time_mult;
rem  = time % time_mult;
cyc  = (quot << time_shift) + (rem << time_shift) / time_mult;
    

والعكس صحيح:

quot = cyc >> time_shift;
rem  = cyc & (((u64)1 << time_shift) - 1);
timestamp = time_zero + quot * time_mult +

((rem * time_mult) >> time_shift);

يشير هذا إلى رأس قسم البيانات. تزداد القيمة باستمرار، ولا تلتف. يجب لف القيمة يدويًا بحجم وسيط mmap قبل الوصول إلى العينات.
في المنصات التي تدعم SMP، بعد قراءة قيمة data_head، يجب على مساحة المستخدم إصدار rmb().
عندما يكون الربط PROT_WRITE، يجب كتابة قيمة data_tail بواسطة مساحة المستخدم لتعكس آخر بيانات وُصل إليها. في هذه الحالة، لن تكتب النواة فوق البيانات غير المقروءة.
يحتوي على إزاحة الموقع في وسيط mmap حيث تبدأ بيانات عينة الأداء.
يحتوي على حجم منطقة عينة الأداء داخل وسيط mmap.
تسمح منطقة AUX بإجراء mmap(2) لوسيط عينة منفصل لتدفقات البيانات ذات النطاق الترددي العالي (منفصل عن وسيط عينة الأداء الرئيس). من الأمثلة على تدفقات النطاق الترددي العالي دعم تتبع التعليمات، كما هو موجود في معالجات Intel الأحدث.
لإعداد منطقة AUX، يجب أولاً ضبط aux_offset بإزاحة أكبر من data_offset+data_size ويجب ضبط aux_size على حجم الوسيط المطلوب. يجب أن تكون الإزاحة والحجم المطلوبان متحاذيين مع الصفحة، ويجب أن يكون الحجم من مضاعفات القوة اثنين. تُمرر هذه القيم بعد ذلك إلى mmap لربط وسيط AUX. تُدرج الصفحات في وسيط AUX كجزء من حد الموارد RLIMIT_MEMLOCK (انظر setrlimit(2))، وأيضًا كجزء من مخصص perf_event_mlock_kb.
بشكل مبدئي، سيُبتر وسيط AUX إذا لم يتسع في المساحة المتاحة في الوسيط الدائري. إذا رُبط وسيط AUX كوسيط للقراءة فقط، فسيعمل في وضع الوسيط الدائري حيث تُستبدل البيانات القديمة ببيانات جديدة. في وضع الكتابة فوق البيانات، قد لا يكون من الممكن استنتاج أين بدأت البيانات الجديدة، وتكون مهمة المستهلك تعطيل القياس أثناء القراءة لتجنب سباقات البيانات المحتملة.
تتبع مؤشرات الوسيط الدائري aux_head و aux_tail السلوك نفسه وقواعد الترتيب الخاصة بـ data_head و data_tail الموصوفة سابقًا.

صفحات الوسيط الدائري 2^n التالية لها التخطيط الموصوف أدناه.

إذا ضُبط perf_event_attr.sample_id_all، فستحتوي جميع أنواع الأحداث على حقول sample_type المحددة المتعلقة بمكان/زمان (هوية) وقوع الحدث (TID, TIME, ID, CPU, STREAM_ID) الموضحة في PERF_RECORD_SAMPLE أدناه، وسيُخزن مباشرة بعد perf_event_header والحقول الموجودة بالفعل للحقول الحالية، أي في نهاية الحمولة. يسمح هذا بدعم ملف perf.data أحدث بواسطة أدوات perf قديمة، مع تجاهل الحقول الاختيارية الجديدة.

تبدأ قيم mmap بترويسة:


struct perf_event_header {

__u32 type;
__u16 misc;
__u16 size; };

أدناه، نصف حقول perf_event_header بمزيد من التفصيل. لسهولة القراءة، تُعرض الحقول ذات الأوصاف الأقصر أولاً.

يشير هذا إلى حجم السجل.
يحتوي الحقل misc على معلومات إضافية حول العينة.
يمكن تحديد وضع وحدة المعالجة المركزية من هذه القيمة عن طريق القناع بـ PERF_RECORD_MISC_CPUMODE_MASK والبحث عن أحد ما يلي (لاحظ أن هذه ليست أقنعة بتات، يمكن ضبط واحد فقط في كل مرة):
وضع وحدة معالجة مركزية مجهول.
حدثت العينة في النواة.
حدثت العينة في كود المستخدم.
حدثت العينة في برنامج مراقبة الأجهزة الافتراضية.
حدثت العينة في نواة الضيف.
حدثت العينة في كود مستخدم ضيف.

بما أن الحالات الثلاث التالية تُولَّد بواسطة أنواع سجلات مختلفة، فإنها تشير إلى نفس البت:
يُضبط هذا عندما لا يكون التعيين (mapping) قابلاً للتنفيذ؛ وإلا فإن التعيين يكون قابلاً للتنفيذ.
يُضبط هذا لسجل PERF_RECORD_COMM في النوى الأحدث من Linux 3.16 إذا كان تغيير اسم العملية ناتجًا عن استدعاء نظام execve(2).
عند توليد سجل PERF_RECORD_SWITCH أو PERF_RECORD_SWITCH_CPU_WIDE، يشير هذا البت إلى أن تبديل السياق بعيد عن العملية الحالية (بدلاً من الانتقال إلى العملية الحالية).

بالإضافة إلى ذلك، يمكن ضبط البتات التالية:
يشير هذا إلى أن محتوى PERF_SAMPLE_IP يشير إلى التعليمة الفعلية التي أطلقت الحدث. انظر أيضًا perf_event_attr.precise_ip.
عند توليد سجل PERF_RECORD_SWITCH أو PERF_RECORD_SWITCH_CPU_WIDE، يشير هذا إلى أن تبديل السياق كان استباقاً (preemption).
يشير هذا إلى أن محتوى PERF_SAMPLE_MMAP2 يحتوي على بيانات معرف البناء (build-ID) بدلاً من أرقام الجهاز الرئيسية والثانوية ورقم الفهرس (inode).
يشير هذا إلى وجود بيانات ممتدة متاحة (لا تُستخدم حاليًا).
لا تُضبط هذه البتة بواسطة النواة. إنها محجوزة لأداة perf في مساحة المستخدم للإشارة إلى أن تحليل /proc/pid/maps استغرق وقتًا طويلاً ووقِف، وبالتالي قد تُبتر سجلات mmap.
قيمة type هي واحدة مما يلي. تعتمد القيم في السجل المقابل (الذي يلي الترويسة) على type المحدد كما هو موضح.
تسجل أحداث MMAP تعيينات PROT_EXEC حتى نتمكن من ربط عناوين IP في مساحة المستخدم بالكود. ولها البنية التالية:

struct {

struct perf_event_header header;
u32 pid, tid;
u64 addr;
u64 len;
u64 pgoff;
char filename[]; };

هو معرف العملية.
هو معرف الخيط.
هو عنوان الذاكرة المخصصة. len هو حجم الذاكرة المخصصة. pgoff هو إزاحة الصفحة للذاكرة المخصصة. filename هو سلسلة نصية تصف ما وراء الذاكرة المخصصة.
يشير هذا السجل إلى وقت فقدان الأحداث.

struct {

struct perf_event_header header;
u64 id;
u64 lost;
struct sample_id sample_id; };

هو معرف الحدث الفريد للعينات التي فُقدت.
هو عدد الأحداث التي فُقدت.
يشير هذا السجل إلى تغيير في اسم العملية.

struct {

struct perf_event_header header;
u32 pid;
u32 tid;
char comm[];
struct sample_id sample_id; };

هو معرف العملية.
هو معرف الخيط.
هو سلسلة نصية تحتوي على الاسم الجديد للعملية.
يشير هذا السجل إلى حدث خروج عملية.

struct {

struct perf_event_header header;
u32 pid, ppid;
u32 tid, ptid;
u64 time;
struct sample_id sample_id; };

يشير هذا السجل إلى حدث تقييد/إلغاء تقييد (throttle/unthrottle).

struct {

struct perf_event_header header;
u64 time;
u64 id;
u64 stream_id;
struct sample_id sample_id; };

يشير هذا السجل إلى حدث تشعب (fork).

struct {

struct perf_event_header header;
u32 pid, ppid;
u32 tid, ptid;
u64 time;
struct sample_id sample_id; };

يشير هذا السجل إلى حدث قراءة.

struct {

struct perf_event_header header;
u32 pid, tid;
struct read_format values;
struct sample_id sample_id; };

يشير هذا السجل إلى عينة.

struct {

struct perf_event_header header;
u64 sample_id; /* if PERF_SAMPLE_IDENTIFIER */
u64 ip; /* if PERF_SAMPLE_IP */
u32 pid, tid; /* if PERF_SAMPLE_TID */
u64 time; /* if PERF_SAMPLE_TIME */
u64 addr; /* if PERF_SAMPLE_ADDR */
u64 id; /* if PERF_SAMPLE_ID */
u64 stream_id; /* if PERF_SAMPLE_STREAM_ID */
u32 cpu, res; /* if PERF_SAMPLE_CPU */
u64 period; /* if PERF_SAMPLE_PERIOD */
struct read_format v;
/* if PERF_SAMPLE_READ */
u64 nr; /* if PERF_SAMPLE_CALLCHAIN */
u64 ips[nr]; /* if PERF_SAMPLE_CALLCHAIN */
u32 size; /* if PERF_SAMPLE_RAW */
char data[size]; /* if PERF_SAMPLE_RAW */
u64 bnr; /* if PERF_SAMPLE_BRANCH_STACK */
struct perf_branch_entry lbr[bnr];
/* if PERF_SAMPLE_BRANCH_STACK */
u64 abi; /* if PERF_SAMPLE_REGS_USER */
u64 regs[weight(mask)];
/* if PERF_SAMPLE_REGS_USER */
u64 size; /* if PERF_SAMPLE_STACK_USER */
char data[size]; /* if PERF_SAMPLE_STACK_USER */
u64 dyn_size; /* if PERF_SAMPLE_STACK_USER &&
size != 0 */
union perf_sample_weight weight;
/* if PERF_SAMPLE_WEIGHT */
/* || PERF_SAMPLE_WEIGHT_STRUCT */
u64 data_src; /* if PERF_SAMPLE_DATA_SRC */
u64 transaction; /* if PERF_SAMPLE_TRANSACTION */
u64 abi; /* if PERF_SAMPLE_REGS_INTR */
u64 regs[weight(mask)];
/* if PERF_SAMPLE_REGS_INTR */
u64 phys_addr; /* if PERF_SAMPLE_PHYS_ADDR */
u64 cgroup; /* if PERF_SAMPLE_CGROUP */
u64 data_page_size;
/* if PERF_SAMPLE_DATA_PAGE_SIZE */
u64 code_page_size;
/* if PERF_SAMPLE_CODE_PAGE_SIZE */
u64 size; /* if PERF_SAMPLE_AUX */
char data[size]; /* if PERF_SAMPLE_AUX */ };

إذا مكنت PERF_SAMPLE_IDENTIFIER، سيُدرج معرف فريد 64 بت. هذا تكرار لقيمة id في PERF_SAMPLE_ID، ولكنه مدرج في بداية العينة حتى تتمكن المحللات من الحصول على القيمة بسهولة.
إذا مكنت PERF_SAMPLE_IP، فستُدرج قيمة مؤشر تعليمات 64 بت.
إذا مكنت PERF_SAMPLE_TID، فسيُدرج معرف عملية 32 بت ومعرف خيط 32 بت.
إذا مكنت PERF_SAMPLE_TIME، فسيُدرج طابع زمني 64 بت. يُحصل على هذا عبر local_clock() وهو طابع زمني للأجهزة إذا كان متاحًا وقيمة jiffies إذا لم يكن كذلك.
إذا مكنت PERF_SAMPLE_ADDR، فسيُدرج عنوان 64 بت. يكون هذا عادةً عنوان نقطة تتبع، أو نقطة توقف، أو حدث برمجي؛ وإلا فإن القيمة تكون 0.
إذا مكنت PERF_SAMPLE_ID، سيُدرج معرف فريد 64 بت. إذا كان الحدث عضواً في مجموعة أحداث، فسيُرجع معرف قائد المجموعة. هذا المعرف هو نفسه الذي يرجعه PERF_FORMAT_ID.
إذا مكنت PERF_SAMPLE_STREAM_ID، سيُدرج معرف فريد 64 بت. على عكس PERF_SAMPLE_ID يُرجع المعرف الفعلي، وليس قائد المجموعة. هذا المعرف هو نفسه الذي يرجعه PERF_FORMAT_ID.
وحدة المعالجة المركزية
إذا مكنت PERF_SAMPLE_CPU، فهذه قيمة 32 بت تشير إلى وحدة المعالجة المركزية التي كانت قيد الاستخدام، بالإضافة إلى قيمة 32 بت محجوزة (غير مستخدمة).
إذا مكنت PERF_SAMPLE_PERIOD، فستُكتب قيمة 64 بت تشير إلى فترة المعاينة الحالية.
إذا فُعِّل PERF_SAMPLE_READ، فستُدرج بنية من النوع read_format تحتوي على قيم لكل الأحداث في مجموعة الأحداث. تعتمد القيم المُدرجة على قيمة read_format المستخدمة وقت perf_event_open().
إذا فُعِّل PERF_SAMPLE_CALLCHAIN، فسيُدرج رقم 64-بت يشير إلى عدد مؤشرات التعليمات (instruction pointers) التالية ذات 64-بت التي ستتبع. هذا هو تسلسل الاستدعاء الحالي.
إذا فُعِّل PERF_SAMPLE_RAW، فستُدرج قيمة 32-بت تشير إلى الحجم، تليها مصفوفة من قيم 8-بت بحجم size. تُحشى القيم بالأصفار لتحقيق محاذاة 64-بت.
بيانات السجل الخام (RAW) هذه مبهمة بالنسبة لواجهة التطبيق الثنائية (ABI). لا تقدم واجهة ABI أي وعود فيما يتعلق باستقرار محتواها، فقد تختلف بناءً على الحدث، والعتاد، وإصدار النواة (Kernel).
إذا فُعِّل PERF_SAMPLE_BRANCH_STACK، فستُدرج قيمة 64-بت تشير إلى عدد السجلات، تليها bnr من بنيات perf_branch_entry التي يتضمن كل منها الحقول التالية:
يشير هذا إلى تعليمة المصدر (قد لا تكون فرعًا).
هدف الفرع.
أُسيء التنبؤ بهدف الفرع.
تُنُبئ بهدف الفرع.
كان الفرع ضمن معاملة ذاكرة تعاملية (transactional memory transaction).
كان الفرع ضمن معاملة ذاكرة تعاملية مُجهضة.
يبلغ هذا عن عدد الدورات (cycles) المنقضية منذ التحديث السابق لمكدس الفروع (branch stack).

تُرتب المدخلات من الأحدث إلى الأقدم، لذا فإن المدخل الأول يحتوي على أحدث فرع.

دعم mispred و predicted و cycles اختياري؛ وإذا لم تكن مدعومة، فستكون هذه القيم 0.

نوع الفروع المسجلة يُحدد بواسطة حقل branch_sample_type.

إذا فُعِّل PERF_SAMPLE_REGS_USER، فتُسجل سجلات وحدة المعالجة المركزية (CPU) للمستخدم.
يكون حقل abi واحدًا من PERF_SAMPLE_REGS_ABI_NONE، أو PERF_SAMPLE_REGS_ABI_32، أو PERF_SAMPLE_REGS_ABI_64.
حقل regs هو مصفوفة من سجلات CPU التي حُددت بواسطة حقل sample_regs_user في السمات (attr). عدد القيم هو عدد البتات المضبطة في قناع البتات sample_regs_user.
إذا فُعِّل PERF_SAMPLE_STACK_USER، فسيُسجل مكدس المستخدم. يمكن استخدام هذا لإنشاء تتبعات خلفية للمكدس (backtraces). يمثل size الحجم الذي طلبه المستخدم في sample_stack_user أو أقصى حجم للسجل. data هي بيانات المكدس (تفريغ خام للذاكرة التي يشير إليها مؤشر المكدس وقت أخذ العينات). dyn_size هو كمية البيانات التي فُرغت فعليًا (يمكن أن تكون أقل من size). لاحظ أن dyn_size يُحذف إذا كان size هو 0.
إذا فُعِّل PERF_SAMPLE_WEIGHT أو PERF_SAMPLE_WEIGHT_STRUCT، فتُسجل قيمة 64-بت يوفرها العتاد تشير إلى مدى تكلفة الحدث. يسمح هذا للأحداث المكلفة بالبروز بوضوح أكبر في التشكيلات (profiles).
إذا فُعِّل PERF_SAMPLE_DATA_SRC، فتُسجل قيمة 64-بت تتكون من الحقول التالية:
نوع رمز العملية (opcode)، وهو مزيج بتات (bitwise combination) من:
غير متاح
تعليمة تحميل (Load)
تعليمة تخزين (Store)
جلب مسبق
كود قابل للتنفيذ
إصابة أو إخفاق مستوى هرمية الذاكرة، وهو مزيج بتات مما يلي، مُزاح لليسار بمقدار PERF_MEM_LVL_SHIFT:
غير متاح
إصابة (Hit)
إخفاق (Miss)
خبيئة المستوى 1
مخزن مؤقت لملء السطور (Line fill buffer)
خبيئة المستوى 2
خبيئة المستوى 3
DRAM محلية
DRAM بعيدة على بعد قفزة واحدة
ذاكرة DRAM بعيدة عبر قفزتين
خبيئة بعيدة عبر قفزة واحدة
خبيئة بعيدة عبر قفزتين
ذاكرة الإدخال/الإخراج
ذاكرة غير مخبوءة
وضع الاسترقاق (Snoop mode)، وهو مزيج بتات مما يلي، مُزاح إلى اليسار بمقدار PERF_MEM_SNOOP_SHIFT:
غير متاح
لا يوجد استرقاق
إصابة استرقاق
إخفاق استرقاق
إصابة استرقاق مُعدلة
تعليمات القفل، وهي مزيج بتات مما يلي، مُزاح إلى اليسار بمقدار PERF_MEM_LOCK_SHIFT:
غير متاح
عملية مقفلة
إصابة أو إخفاق وصول TLB، وهي مزيج بتات مما يلي، مُزاح إلى اليسار بمقدار PERF_MEM_TLB_SHIFT:
غير متاح
إصابة (Hit)
إخفاق (Miss)
TLB المستوى 1
TLB المستوى 2
جوال عتادي
مُعالج أخطاء نظام التشغيل
إذا ضُبطت العلامة PERF_SAMPLE_TRANSACTION، فسيُسجل حقل بطول 64 بت يصف مصادر أي إجهاضات للذاكرة المعاملاتية.
هذا الحقل هو مزيج بتات من القيم التالية:
إجهاض من معاملة من نوع الحذف (خاص بمعالجات إنقيل).
إجهاض من معاملة عامة.
إجهاض متزامن (متعلق بالتعليمات المُبلغ عنها).
إجهاض غير متزامن (غير متعلق بالتعليمات المُبلغ عنها).
إجهاض قابل لإعادة المحاولة (ربما نجحت إعادة محاولة المعاملة).
إجهاض بسبب تضارب الذاكرة مع خيوط أخرى.
إجهاض بسبب تجاوز سعة الكتابة.
إجهاض بسبب تجاوز سعة القراءة.
بالإضافة إلى ذلك، يمكن الحصول على كود إجهاض محدد من قبل المستخدم من الـ 32 بت العليا للحقل عن طريق الإزاحة لليمين بمقدار PERF_TXN_ABORT_SHIFT وتطبيق قناع بالقيمة PERF_TXN_ABORT_MASK.
إذا فُعّلت PERF_SAMPLE_REGS_INTR، فستُسجل سجلات وحدة المعالجة المركزية للمستخدم.
يكون حقل abi واحدًا من PERF_SAMPLE_REGS_ABI_NONE، أو PERF_SAMPLE_REGS_ABI_32، أو PERF_SAMPLE_REGS_ABI_64.
حقل regs هو مصفوفة من سجلات وحدة المعالجة المركزية التي حُددت بواسطة حقل السمة sample_regs_intr. عدد القيم هو عدد البتات المضبوطة في قناع البتات sample_regs_intr.
إذا ضُبطت العلامة PERF_SAMPLE_PHYS_ADDR، فسيُسجل العنوان الفيزيائي ذو الـ 64 بت.
إذا ضُبطت العلامة PERF_SAMPLE_CGROUP، فسيُسجل معرف cgroup ذو الـ 64 بت (الخاص بنظام perf_event الفرعي). للحصول على مسار cgroup، يجب أن يتطابق المعرف مع أحد المعرفات في PERF_RECORD_CGROUP.
إذا ضُبطت العلامة PERF_SAMPLE_DATA_PAGE_SIZE، فسيُسجل حجم الصفحة ذو الـ 64 بت لعنوان الـ data.
إذا ضُبطت العلامة PERF_SAMPLE_CODE_PAGE_SIZE، فسيُسجل حجم الصفحة ذو الـ 64 بت لعنوان الـ ip.
إذا فُعّلت PERF_SAMPLE_AUX، فستُسجل لقطة لمخزن aux المؤقت.
يتضمن هذا السجل معلومات ممتدة حول استدعاءات mmap(2) التي تعيد تخطيطات قابلة للتنفيذ. التنسيق مشابه لتنسيق سجل PERF_RECORD_MMAP، ولكنه يتضمن قيمًا إضافية تسمح بتحديد التخطيطات المشتركة بشكل فريد. اعتمادًا على بت PERF_RECORD_MISC_MMAP_BUILD_ID في الترويسة، تختلف معاني القيم الإضافية ومخططها.

struct {

struct perf_event_header header;
u32 pid;
u32 tid;
u64 addr;
u64 len;
u64 pgoff;
union {
struct {
u32 maj;
u32 min;
u64 ino;
u64 ino_generation;
};
struct { /* if PERF_RECORD_MISC_MMAP_BUILD_ID */
u8 build_id_size;
u8 __reserved_1;
u16 __reserved_2;
u8 build_id[20];
};
};
u32 prot;
u32 flags;
char filename[];
struct sample_id sample_id; };

هو معرف العملية.
هو معرف الخيط.
هو عنوان الذاكرة المخصصة.
هو حجم الذاكرة المخصصة.
هو إزاحة الصفحة للذاكرة المخصصة.
هو المعرف الرئيس للجهاز الأساسي.
هو المعرف الثانوي للجهاز الأساسي.
هو رقم الآينود (inode).
هو جيل الآينود (inode).
هو الحجم الفعلي لحقل build_id (حتى 20).
هي بيانات خام لتعريف ملف ثنائي.
هي معلومات الحماية.
هي معلومات الأعلام (flags).
هي سلسلة نصية تصف ما يسند الذاكرة المخصصة.
يبلغ هذا السجل عن توفر بيانات جديدة في منطقة مخزن AUX المؤقت المنفصلة.

struct {

struct perf_event_header header;
u64 aux_offset;
u64 aux_size;
u64 flags;
struct sample_id sample_id; };

الإزاحة في منطقة mmap لـ AUX حيث تبدأ البيانات الجديدة.
حجم البيانات التي أُتيحت.
يصف تحديث AUX.
إذا ضُبط، فهذا يعني أن البيانات المعادة بُترت لتناسب حجم المخزن المؤقت المتاح.
إذا ضُبط، فهذا يعني أن البيانات المعادة كتبت فوق بيانات سابقة.
يشير هذا السجل إلى العملية التي بدأت حدث تتبع التعليمات، مما يسمح للأدوات بربط عناوين التعليمات في مخزن AUX المؤقت بالملف التنفيذي المناسب بشكل صحيح.

struct {

struct perf_event_header header;
u32 pid;
u32 tid; };

معرف العملية للخيط (thread) الذي يبدأ تتبع التعليمات.
معرف الخيط (thread ID) للخيط الذي يبدأ تتبع التعليمات.
عند استخدام المعاينة العتادية (مثل Intel PEBS)، يشير هذا السجل إلى عدد من العينات التي قد تكون فُقدت.

struct {

struct perf_event_header header;
u64 lost;
struct sample_id sample_id; };

عدد العينات التي يحتمل فقدانها.
يشير هذا السجل إلى حدوث تبديل سياق. يشير بت PERF_RECORD_MISC_SWITCH_OUT في حقل misc ما إذا كان تبديل السياق إلى العملية الحالية أو بعيدًا عنها.

struct {

struct perf_event_header header;
struct sample_id sample_id; };

كما هو الحال مع PERF_RECORD_SWITCH، يشير هذا السجل إلى حدوث تبديل سياق، ولكنه يحدث فقط عند المعاينة في وضع شامل للمعالج (CPU-wide) ويوفر معلومات إضافية حول العملية التي يجري التبديل إليها أو منها. يشير بت PERF_RECORD_MISC_SWITCH_OUT في حقل misc ما إذا كان تبديل السياق إلى العملية الحالية أو بعيدًا عنها.

struct {

struct perf_event_header header;
u32 next_prev_pid;
u32 next_prev_tid;
struct sample_id sample_id; };

معرف العملية للعملية السابقة (في حالة التبديل للداخل) أو التالية (في حالة التبديل للخارج) على المعالج.
معرف الخيط (thread ID) للخيط السابق (في حالة التبديل للداخل) أو التالي (في حالة التبديل للخارج) على المعالج.
يتضمن هذا السجل معلومات مساحات أسماء متنوعة لعملية ما.

struct {

struct perf_event_header header;
u32 pid;
u32 tid;
u64 nr_namespaces;
struct { u64 dev, inode } [nr_namespaces];
struct sample_id sample_id; };

هو معرف العملية
هو معرف الخيط
هو عدد مساحات الأسماء في هذا السجل
تملك كل مساحة أسماء حقلين dev و inode وتُسجل في موضع ثابت مثل أدناه:
مساحة أسماء الشبكة
مساحة أسماء UTS
مساحة أسماء IPC
نطاق تسمية PID
نطاق تسمية المستخدم
نطاق تسمية الوصل
نطاق تسمية Cgroup
يشير هذا السجل إلى أحداث تسجيل/إلغاء تسجيل رموز النواة.

struct {

struct perf_event_header header;
u64 addr;
u32 len;
u16 ksym_type;
u16 flags;
char name[];
struct sample_id sample_id; };

هو عنوان رمز النواة.
هو حجم رمز النواة.
هو نوع رمز النواة. تتوفر الأنواع التالية حاليًا:
رمز النواة هو دالة BPF.
إذا ضُبط PERF_RECORD_KSYMBOL_FLAGS_UNREGISTER، فإن هذا الحدث يكون لإلغاء تسجيل رمز النواة.
يشير هذا السجل إلى تحميل برنامج BPF أو تفريغه.

struct {

struct perf_event_header header;
u16 type;
u16 flags;
u32 id;
u8 tag[BPF_TAG_SIZE];
struct sample_id sample_id; };

هي واحدة من القيم التالية:
حُمِّل برنامج BPF
فُرِّغ برنامج BPF
هو معرف برنامج BPF.
وسم
هو وسم برنامج BPF. حاليًا، يُعرَّف BPF_TAG_SIZE على أنه 8.
يشير هذا السجل إلى إنشاء cgroup جديد وتنشيطه.

struct {

struct perf_event_header header;
u64 id;
char path[];
struct sample_id sample_id; };

هو معرف cgroup. يمكن استرداده أيضًا بواسطة name_to_handle_at(2) على مسار cgroup (كمقبض ملف).
مسار
هو مسار cgroup من الجذر.
يشير هذا السجل إلى تغيير في نص النواة. يتضمن ذلك إضافة النص وإزالته، ويكون الحجم المقابل صفرًا في هذه الحالة.

struct {

struct perf_event_header header;
u64 addr;
u16 old_len;
u16 new_len;
u8 bytes[];
struct sample_id sample_id; };

هو عنوان التغيير
هو الحجم القديم
هو الحجم الجديد
يحتوي على البايتات القديمة متبوعة مباشرة بالبايتات الجديدة.

التعامل مع الطفح

يمكن ضبط الأحداث للإشعار عند تجاوز عتبة معينة، مما يشير إلى حدوث طفح. يمكن التقاط حالات الطفح من خلال مراقبة واصف ملف الحدث باستخدام poll(2)، أو select(2)، أو epoll(7). بدلاً من ذلك، يمكن التقاط أحداث الطفح عبر معالج إشارات، من خلال تمكين إشارات الدخل/الخرج على واصف الملف؛ انظر مناقشة عمليتي F_SETOWN و F_SETSIG في fcntl(2).

لا تُولَّد حالات الطفح إلا بواسطة أحداث أخذ العينات (يجب أن تكون قيمة sample_period غير صفرية).

توجد طريقتان لتوليد إشعارات الطفح.

الأولى هي ضبط قيمة wakeup_events أو wakeup_watermark التي ستعمل إذا كُتب عدد معين من العينات أو البايتات في المخزن المؤقت الحلقي لـ mmap. في هذه الحالة، يُشار إلى POLL_IN.

الطريقة الأخرى هي استخدام ioctl PERF_EVENT_IOC_REFRESH. يضيف هذا الـ ioctl إلى عداد يتناقص في كل مرة يطفح فيها الحدث. عندما تكون القيمة غير صفرية، يُشار إلى POLL_IN، ولكن بمجرد وصول العداد إلى 0، يُشار إلى POLL_HUP ويُعطَّل الحدث الأساسي.

تؤدي عملية تنشيط متصدر مجموعة أحداث إلى تنشيط جميع الأشقاء، كما أن التنشيط باستخدام المعامل 0 يتيح حاليًا عمليات تنشيط غير محدودة؛ هذه السلوكيات غير مدعومة ولا ينبغي الاعتماد عليها.

بدءًا من لينكس 3.18، يُشار إلى POLL_HUP إذا كان الحدث الذي تُجرى مراقبته مرتبطًا بعملية مختلفة وخرجت تلك العملية.

تعليمة rdpmc

بدءًا من لينكس 3.4 على x86، يمكنك استخدام تعليمة rdpmc للحصول على قراءات ذات زمن وصول منخفض دون الحاجة إلى الدخول إلى النواة. لاحظ أن استخدام rdpmc ليس بالضرورة أسرع من الطرق الأخرى لقراءة قيم الأحداث.

يمكن اكتشاف دعم ذلك من خلال حقل cap_usr_rdpmc في صفحة mmap؛ يمكن العثور على وثائق حول كيفية حساب قيم الأحداث في ذلك القسم.

في الأصل، عندما كان دعم rdpmc مُمكَّنًا، كان بإمكان أي عملية (ليس فقط تلك التي لديها حدث perf نشط) استخدام تعليمة rdpmc للوصول إلى العدادات. بدءًا من لينكس 4.0، لا يُسمح بدعم rdpmc إلا إذا كان هناك حدث مُمكَّن حاليًا في سياق العملية. لاستعادة السلوك القديم، اكتب القيمة 2 في /sys/devices/cpu/rdpmc.

استدعاءات ioctl لـ perf_event

تعمل استدعاءات ioctl المتنوعة على واصفات ملفات perf_event_open():

يُمكِّن هذا الحدث الفردي أو مجموعة الأحداث المحددة بواسطة وسيط واصف الملف.
إذا ضُبطت بتة PERF_IOC_FLAG_GROUP في وسيط ioctl، فستُمكَّن جميع الأحداث في المجموعة، حتى لو لم يكن الحدث المحدد هو متصدر المجموعة (ولكن انظر قسم العيوب BUGS).
يُعطِّل هذا العداد الفردي أو مجموعة الأحداث المحددة بواسطة وسيط واصف الملف.
يؤدي تمكين أو تعطيل متصدر المجموعة إلى تمكين أو تعطيل المجموعة بأكملها؛ أي أنه أثناء تعطيل متصدر المجموعة، لن يقوم أي من العدادات في المجموعة بالعد. يؤثر تمكين أو تعطيل عضو في مجموعة غير المتصدر على ذلك العداد فقط؛ حيث يؤدي تعطيل عضو غير متصدر إلى إيقاف ذلك العداد عن العد ولكنه لا يؤثر على أي عداد آخر.
إذا ضُبطت بتة PERF_IOC_FLAG_GROUP في وسيط ioctl، فستُعطَّل جميع الأحداث في المجموعة، حتى لو لم يكن الحدث المحدد هو متصدر المجموعة (ولكن انظر قسم العيوب BUGS).
يمكن لعدادات الطفح غير الموروثة استخدام هذا لتمكين عداد لعدد من حالات الطفح المحددة بواسطة الوسيط، وبعد ذلك يُعطَّل. تضيف الاستدعاءات اللاحقة لهذا الـ ioctl قيمة الوسيط إلى العدد الحالي. سيحدث إشعار طفح مع ضبط POLL_IN عند كل طفح حتى يصل العدد إلى 0؛ وعندما يحدث ذلك، يُرسل إشعار مع ضبط POLL_HUP ويُعطَّل الحدث. يُعد استخدام وسيط بقيمة 0 سلوكًا غير محدد.
تُصفَّر قيمة عداد الأحداث المحدد بواسطة وسيط واصف الملف. يصفر هذا القيم فقط؛ ولا توجد طريقة لتصفير قيم تعدد الإرسال time_enabled أو time_running.
إذا ضُبطت بتة PERF_IOC_FLAG_GROUP في وسيط ioctl، فستُصفر كل الأحداث في المجموعة، حتى لو لم يكن الحدث المحدد هو قائد المجموعة (لكن انظر قسم العلل BUGS).
يحدث هذا فترة التجاوز (overflow) للحدث.
بدءًا من لينكس 3.7 (على ARM) ولينكس 3.14 (بقية المعماريات الأخرى)، تسري الفترة الجديدة فورًا. أما في نويات النواة الأقدم، فلم تكن الفترة الجديدة تسري إلا بعد حدوث التجاوز التالي.
الوسيط هو مؤشر إلى قيمة 64 بت تحتوي على الفترة الجديدة المطلوبة.
قبل لينكس 2.6.36، كان ioctl هذا يفشل دائمًا بسبب علة في النواة.
يخبر هذا النواة بإرسال إشعارات الأحداث إلى واصف الملف المحدد بدلًا من الواصف المبدئي. يجب أن تكون جميع واصفات الملفات على وحدة المعالجة المركزية ذاتها.
يحدد الوسيط واصف الملف المطلوب، أو -1 إذا وجب تجاهل المخرجات.
يضيف هذا مرشح ftrace إلى هذا الحدث.
الوسيط هو مؤشر إلى مرشح ftrace المطلوب.
يعيد هذا قيمة معرف الحدث لواصف ملف الحدث المعطى.
الوسيط هو مؤشر إلى عدد صحيح غير موقع بطول 64 بت لحفظ النتيجة.
يسمح هذا بربط برنامج مرشح حزم بيركلي (BPF) بحدث نقطة تتبع kprobe موجود. تحتاج إلى امتيازات CAP_PERFMON (منذ لينكس 5.8) أو CAP_SYS_ADMIN لاستخدام ioctl هذا.
الوسيط هو واصف ملف برنامج BPF أُنشئ عبر استدعاء نظام bpf(2) سابق.
يسمح هذا بإيقاف واستئناف المخزن الحلقي (ring-buffer) للحدث. لا يمنع المخزن الحلقي المتوقف مؤقتًا توليد العينات، ولكنه يطرحها ببساطة. تُعتبر العينات المطروحة مفقودة، وتتسبب في توليد عينة PERF_RECORD_LOST عندما يكون ذلك ممكنًا. قد تظل إشارة التجاوز تنطلق بسبب العينة المطروحة حتى لو ظل المخزن الحلقي فارغًا.
الوسيط هو عدد صحيح غير موقع بطول 32 بت. تؤدي القيمة غير الصفرية إلى إيقاف المخزن الحلقي مؤقتًا، بينما تستأنفه القيمة الصفرية.
يسمح هذا بتعديل حدث موجود دون العبء الإضافي لإغلاق وفتح حدث جديد. هذا مدعوم حاليًا لأحداث نقاط التوقف (breakpoint events) فقط.
الوسيط هو مؤشر إلى بنية perf_event_attr تحتوي على إعدادات الحدث المحدثة.
يسمح هذا بالاستعلام عن برامج مرشح حزم بيركلي (BPF) المربوطة بنقطة تتبع kprobe موجودة. يمكنك ربط برنامج BPF واحد فقط لكل حدث، ولكن يمكن أن يكون لديك أحداث متعددة مربوطة بنقطة تتبع واحدة. يعيد الاستعلام عن هذه القيمة في حدث نقطة تتبع واحد معرفات جميع برامج BPF في جميع الأحداث المربوطة بنقطة التتبع تلك. تحتاج إلى امتيازات CAP_PERFMON (منذ لينكس 5.8) أو CAP_SYS_ADMIN لاستخدام ioctl هذا.
الوسيط هو مؤشر إلى بنية
struct perf_event_query_bpf {

__u32 ids_len;
__u32 prog_cnt;
__u32 ids[0]; };

يشير حقل ids_len إلى عدد المعرفات التي يمكن أن يتسع لها مصفوفة ids الموفرة. تملأ النواة قيمة prog_cnt بعدد برامج BPF المربوطة. تُملأ مصفوفة ids بمعرف كل برنامج BPF مربوط. إذا كان هناك عدد من البرامج أكبر مما يتسع له المصفوفة، فستعيد النواة ENOSPC وسيشير ids_len إلى عدد معرفات البرامج التي نُسخت بنجاح.

استخدام prctl(2)

يمكن للعملية تفعيل أو تعطيل جميع مجموعات الأحداث المفتوحة حاليًا باستخدام عمليتي prctl(2) هما PR_TASK_PERF_EVENTS_ENABLE و PR_TASK_PERF_EVENTS_DISABLE. ينطبق هذا فقط على الأحداث التي أنشأها المستدعِي محليًا. ولا ينطبق على الأحداث التي أنشأتها عمليات أخرى مرتبطة بالعملية المستدعِية أو الأحداث الموروثة من عملية أب. تُفعل وتُعطل قادة المجموعات فقط، وليس أي أعضاء آخرين في المجموعات.

ملفات الإعداد المتعلقة بـ perf_event

ملفات في /proc/sys/kernel/

/proc/sys/kernel/perf_event_paranoid
يمكن ضبط ملف perf_event_paranoid لتقييد الوصول إلى عدادات الأداء.
2
يسمح فقط بقياسات مساحة المستخدم (المبدئي منذ لينكس 4.6).
1
يسمح بكل من قياسات النواة والمستخدم (المبدئي قبل لينكس 4.6).
0
يسمح بالوصول إلى البيانات الخاصة بوحدة المعالجة المركزية ولكن ليس لعينات نقطة التتبع الخام.
-1
بلا قيود.
يُعد وجود ملف perf_event_paranoid هو الطريقة الرسمية لتحديد ما إذا كانت النواة تدعم perf_event_open().
/proc/sys/kernel/perf_event_max_sample_rate
يضبط هذا الحد الأقصى لمعدل أخذ العينات. قد يؤدي ضبط هذا المعدل على قيمة عالية جدًا إلى السماح للمستخدمين بأخذ العينات بمعدل يؤثر على الأداء العام للحاسوب وقد يؤدي إلى تجمده. القيمة المبدئية هي 100000 (عينة في الثانية).
/proc/sys/kernel/perf_event_max_stack
يضبط هذا الملف الحد الأقصى لعمق مدخلات إطارات المكدس (stack frame) المبلغ عنها عند توليد تتبع الاستدعاء (call trace).
/proc/sys/kernel/perf_event_mlock_kb
الحد الأقصى لعدد الصفحات التي يمكن لمستخدم غير متميز قفلها باستخدام mlock(2). القيمة المبدئية هي 516 (كيلوبايت).

ملفات في /sys/bus/event_source/devices/

منذ لينكس 2.6.34، تدعم النواة وجود عدة وحدات مراقبة أداء (PMUs) متاحة للمراقبة. يمكن العثور على معلومات حول كيفية برمجة هذه الوحدات تحت المسار /sys/bus/event_source/devices/. يقابل كل دليل فرعي وحدة PMU مختلفة.
/sys/bus/event_source/devices/*/type (منذ لينكس 2.6.38)
يحتوي هذا على عدد صحيح يمكن استخدامه في حقل type في perf_event_attr للإشارة إلى رغبتك في استخدام وحدة PMU هذه.
/sys/bus/event_source/devices/cpu/rdpmc (منذ لينكس 3.4)
إذا كانت قيمة هذا الملف هي 1، فسيُسمح بالوصول المباشر من مساحة المستخدم إلى سجلات عداد الأداء عبر تعليمة rdpmc. يمكن تعطيل ذلك عبر كتابة 0 في الملف.
بدءًا من لينكس 4.0 تغير السلوك، حيث تعني القيمة 1 الآن السماح بالوصول فقط للعمليات التي لديها أحداث perf نشطة، بينما تشير القيمة 2 إلى السلوك القديم الذي يسمح للجميع بالوصول.
/sys/bus/event_source/devices/*/format/ (منذ لينكس 3.4)
يحتوي هذا الدليل الفرعي على معلومات حول الحقول الفرعية الخاصة بالمعمارية والمتاحة لبرمجة حقول config المتنوعة في بنية perf_event_attr.
محتوى كل ملف هو اسم حقل الإعداد، متبوعًا بنقطتين، متبوعًا بسلسلة من نطاقات البتات الصحيحة المفصولة بفواصل. على سبيل المثال، قد يحتوي الملف event على القيمة config1:1,6-10,44 مما يشير إلى أن الحدث هو سمة تحتل البتات 1 و 6 إلى 10 و 44 من perf_event_attr::config1.
/sys/bus/event_source/devices/*/events/ (منذ لينكس 3.4)
يحتوي هذا الدليل الفرعي على ملفات بها أحداث محددة مسبقًا. المحتويات عبارة عن سلاسل تصف إعدادات الحدث معبرًا عنها بدلالة الحقول الموجودة في دليل ./format/ المذكور سابقًا. ليست هذه بالضرورة قوائم كاملة لجميع الأحداث التي تدعمها وحدة PMU، ولكنها عادة ما تكون مجموعة فرعية من الأحداث التي تعتبر مفيدة أو مثيرة للاهتمام.
محتوى كل ملف هو قائمة بأسماء السمات مفصولة بفواصل. لكل مدخل قيمة اختيارية (إما ست عشرية أو عشرية). إذا لم تُحدد أي قيمة، فيُفترض أنها حقل من بت واحد بقيمته 1. قد يبدو مدخل المثال كالتالي: event=0x2,inv,ldlat=3.
/sys/bus/event_source/devices/*/uevent
هذا الملف هو واجهة جهاز النواة القياسية لحقن أحداث التوصيل الفوري (hotplug).
/sys/bus/event_source/devices/*/cpumask (منذ لينكس 3.7)
يحتوي ملف cpumask على قائمة من الأعداد الصحيحة المفصولة بفواصل والتي تشير إلى رقم معالج ممثل لكل مقبس (socket) على اللوحة الأم. هذا مطلوب عند إعداد أحداث uncore أو الجسر الشمالي (northbridge)، حيث تقدم تلك الوحدات (PMUs) أحداثًا على مستوى المقبس.

قيمة الإرجاع

عند النجاح، يعيد perf_event_open() واصف الملف الجديد. وعند الخطأ، تُعاد القيمة -1 ويُضبط errno للإشارة إلى الخطأ.

الأخطاء

يمكن أن تكون الأخطاء التي يعيدها perf_event_open() غير متسقة، وقد تختلف عبر معماريات المعالجات ووحدات مراقبة الأداء.

يُعاد إذا كانت قيمة size في perf_event_attr صغيرة جدًا (أصغر من PERF_ATTR_SIZE_VER0)، أو كبيرة جدًا (أكبر من حجم الصفحة)، أو أكبر مما تدعمه النواة ولم تكن البتات الإضافية صفرًا. عند إرجاع E2BIG، يُكتب فوق حقل size في perf_event_attr من قبل النواة ليصبح حجم البنية التي كانت تتوقعها.
يُعاد عندما يتطلب الحدث المطلوب صلاحيات CAP_PERFMON (منذ لينكس 5.8) أو CAP_SYS_ADMIN (أو إعداد perf_event paranoid أكثر تسامحًا). بعض الحالات الشائعة التي قد تواجه فيها عملية غير متميزة هذا الخطأ: الارتباط بعملية يملكها مستخدم آخر؛ ومراقبة جميع العمليات على وحدة معالجة مركزية معينة (أي تحديد معامل pid كـ -1)؛ وعدم ضبط exclude_kernel عندما يتطلب إعداد paranoid ذلك.
يُعاد إذا كان واصف الملف group_fd غير صالح، أو إذا ضُبط PERF_FLAG_PID_CGROUP وكان واصف ملف cgroup في pid غير صالح.
يُعاد إذا كان هناك حدث آخر يمتلك بالفعل وصولاً حصريًا إلى PMU.
يُعاد إذا كان مؤشر attr يشير إلى عنوان ذاكرة غير صالح.
يُعاد عند محاولة الخلط بين معالجة perf و ftrace لـ uprobe.
يُعاد إذا كان الحدث المحدد غير صالح. هناك العديد من الأسباب المحتملة لذلك، منها على سبيل المثال لا الحصر: كون sample_freq أعلى من الحد الأقصى للإعداد؛ أو أن cpu المراد مراقبته غير موجود؛ أو read_format خارج النطاق؛ أو sample_type خارج النطاق؛ أو قيمة flags خارج النطاق؛ أو تعيين exclusive أو pinned والحدث ليس قائد مجموعة؛ أو قيم config للحدث خارج النطاق أو تم تعيين بتات محجوزة؛ أو أن الحدث العام المحدد غير مدعوم؛ أو عدم وجود مساحة كافية لإضافة الحدث المحدد.
يستخدم كل حدث مفتوح واصف ملف واحد. إذا فُتح عدد كبير من الأحداث، سيتم الوصول إلى الحد الأقصى لواصفات الملفات المفتوحة لكل عملية، ولن يمكن إنشاء المزيد من الأحداث.
يُعاد عندما يتضمن الحدث ميزة لا تدعمها وحدة المعالجة المركزية الحالية.
يُعاد إذا كان إعداد type غير صالح. يُعاد هذا الخطأ أيضًا لبعض الأحداث العامة غير المدعومة.
قبل لينكس 3.3، إذا لم تكن هناك مساحة كافية للحدث، كان يُعاد ENOSPC. في لينكس 3.3، غُيّر هذا إلى EINVAL. لا يزال ENOSPC يُعاد إذا حاولت إضافة أحداث نقاط توقف (breakpoint) أكثر مما يدعمه العتاد.
يُعاد إذا ضُبط PERF_SAMPLE_STACK_USER في sample_type وكان غير مدعوم من قبل العتاد.
يُعاد إذا طُلب حدث يتطلب ميزة عتادية معينة ولكن لا يوجد دعم عتادي لها. يتضمن ذلك طلب أحداث منخفضة الانحراف (low-skid) إذا كانت غير مدعومة، وتتبع الفروع (branch tracing) إذا لم يكن متاحًا، وأخذ العينات (sampling) إذا لم يتوفر مقاطعة PMU، وكدسات الفروع للأحداث البرمجية.
يُعاد إذا طُلب PERF_SAMPLE_CALLCHAIN وكان sample_max_stack أكبر من الحد الأقصى المحدد في /proc/sys/kernel/perf_event_max_stack.
يُعاد في العديد من البنى (وليس جميعها) عند تحديد إعداد غير مدعوم لـ exclude_hv أو exclude_idle أو exclude_user أو exclude_kernel.
يمكن أن يحدث أيضًا، كما هو الحال مع EACCES، عندما يتطلب الحدث المطلوب صلاحيات CAP_PERFMON (منذ لينكس 5.8) أو CAP_SYS_ADMIN (أو إعداد perf_event paranoid أكثر تسامحًا). يتضمن ذلك تعيين نقطة توقف على عنوان للنواة، و(منذ لينكس 3.13) تعيين نقطة تتبع تتبع وظائف النواة.
يُعاد عند محاولة الارتباط بعملية غير موجودة.

المعايير

لينكس.

التاريخ

أُدخلت perf_event_open() في لينكس 2.6.31 ولكن كانت تسمى perf_counter_open(). أُعيدت تسميتها في لينكس 2.6.32.

ملاحظات

الطريقة الرسمية لمعرفة ما إذا كان دعم perf_event_open() مُمكّنًا هي التحقق من وجود الملف /proc/sys/kernel/perf_event_paranoid.

توفر قدرة CAP_PERFMON (منذ لينكس 5.8) نهجًا آمنًا لعمليات مراقبة الأداء والقابلية للملاحظة في النظام وفقًا لمبدأ الأقل صلاحية (POSIX IEEE 1003.1e). إن الوصول إلى عمليات مراقبة أداء النظام والقابلية للملاحظة باستخدام CAP_PERFMON بدلاً من CAP_SYS_ADMIN الأكثر قوة بكثير يستبعد فرص إساءة استخدام الاعتمادات ويجعل العمليات أكثر أمانًا. لا يُنصح باستخدام CAP_SYS_ADMIN لمراقبة أداء النظام الآمن والقابلية للملاحظة ويُفضل استخدام قدرة CAP_PERFMON بدلاً منها.

العلل

خيار F_SETOWN_EX لـ fcntl(2) مطلوب للحصول بشكل صحيح على إشارات التجاوز في الخيوط. أُدخل هذا في لينكس 2.6.32.

قبل لينكس 2.6.33 (على الأقل لـ x86)، لم تكن النواة تتحقق مما إذا كان يمكن جدولة الأحداث معًا حتى وقت القراءة. يحدث الشيء نفسه في جميع النوى المعروفة إذا كان مراقب NMI مُمكّنًا. هذا يعني أنه لرؤية ما إذا كانت مجموعة معينة من الأحداث تعمل، يتعين عليك استدعاء perf_event_open()، والبدء، ثم القراءة قبل أن تعرف بالتأكيد ما إذا كان يمكنك الحصول على قياسات صالحة.

قبل لينكس 2.6.34، لم تكن قيود الأحداث تُفرض من قبل النواة. في هذه الحالة، كانت بعض الأحداث ستعيد "0" بصمت إذا قامت النواة بجدولتها في فتحة عداد غير مناسبة.

قبل لينكس 2.6.34، كانت هناك علة عند تعدد الإرسال حيث يمكن إعادة نتائج خاطئة.

يمكن للنوى من لينكس 2.6.35 إلى لينكس 2.6.39 أن تنهار بسرعة إذا كان "inherit" مُمكّنًا وبُدئ العديد من الخيوط.

قبل لينكس 2.6.35، لم يكن PERF_FORMAT_GROUP يعمل مع العمليات المرتبطة.

هناك علة في كود النواة بين لينكس 2.6.36 ولينكس 3.0 تتجاهل حقل "watermark" وتتصرف كما لو اختير wakeup_event إذا كان للاتحاد (union) قيمة غير صفرية فيه.

من لينكس 2.6.31 إلى لينكس 3.4، كان معامل ioctl لـ PERF_IOC_FLAG_GROUP معطلاً وكان يعمل بشكل متكرر على الحدث المحدد بدلاً من التكرار عبر جميع الأحداث الشقيقة في مجموعة.

من لينكس 3.4 إلى لينكس 3.11، خُصصت بتات mmap لـ cap_usr_rdpmc و cap_usr_time إلى نفس الموقع. يجب أن ينتقل الكود إلى حقول cap_user_rdpmc و cap_user_time الجديدة بدلاً من ذلك.

تحقق دائمًا من نتائجك مرتين! كانت لعدة أحداث عامة قيم خاطئة. على سبيل المثال، كانت الفروع المتقاعدة (retired branches) تقيس الشيء الخاطئ على أجهزة AMD حتى لينكس 2.6.35.

أمثلة

فيما يلي مثال قصير يقيس إجمالي عدد التعليمات لاستدعاء لـ printf(3).

#include <err.h>
#include <linux/perf_event.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
static long
perf_event_open(struct perf_event_attr *hw_event, pid_t pid,

int cpu, int group_fd, unsigned long flags) {
int ret;
ret = syscall(SYS_perf_event_open, hw_event, pid, cpu,
group_fd, flags);
return ret; } int main(void) {
int fd;
long long count;
struct perf_event_attr pe;
memset(&pe, 0, sizeof(pe));
pe.type = PERF_TYPE_HARDWARE;
pe.size = sizeof(pe);
pe.config = PERF_COUNT_HW_INSTRUCTIONS;
pe.disabled = 1;
pe.exclude_kernel = 1;
pe.exclude_hv = 1;
fd = perf_event_open(&pe, 0, -1, -1, 0);
if (fd == -1)
err(EXIT_FAILURE, "Error opening leader %llx\n", pe.config);
if (ioctl(fd, PERF_EVENT_IOC_RESET, 0) == -1)
err(EXIT_FAILURE, "PERF_EVENT_IOC_RESET");
if (ioctl(fd, PERF_EVENT_IOC_ENABLE, 0) == -1)
err(EXIT_FAILURE, "PERF_EVENT_IOC_ENABLE");
printf("Measuring instruction count for this printf\n");
if (ioctl(fd, PERF_EVENT_IOC_DISABLE, 0) == -1)
err(EXIT_FAILURE, "PERF_EVENT_IOC_DISABLE");
if (read(fd, &count, sizeof(count)) != sizeof(count))
err(EXIT_FAILURE, "read");
printf("Used %lld instructions\n", count);
if (close(fd) == -1)
err(EXIT_FAILURE, "close"); }

انظر أيضًا

perf(1), fcntl(2), mmap(2), open(2), prctl(2), read(2)

Documentation/admin-guide/perf-security.rst في شجرة مصدر النواة

ترجمة

تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.

8 فبراير 2026 صفحات دليل لينكس 6.18