pid_namespaces(7)

الاسم
pid_namespaces - نظرة عامة على مساحات أسماء PID في لينكس

الوصف
للحصول على نظرة عامة على مساحات الأسماء، انظر namespaces(7).

تعزل مساحات أسماء PID فضاء أرقام معرفات العمليات، مما يعني أن العمليات في مساحات أسماء PID مختلفة يمكن أن تمتلك نفس PID. تسمح مساحات أسماء PID للحاويات بتوفير وظائف مثل تعليق/استئناف مجموعة العمليات في الحاوية وترحيل الحاوية إلى مضيف جديد مع احتفاظ العمليات داخل الحاوية بنفس معرفات PID.

تبدأ معرفات PID في مساحة أسماء PID جديدة من 1، بشكل يشبه النظام المستقل، وتنتج استدعاءات fork(2) أو vfork(2) أو clone(2) عمليات ذات معرفات PID فريدة داخل مساحة الاسم.

يتطلب استخدام مساحات أسماء PID نواة مكونة مع الخيار CONFIG_PID_NS.

  عملية init لمساحة الاسم
تمتلك أول عملية منشأة في مساحة اسم جديدة (أي العملية المنشأة باستخدام clone(2) مع العلم CLONE_NEWPID، أو أول طفل منشأ بواسطة عملية بعد استدعاء unshare(2) باستخدام العلم CLONE_NEWPID) PID 1، وهي عملية "init" لمساحة الاسم (انظر init(1)). تصبح هذه العملية الوالد لأي عمليات طفل يتيمة بسبب إنهاء عملية تقع في مساحة اسم PID هذه (انظر أدناه لمزيد من التفاصيل).

إذا أنهيت عملية "init" لمساحة اسم PID، تنهي النواة جميع العمليات في مساحة الاسم عبر إشارة SIGKILL. يعكس هذا السلوك حقيقة أن عملية "init" أساسية للتشغيل الصحيح لمساحة اسم PID. في هذه الحالة، يفشل استدعاء fork(2) لاحق إلى مساحة اسم PID هذه مع الخطأ ENOMEM؛ لا يمكن إنشاء عملية جديدة في مساحة اسم PID التي أنهيت عملية "init" الخاصة بها. يمكن أن تحدث مثل هذه السيناريوهات عندما، على سبيل المثال، تستخدم عملية واصف ملف مفتوح لملف /proc/pid/ns/pid مطابق لعملية كانت في مساحة اسم لـ setns(2) إلى تلك المساحة بعد إنهاء عملية "init". يمكن أن يحدث سيناريو آخر محتمل بعد استدعاء unshare(2): إذا أنهي أول طفل منشأ لاحقًا بواسطة fork(2)، فإن استدعاءات fork(2) اللاحقة تفشل مع ENOMEM.

يمكن إرسال الإشارات التي أنشأت عملية "init" معالج إشارة لها فقط إلى عملية "init" بواسطة أعضاء آخرين في مساحة اسم PID. ينطبق هذا التقييد حتى على العمليات المميزة، ويمنع الأعضاء الآخرين في مساحة اسم PID من قتل عملية "init" عن طريق الخطأ.

وبالمثل، يمكن لعملية في مساحة اسم سلف—مع مراعاة فحوصات الإذن المعتادة الموصوفة في kill(2)—إرسال إشارات إلى عملية "init" لمساحة اسم PID فرعية فقط إذا أنشأت عملية "init" معالجًا لتلك الإشارة. (داخل المعالج، سيكون حقل siginfo_t si_pid الموصوف في sigaction(2) صفرًا.) تُعامل SIGKILL أو SIGSTOP بشكل استثنائي: تُسلم هذه الإشارات قسرًا عند إرسالها من مساحة اسم PID سلف. لا يمكن لعملية "init" التقاط أي من هاتين الإشارتين، وبالتالي ستؤدي إلى الإجراءات المعتادة المرتبطة بتلك الإشارات (إنهاء العملية وإيقافها على التوالي).

بدءًا من لينكس 3.4، يتسبب استدعاء النظام reboot(2) في إرسال إشارة إلى عملية "init" لمساحة الاسم. انظر reboot(2) لمزيد من التفاصيل.

  تداخل مساحات أسماء PID
يمكن تداخل مساحات أسماء PID: لكل مساحة اسم PID والد، باستثناء مساحة اسم PID الأولية ("الجذر"). والد مساحة اسم PID هو مساحة اسم PID للعملية التي أنشأت مساحة الاسم باستخدام clone(2) أو unshare(2). تشكل مساحات أسماء PID بذلك شجرة، مع تتبع جميع مساحات الاسم نسبها في النهاية إلى مساحة الاسم الجذر. منذ لينكس 3.7، تحد النواة أقصى عمق تداخل لمساحات أسماء PID إلى 32.

