core(5)

الاسم
core - ملف تفريغ النواة

الوصف
الإجراء المبدئي لبعض الإشارات هو إنهاء عملية وإنتاج ملف تفريغ النواة، وهو ملف يحتوي على صورة لذاكرة العملية وقت الإنهاء. يمكن استخدام هذه الصورة في مصحح (مثل gdb(1)) لفحص حالة البرنامج وقت إنهائه. يمكن العثور على قائمة الإشارات التي تسبب تفريغ النواة في signal(7).

يمكن لعملية تعيين حد الموارد الناعم RLIMIT_CORE لوضع حد أعلى لحجم ملف تفريغ النواة الذي سينتج إذا تلقت إشارة "تفريغ نواة"؛ انظر getrlimit(2) للتفاصيل.

توجد ظروف مختلفة لا ينتج فيها ملف تفريغ النواة:

•   لا تملك العملية صلاحية كتابة ملف النواة. (مبدئيًا، يسمى ملف النواة core أو core.pid، حيث pid هو معرف العملية التي فرغت النواة، ويُنشأ في دليل العمل الحالي. انظر أدناه لتفاصيل التسمية.) تفشل كتابة ملف النواة إذا كان الدليل الذي سينشأ فيه غير قابل للكتابة، أو إذا كان ملف بنفس الاسم موجودًا وغير قابل للكتابة أو ليس ملفًا عاديًا (مثل دليل أو رابط رمزي).

•   يوجد بالفعل ملف (قابل للكتابة، عادي) بنفس الاسم الذي سيستخدم لتفريغ النواة، ولكن يوجد أكثر من رابط صلب لذلك الملف.

•   نظام الملفات حيث سينشأ ملف تفريغ النواة ممتلئ؛ أو نفدت عُقد الفهرس (inodes)؛ أو وُصل للقراءة فقط؛ أو بلغ المستخدم حصته لنظام الملفات.

•   الدليل الذي سينشأ فيه ملف تفريغ النواة غير موجود.

•   حدود الموارد RLIMIT_CORE (حجم ملف النواة) أو RLIMIT_FSIZE (حجم الملف) للعملية مضبوطة على صفر؛ انظر getrlimit(2) ووثائق أمر ulimit للصدفة (limit في csh(1)). ومع ذلك، يُتجاهل RLIMIT_CORE إذا كان النظام مهيأً لتوجيه تفريغات النواة عبر أنبوب إلى برنامج.

•   لا يمتلك الثنائي الذي تنفذه العملية صلاحية قراءة مفعلة. (هذا إجراء أمني لضمان أن ملفًا تنفيذيًا محتوياته غير قابلة للقراءة لا ينتج تفريغ نواة—قد يكون قابلاً للقراءة—يحتوي على صورة للتنفيذي.)

•   تنفذ العملية برنامج set-user-ID (set-group-ID) مملوك لمستخدم (مجموعة) غير معرف المستخدم (المجموعة) الحقيقي للعملية، أو تنفذ العملية برنامجًا لديه قدرات ملف (انظر capabilities(7)). (ومع ذلك، انظر وصف عملية prctl(2) PR_SET_DUMPABLE، ووصف ملف /proc/sys/fs/suid_dumpable في proc(5).)

•   /proc/sys/kernel/core_pattern فارغ و /proc/sys/kernel/core_uses_pid يحتوي على القيمة 0. (هذه الملفات موصوفة أدناه.) لاحظ أنه إذا كان /proc/sys/kernel/core_pattern فارغًا و /proc/sys/kernel/core_uses_pid يحتوي على القيمة 1، فستكون أسماء ملفات تفريغ النواة بالصيغة .pid، وهذه الملفات مخفية ما لم يستخدم المرء خيار ls(1) -a.

•   (منذ لينكس 3.7) هُيئت النواة بدون خيار CONFIG_COREDUMP.

بالإضافة إلى ذلك، قد يستبعد تفريغ النواة جزءًا من مساحة العناوين للعملية إذا استُخدم علم madvise(2) MADV_DONTDUMP.

على الأنظمة التي تستخدم systemd(1) كإطار init، قد تُوضع تفريغات النواة بدلاً من ذلك في موقع يحدده systemd(1). انظر أدناه لمزيد من التفاصيل.

  تسمية ملفات تفريغ النواة
مبدئيًا، يُسمى ملف تفريغ النواة core، ولكن يمكن ضبط ملف /proc/sys/kernel/core_pattern (منذ لينكس 2.6 و 2.4.21) لتعريف قالب يُستخدم لتسمية ملفات تفريغ النواة. يمكن أن يحتوي القالب على محددات % تُستبدل بالقيم التالية عند إنشاء ملف نواة:

    %%  حرف % واحد.
    %c  حد الموارد الناعم لحجم ملف النواة للعملية المتعطلة (منذ لينكس 2.6.24).
    %C  وحدة المعالجة المركزية (CPU) التي شُغلت عليها المهمة (منذ لينكس 6.2).
    %d  وضع التفريغ—نفس القيمة التي يعيدها prctl(2) PR_GET_DUMPABLE (منذ لينكس 3.7).
    %e  قيمة comm للعملية أو الخيط، والتي تكون عادةً نفس اسم الملف التنفيذي (بدون بادئة المسار، ومقتطعة إلى حد أقصى 15 حرفًا)، ولكن قد تم تعديلها لتصبح شيئًا مختلفًا؛ انظر مناقشة /proc/pid/comm و /proc/pid/task/tid/comm في proc(5).
    %E  اسم مسار الملف التنفيذي، مع استبدال الشرطات المائلة ('/') بعلامات تعجب ('!') (منذ لينكس 3.0).
    %f  اسم الملف الفعلي للملف التنفيذي، والذي قد يختلف عن %e (منذ لينكس 5.9).
    %F  PIDFD للعملية المفرغة (منذ لينكس 6.16).
    %g  GID الحقيقي العددي للعملية المفرغة.
    %h  اسم المضيف (نفس nodename الذي يعيده uname(2)).
    %i  TID للخيط الذي تسبب في تفريغ النواة، كما يُرى في مساحة أسماء PID التي يقيم فيها الخيط (منذ لينكس 3.18).
    %I  TID للخيط الذي تسبب في تفريغ النواة، كما يُرى في مساحة أسماء PID الأولية (منذ لينكس 3.18).
    %p  PID للعملية المفرغة، كما يُرى في مساحة أسماء PID التي تقيم فيها العملية.
    %P  PID للعملية المفرغة، كما يُرى في مساحة أسماء PID الأولية (منذ لينكس 3.12).
    %s  رقم الإشارة المسببة للتفريغ.
    %t  وقت التفريغ، معبرًا عنه بالثواني منذ الحقبة، 1970-01-01 00:00:00 +0000 (UTC).
    %u  UID الحقيقي العددي للعملية المفرغة.

يتم إسقاط علامة % واحدة في نهاية القالب من اسم ملف النواة، وكذلك تركيبة % متبوعة بأي حرف غير تلك المذكورة أعلاه. تصبح جميع الأحرف الأخرى في القالب جزءًا حرفيًا من اسم ملف النواة. قد يتضمن القالب أحرف '/'، والتي تُفسر كمحددات لأسماء الدلائل. الحجم الأقصى لاسم ملف النواة الناتج هو 128 بايت (64 بايت قبل لينكس 2.6.19). القيمة المبدئية في هذا الملف هي "core". للتوافق مع الإصدارات السابقة، إذا كان /proc/sys/kernel/core_pattern لا يتضمن %p وكان /proc/sys/kernel/core_uses_pid (انظر أدناه) غير صفري، فسيتم إلحاق .PID باسم ملف النواة.

تُفسر المسارات وفقًا للإعدادات النشطة للعملية المتعطلة. هذا يعني مساحة أسماء الوصل للعملية المتعطلة (انظر mount_namespaces(7))، ودليل العمل الحالي الخاص بها (الموجود عبر getcwd(2))، ودليلها الجذر (انظر chroot(2)).

منذ لينكس 2.4، وفر لينكس أيضًا طريقة أكثر بدائية للتحكم في اسم ملف تفريغ النواة. إذا كان الملف /proc/sys/kernel/core_uses_pid يحتوي على القيمة 0، فسيتم تسمية ملف تفريغ النواة ببساطة core. إذا كان هذا الملف يحتوي على قيمة غير صفرية، فسيشمل ملف تفريغ النواة معرف العملية في اسم بالشكل core.PID.

منذ لينكس 3.6، إذا تم تعيين /proc/sys/fs/suid_dumpable إلى 2 ("suidsafe")، فيجب أن يكون النمط إما اسم مسار مطلق (يبدأ بحرف '/' بادئ) أو أنبوب، كما هو معرف أدناه.

  توجيه تفريغات النواة إلى برنامج عبر الأنبوب