تكون العملية مرئية للعمليات الأخرى في مساحة اسم PID الخاصة بها، وللعمليات في كل مساحة اسم PID سلف مباشر عائدًا إلى مساحة اسم PID الجذر. في هذا السياق، يعني "مرئي" أن عملية يمكن أن تكون هدفًا لعمليات من قبل عملية أخرى باستخدام استدعاءات نظام تحدد معرف عملية. على العكس، لا يمكن للعمليات في مساحة اسم PID فرعية رؤية العمليات في مساحة الاسم الوالد ومساحات الاسم السلف البعيدة. بشكل أكثر إيجازًا: يمكن لعملية رؤية (مثل إرسال إشارات باستخدام kill(2)، تعيين قيم nice باستخدام setpriority(2)، إلخ) فقط العمليات الموجودة في مساحة اسم PID الخاصة بها وفي سلالات تلك المساحة.

تمتلك العملية معرف عملية واحد في كل طبقة من طبقات تسلسل مساحة اسم PID التي تكون مرئية فيها، والعودة عبر كل مساحة اسم سلف مباشر حتى مساحة اسم PID الجذر. تعمل استدعاءات النظام التي تعمل على معرفات العملية دائمًا باستخدام معرف العملية المرئي في مساحة اسم PID للمتصل. يعيد استدعاء getpid(2) دائمًا PID المرتبط بمساحة الاسم التي أنشئت فيها العملية.

قد يكون لبعض العمليات في مساحة اسم PID آباء خارج مساحة الاسم. على سبيل المثال، والد العملية الأولية في مساحة الاسم (أي عملية init(1) مع PID 1) هو بالضرورة في مساحة اسم أخرى. وبالمثل، فإن الأطفال المباشرين لعملية تستخدم setns(2) لجعل أطفالها ينضمون إلى مساحة اسم PID هم في مساحة اسم PID مختلفة عن متصل setns(2). تعيد استدعاءات getppid(2) لمثل هذه العمليات 0.

بينما قد تنزل العمليات بحرية إلى مساحات اسم PID فرعية (مثل استخدام setns(2) مع واصف ملف مساحة اسم PID)، لا يمكنها التحرك في الاتجاه الآخر. أي أن العمليات لا يمكنها دخول أي مساحات اسم سلف (والد، جد، إلخ). تغيير مساحات أسماء PID هو عملية باتجاه واحد.

يمكن استخدام عملية NS_GET_PARENT ioctl(2) لاكتشاف العلاقة الوالدية بين مساحات أسماء PID؛ انظر ioctl_nsfs(2).

  دلالات setns(2) و unshare(2)
تتسبب استدعاءات setns(2) التي تحدد واصف ملف مساحة اسم PID واستدعاءات unshare(2) مع العلم CLONE_NEWPID في وضع الأطفال المنشأين لاحقًا بواسطة المتصل في مساحة اسم PID مختلفة عن المتصل. (منذ لينكس 4.12، تُعرض مساحة اسم PID تلك عبر ملف /proc/pid/ns/pid_for_children، كما هو موصوف في namespaces(7).) لا تغير هذه الاستدعاءات، مع ذلك، مساحة اسم PID لعملية المتصل، لأن القيام بذلك سيغير فكرة المتصل عن PID الخاص به (كما أبلغ عنها getpid())، مما سيكسر العديد من التطبيقات والمكتبات.

لوضع الأمور بطريقة أخرى: تُحدد عضوية مساحة اسم PID للعملية عند إنشاء العملية ولا يمكن تغييرها بعد ذلك. من بين أمور أخرى، يعني هذا أن العلاقة الوالدية بين العمليات تعكس العلاقة الوالدية بين مساحات أسماء PID: والد العملية إما في نفس مساحة الاسم أو يقيم في مساحة اسم PID الوالد المباشر.

يمكن لعملية استدعاء unshare(2) مع العلم CLONE_NEWPID مرة واحدة فقط. بعد أن تنفذ هذه العملية، سيكون رابطها الرمزي /proc/pid/ns/pid_for_children فارغًا حتى يُنشأ الطفل الأول في مساحة الاسم.

  تبني الأطفال اليتامى