منذ لينكس 2.6.19، يدعم لينكس صيغة بديلة لملف /proc/sys/kernel/core_pattern. إذا كان الحرف الأول من هذا الملف هو رمز أنبوب (|)، فسيتم تفسير باقي السطر كسطر أوامر لبرنامج (أو سكريبت) في مساحة المستخدم سيتم تنفيذه.

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

بدلاً من كتابته إلى ملف، يُعطى تفريغ النواة كمدخل قياسي للبرنامج. لاحظ النقاط التالية:

•   يجب تحديد البرنامج باستخدام مسار مطلق (أو مسار نسبي إلى الدليل الجذر، /)، ويجب أن يتبع فوراً الحرف '|'.

•   يمكن أن تتضمن وسائط سطر الأوامر أيًا من محددات % المذكورة أعلاه. على سبيل المثال، لتمرير PID العملية التي يجري تفريغها، حدد %p في وسيطة.

•   العملية المنشأة لتشغيل البرنامج تعمل كمستخدم ومجموعة root.

•   التشغيل كـ root لا يمنح أي تجاوزات أمنية استثنائية. أي أن LSMs (مثل SELinux) لا تزال نشطة وقد تمنع المعالج من الوصول إلى تفاصيل حول العملية المنهارة عبر /proc/pid.

•   يُفسّر مسار البرنامج بالنسبة لمساحة أسماء الوصل الأولية حيث يُنفّذ دائمًا هناك. لا يتأثر بإعدادات (مثل الدليل الجذر، مساحة أسماء الوصل، دليل العمل الحالي) العملية المنهارة.

•   تعمل العملية في مساحات الأسماء الأولية (PID، الوصل، المستخدم، وهكذا) وليس في مساحات أسماء العملية المنهارة. يمكن استخدام محددات مثل %P للعثور على دليل /proc/pid الصحيح واستكشاف/الدخول إلى مساحات أسماء العملية المنهارة إذا لزم الأمر.

•   تبدأ العملية بدليل عملها الحالي كدليل جذر. إذا رغبت، يمكن تغيير دليل العمل لعملية التفريغ باستخدام القيمة المقدمة من المحدد %P للتغيير إلى موقع عملية التفريغ عبر /proc/pid/cwd.

•   يمكن توفير وسائط سطر الأوامر للبرنامج (منذ لينكس 2.6.24)، محددة بمسافات بيضاء (حتى طول سطر إجمالي يبلغ 128 بايت).

•   لا يُطبّق حد RLIMIT_CORE على تفريغات النواة التي تُنقل عبر أنبوب إلى برنامج عبر هذه الآلية.

  /proc/sys/kernel/core_pipe_limit
عند جمع تفريغات النواة عبر أنبوب إلى برنامج مساحة المستخدم، قد يكون من المفيد لبرنامج الجمع جمع بيانات حول العملية المنهارة من دليل /proc/pid لتلك العملية. للقيام بذلك بأمان، يجب أن تنتظر النواة حتى يخرج برنامج جمع تفريغ النواة، حتى لا تُزال ملفات /proc/pid للعملية المنهارة قبل الأوان. وهذا بدوره يخلق إمكانية أن برنامج جمع سيئ السلوك يمكنه منع استرداد عملية منهارة بمجرد عدم الخروج أبدًا.

منذ لينكس 2.6.32، يمكن استخدام /proc/sys/kernel/core_pipe_limit للدفاع ضد هذا الاحتمال. تحدد القيمة في هذا الملف عدد العمليات المنهارة المتزامنة التي يمكن نقلها عبر أنبوب إلى برامج مساحة المستخدم بالتوازي. إذا تجاوزت هذه القيمة، فإن تلك العمليات المنهارة فوق هذه القيمة تُسجل في سجل النواة ويُتخطى تفريغات نواتها.

القيمة 0 في هذا الملف خاصة. تشير إلى أنه يمكن التقاط عمليات غير محدودة بالتوازي، ولكن لن يحدث أي انتظار (أي أن برنامج الجمع غير مضمون الوصول إلى /proc/<crashing-PID>). القيمة المبدئية لهذا الملف هي 0.

  التحكم في أي تعيينات تُكتب إلى تفريغ النواة
منذ لينكس 2.6.23، يمكن استخدام الملف الخاص بلينكس /proc/pid/coredump_filter للتحكم في أي قطاعات ذاكرة تُكتب إلى ملف تفريغ النواة في حالة تنفيذ تفريغ نواة للعملية بمعرف العملية المقابل.

القيمة في الملف هي قناع بت لأنواع تعيين الذاكرة (انظر mmap(2)). إذا تم تعيين بت في القناع، فإن تعيينات الذاكرة من النوع المقابل تُفرّغ؛ وإلا، لا تُفرّغ. للبتات في هذا الملف المعاني التالية:

    bit 0
        افرغ تعيينات خاصة مجهولة.
    bit 1
        افرغ تعيينات مشتركة مجهولة.
    bit 2
        افرغ تعيينات خاصة مدعومة بملفات.
    bit 3
        تفريغ التعيينات المشتركة المدعومة بالملفات.
    bit 4 (منذ لينكس 2.6.24)
        تفريغ رؤوس ELF.
    bit 5 (منذ لينكس 2.6.28)
        تفريغ الصفحات الضخمة الخاصة.
    bit 6 (منذ لينكس 2.6.28)
        تفريغ الصفحات الضخمة المشتركة.
    bit 7 (منذ لينكس 4.4)
        تفريغ صفحات DAX الخاصة.
    bit 8 (منذ لينكس 4.4)
        تفريغ صفحات DAX المشتركة.

مبدئيًا، تُعيّن البتات التالية: 0، 1، 4 (إذا كان خيار تهيئة النواة CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS مفعّلاً)، و5. يمكن تعديل هذا المبدئي عند الإقلاع باستخدام خيار الإقلاع coredump_filter.

تُعرض قيمة هذا الملف بالنظام الست عشري. (وبالتالي تُعرض القيمة المبدئية كـ 33.)

لا تُفرّغ صفحات الإدخال/الإخراج المعيّنة بالذاكرة مثل مخزن الإطار أبدًا، وتُفرّغ صفحات DSO الافتراضية (vdso(7)) دائمًا، بغض النظر عن قيمة coredump_filter.

ترث عملية فرعية منشأة عبر fork(2) قيمة coredump_filter الخاصة بعملية الأب؛ تُحفظ قيمة coredump_filter عبر execve(2).

قد يكون من المفيد تعيين coredump_filter في الصدفة الأب قبل تشغيل برنامج، على سبيل المثال:

    $ echo 0x7 > /proc/self/coredump_filter
    $ ./some_program

يُوفّر هذا الملف فقط إذا بُنيت النواة مع خيار التهيئة CONFIG_ELF_CORE.

  تفريغات النواة وsystemd
على الأنظمة التي تستخدم إطار init الخاص بـ systemd(1)، قد تُوضع تفريغات النواة في موقع تحدده systemd(1). لفعل ذلك، تستخدم systemd(1) ميزة core_pattern التي تسمح بتوجيه تفريغات النواة إلى برنامج. يمكن التحقق من ذلك بفحص ما إذا كانت تفريغات النواة تُوجّه إلى برنامج systemd-coredump(8):

    $ cat /proc/sys/kernel/core_pattern;
    |/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %e

في هذه الحالة، تُوضع تفريغات النواة في الموقع المكوّن لـ systemd-coredump(8)، عادةً كملفات مضغوطة بـ lz4(1) في الدليل /var/lib/systemd/coredump/. يمكن سرد تفريغات النواة التي سُجّلت بواسطة systemd-coredump(8) باستخدام coredumpctl(1):

    $ coredumpctl list | tail -5;
    Wed 2017-10-11 22:25:30 CEST  2748 1000 1000 3 present  /usr/bin/sleep
    Thu 2017-10-12 06:29:10 CEST  2716 1000 1000 3 present  /usr/bin/sleep
    Thu 2017-10-12 06:30:50 CEST  2767 1000 1000 3 present  /usr/bin/sleep
    Thu 2017-10-12 06:37:40 CEST  2918 1000 1000 3 present  /usr/bin/cat
    Thu 2017-10-12 08:13:07 CEST  2955 1000 1000 3 present  /usr/bin/cat

تتضمن المعلومات المعروضة لكل تفريغ نواة تاريخ ووقت التفريغ، ومعرف العملية (PID)، ومعرف المستخدم (UID)، ومعرف المجموعة (GID) لعملية التفريغ، ورقم الإشارة التي سببت تفريغ النواة، واسم مسار الملف القابل للتنفيذ الذي كانت تشغله العملية المُفرّغة. تسمح الخيارات المختلفة لـ coredumpctl(1) بسحب ملف تفريغ نواة محدد من موقع systemd(1) إلى ملف محدد. على سبيل المثال، لاستخراج تفريغ النواة لمعرف العملية 2955 الموضح أعلاه إلى ملف باسم core في الدليل الحالي، يمكن استخدام:

    $ coredumpctl dump 2955 -o core;