عندما يصبح أحد العمليات الفرعية معزولًا، يُعاد ربطه بالعملية "init" في نطاق أسماء PID الخاص بالعملية الأصلية (إلا إذا استخدم أحد أسلاف العملية الأصلية الأقرب الأمر prctl(2) PR_SET_CHILD_SUBREAPER لتمييز نفسه كحاصد للعمليات الفرعية المعزولة).لاحظ أنه نظرًا لدلالات setns(2) وunshare(2) المذكورة أعلاه، فقد تكون هذه العملية "init" في نطاق أسماء PID الذي يمثل parent لنطاق أسماء PID الخاص بالعملية الفرعية، وليس العملية "init" في نطاق أسماء PID الخاص بالعملية الفرعية نفسها.

  توافق CLONE_NEWPID مع علامات CLONE_* الأخرى
في الإصدارات الحالية من لينكس، لا يمكن الجمع بين CLONE_NEWPID وCLONE_THREAD. يجب أن تكون الخيوط في نفس مساحة أسماء PID بحيث تتمكن الخيوط الموجودة في عملية ما من إرسال إشارات لبعضها البعض. وبالمثل، يجب أن يكون من الممكن رؤية جميع خيوط العملية في نظام الملفات proc(5) . بالإضافة إلى ذلك، إذا كان خيطان في مساحات أسماء PID مختلفة، فلن يكون من الممكن ترميز معرف العملية التي ترسل الإشارة بشكل ذي معنى عند إرسال الإشارة (انظر وصف النوع siginfo_t في sigaction(2)). نظرًا لأن هذا يُحسب عند إدراج الإشارة في قائمة الانتظار، فإن قائمة انتظار الإشارات المشتركة بين العمليات في مساحات أسماء PID متعددة ستحبط ذلك.

في الإصدارات السابقة من لينكس، كان CLONE_NEWPID ممنوعًا أيضًا (يفشل مع الخطأ EINVAL) بالاقتران مع CLONE_SIGHAND (قبل لينكس 4.3) وكذلك CLONE_VM (قبل لينكس 3.12). التغييرات التي رفعت هذه القيود نُقلت أيضًا إلى النوى المستقرة السابقة.

  /proc ومساحات أسماء PID
نظام الملفات /proc يُظهر (في الدلائل /proc/pid) فقط العمليات المرئية في مساحة اسم PID للعملية التي نفذت الوصل، حتى لو نُظر إلى نظام الملفات /proc من عمليات في مساحات أسماء أخرى.

بعد إنشاء مساحة اسم PID جديدة، من المفيد للطفل تغيير دليله الجذر ووصل مثيل procfs جديد في /proc حتى تعمل أدوات مثل ps(1) بشكل صحيح. إذا أُنشئت مساحة اسم وصل جديدة في وقت واحد بتضمين CLONE_NEWNS في وسيط flags لـ clone(2) أو unshare(2)، فليس من الضروري تغيير الدليل الجذر: يمكن وصل مثيل procfs جديد مباشرة فوق /proc.

من شل، الأمر لوصل /proc هو:

    $ mount -t proc proc /proc

استدعاء readlink(2) على المسار /proc/self يُنتج معرف العملية للمتصل في مساحة اسم PID لوصل procfs (أي مساحة اسم PID للعملية التي وصلت procfs). يمكن أن يكون هذا مفيدًا لأغراض الاستبطان، عندما تريد عملية اكتشاف PID الخاص بها في مساحات أسماء أخرى.

  ملفات /proc

/proc/sys/kernel/ns_last_pid (منذ لينكس 3.3)
    هذا الملف (الذي يُظاهَر لكل مساحة اسم PID) يُظهر آخر PID خُصص في مساحة اسم PID هذه. عندما يُخصص PID التالي، سيبحث النواة عن أدنى PID غير مخصص أكبر من هذه القيمة، وعند قراءة هذا الملف لاحقًا سيُظهر ذلك PID.

    هذا الملف قابل للكتابة بواسطة عملية تمتلك إمكانية CAP_SYS_ADMIN أو (منذ لينكس 5.9) CAP_CHECKPOINT_RESTORE داخل مساحة اسم المستخدم التي تملك مساحة اسم PID. هذا يجعل من الممكن تحديد PID الذي سيُخصص للعملية التالية التي تُنشأ داخل مساحة اسم PID هذه.

  متفرقات
عند تمرير معرف عملية عبر مقبس نطاق يونكس إلى عملية في مساحة اسم PID مختلفة (انظر وصف SCM_CREDENTIALS في unix(7))، يُترجم إلى قيمة PID المقابلة في مساحة اسم PID للعملية المستقبلة.

المعايير
لينكس.

أمثلة
راجع user_namespaces(7).

انظر أيضًا
clone(2), reboot(2), setns(2), unshare(2), proc(5), capabilities(7), credentials(7), mount_namespaces(7), namespaces(7), user_namespaces(7), switch_root(8)

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

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

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