للحصول على تفاصيل أكثر شمولاً، راجع صفحة الدليل coredumpctl(1).

لتعطيل آلية systemd(1) التي تؤرشف تفريغات النواة (بشكل دائم)، واستعادة سلوك أقرب إلى سلوك Linux التقليدي، يمكن تعيين تجاوز لآلية systemd(1) باستخدام شيء مثل:

    # echo "kernel.core_pattern=core.%p" > \;
                   /etc/sysctl.d/50-coredump.conf
    # /lib/systemd/systemd-sysctl;

من الممكن أيضًا تغيير إعداد core_pattern مؤقتًا (أي حتى إعادة الإقلاع التالية) باستخدام أمر مثل التالي (مما يجعل أسماء ملفات تفريغ النواة تتضمن اسم الملف القابل للتنفيذ بالإضافة إلى رقم الإشارة التي سببت تفريغ النواة):

    # sysctl -w kernel.core_pattern="%e-%s.core";

ملاحظات
يمكن استخدام أمر gdb(1) gcore للحصول على تفريغ نواة لعملية قيد التشغيل.

في إصدارات لينكس حتى الإصدار 2.6.27، إذا قامت عملية متعددة الخيوط (أو بشكل أدق، عملية تشارك ذاكرتها مع عملية أخرى عن طريق إنشائها باستخدام علامة CLONE_VM من clone(2)) بتفريغ النواة، فإن معرف العملية يُلحق دائمًا باسم ملف النواة، ما لم يكن معرف العملية مضمنًا بالفعل في مكان آخر من اسم الملف عبر مواصفة %p في /proc/sys/kernel/core_pattern. (هذا مفيد بشكل أساسي عند استخدام تطبيق LinuxThreads القديم، حيث يكون لكل خيط من العملية معرف عملية مختلف.)

أمثلة
يمكن استخدام البرنامج أدناه لتوضيح استخدام صيغة الأنبوب في ملف /proc/sys/kernel/core_pattern. توضح جلسة الصدفة التالية استخدام هذا البرنامج (المُجمّع لإنشاء ملف تنفيذي باسم core_pattern_pipe_test):

    $ cc -o core_pattern_pipe_test core_pattern_pipe_test.c
    $ su
    Password:
    # echo "|$PWD/core_pattern_pipe_test %p UID=%u GID=%g sig=%s" > \
    /proc/sys/kernel/core_pattern
    # exit
    $ sleep 100
    ^\                     # type control-backslash
    Quit (core dumped)
    $ cat core.info
    argc=5
    argc[0]=</home/mtk/core_pattern_pipe_test>
    argc[1]=<20575>
    argc[2]=<UID=1000>
    argc[3]=<GID=100>
    argc[4]=<sig=3>
    Total bytes in core dump: 282624

  مصدر البرنامج
    /* core_pattern_pipe_test.c */

    #define _GNU_SOURCE
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <limits.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>

    #define BUF_SIZE 1024

    int
    main(int argc, char *argv[])
    {
        ssize_t nread, tot;
        char buf[BUF_SIZE];
        FILE *fp;
        char cwd[PATH_MAX];

        /* Change our current working directory to that of the
           crashing process.  */

        snprintf(cwd, PATH_MAX, "/proc/%s/cwd", argv[1]);
        chdir(cwd);

        /* Write output to file "core.info" in that directory.  */

        fp = fopen("core.info", "w+");
        if (fp == NULL)
            exit(EXIT_FAILURE);

        /* Display command-line arguments given to core_pattern
           pipe program.  */

        fprintf(fp, "argc=%d\n", argc);
        for (size_t j = 0; j < argc; j++)
            fprintf(fp, "argc[%zu]=<%s>\n", j, argv[j]);

        /* Count bytes in standard input (the core dump).  */

        tot = 0;
        while ((nread = read(STDIN_FILENO, buf, BUF_SIZE)) > 0)
            tot += nread;
        fprintf(fp, "Total bytes in core dump: %zd\n", tot);

        fclose(fp);
        exit(EXIT_SUCCESS);
    }

انظر أيضًا
bash(1), coredumpctl(1), gdb(1), getrlimit(2), mmap(2), prctl(2), sigaction(2), elf(5), proc(5), pthreads(7), signal(7), systemd-coredump(8)

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

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 (https://www.gnu.org/licenses/gpl-3.0.html) أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

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