سؤال

يستغرق استنساخ نظام Clone () على Linux معلمة تشير إلى المكدس لخيط جديد تم إنشاؤه لاستخدامه. الطريقة الواضحة للقيام بذلك هي ببساطة Maloc بعض المساحة وتمرير ذلك، ولكن بعد ذلك عليك أن تكون متأكدا من أنك متأكد من أنك مساحة مكدس حيث سيؤدي هذا الموضوع إلى أي وقت مضى (من الصعب التنبؤ).

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

السياق الوحيد الذي سمعتهما من أي وقت مضى MMAP المستخدمة في تعيين الملفات في الذاكرة، وفي الواقع قراءة صفحة MMAP MAN، فإنه يأخذ واصف الملفات. كيف يمكن استخدام هذا لتخصيص كومة من الطول الديناميكي لإعطاء الاستنساخ ()؟ هل هذا الموقع مجنون فقط؟ ؛)

في كلتا الحالتين، لا يحتاج النواة إلى معرفة كيفية العثور على مجموعة مجانية من الذاكرة للحصول على مكدس جديد على أي حال، لأن هذا شيء يجب القيام به طوال الوقت حيث يطلق المستخدم عمليات جديدة؟ لماذا يحتاج مؤشر المكدس إلى تحديده في المقام الأول إذا كان النواة يمكن أن يرفض هذا بالفعل؟

هل كانت مفيدة؟

المحلول

جوزيف، في الإجابة على سؤالك الأخير:

عندما يقوم المستخدم بإنشاء عملية جديدة "عادية"، يتم ذلك بواسطة FORK (). في هذه الحالة، لا داعي للقلق النواة بشأن إنشاء مكدس جديد على الإطلاق، لأن العملية الجديدة هي نسخة مكررة كاملة من القديم، وصولا إلى المكدس.

إذا يحل المستخدم محل العملية قيد التشغيل حاليا باستخدام EXEC ()، فإن Kernel تحتاج إلى إنشاء مكدس جديد - ولكن في هذه الحالة أمر سهل، لأنه يحصل بدء من لائحة فارغة. يمنح Exec () مساحة ذاكرة العملية وتعيقها، لذلك يحصل النواة على القول "بعد EXEC ()، تعيش المكدس هنا دائما هنا".

ومع ذلك، إذا نستخدم استنساخ ()، فيمكننا القول إن العملية الجديدة ستشارك مساحة ذاكرة مع العملية القديمة (Clone_vm). في هذه الحالة، لا يمكن أن تترك النواة المكدس حيث كانت في عملية الاتصال (مثل شوكة () لا)، لأنه ثم فإن العمليات الخاصة بنا ستكون من الدائري على مكدس بعضنا البعض. لا يمكن للنواة أيضا وضعه فقط في موقع افتراضي (مثل EXEC ())، لأن هذا الموقع مأخوذ بالفعل في مساحة الذاكرة هذه. الحل الوحيد هو السماح لعملية الاتصال للعثور على مكان لذلك، وهو ما يفعله.

نصائح أخرى

مداخن ليست كذلك، ولا يمكن أن تكون أبدا غير محدودة في مساحتها للنمو. مثل كل شيء آخر، يعيشون في مساحة العنوان الافتراضية للعملة، والمبلغ الذي يمكن أن ينمو فيه دائما محدودا دائما عن طريق منطقة الذاكرة المعينة المجاورة.

عندما يتحدث الناس عن مكدس نمو ديناميكيا، ما قد يعنيه هو واحد من شيئين:

  • قد تكون صفحات المكدس صفحات صفرية في الكتابة، والتي لا تحصل على نسخ خاصة مصنوعة حتى يتم إجراء الكتابة الأولى.
  • قد لا يتم حجز الأجزاء السفلية من منطقة المكدس بعد (وبالتالي عدم الاعتماد على تهمة العملية العملية، أي أن كمية الذاكرة الفعلية / المبادلة قد تم حساب kernel كما محجوزة للعملية) حتى يتم ضرب صفحة الحرس، والتي الحالة يرتكب kernel أكثر وينقل صفحة الحرس، أو يقتل العملية إذا لم تكن هناك ذاكرة ترتكز.

محاولة الاعتماد على MAP_GROWSDOWN العلم غير موثوق و خطير لأنه لا يستطيع حمايتك mmap إنشاء رسم خريطة جديدة مجاورة لمكدسك، والتي ستحصل عليها بعد ذلك. (يرى http://lwn.net/articles/294001/) بالنسبة للخيط الرئيسي، تحتفظ Kernel تلقائيا بحجم المكدس ulimit قيمته عنوان العنوان (ليس ذاكرة) أسفل المكدس ويمنع mmap من تخصيصها. (ولكن حذار! بعض حبات البائع المكسورة تعطيل هذا السلوك يؤدي إلى تلف الذاكرة العشوائية!) من أجل مواضيع أخرى، أنت ببساطة يجب mmap مجموعة كاملة من مساحة العنوان قد تحتاج الخيط إلى كومة عند إنشاء ذلك. لا توجد وسيلة أخرى. أنت استطاع اجعل معظمها في البداية غير قابل للكتابة / غير قابل للقراءة / غير قابلة للقراءة، وتغيير ذلك على الأعطال، ولكن بعد ذلك، تحتاج إلى معالجات إشارة وهذا الحل غير مقبول في تطبيق مؤشرات التوايه (لاحظ أنه، كملحق، النواة استطاع عرض خاص MAP_ أعلام تسليم إشارة مختلفة بدلا من SIGSEGV فيما يتعلق بالوصول غير القانوني إلى التعيين، ومن ثم تنفيذ المواضيع يمكن أن يمسك وتتصرف بهذه الإشارة. لكن لينكس في الوقت الحاضر لا يوجد لديه هذه الميزة.)

أخيرا، لاحظ أن clone SYSCALL لا تأخذ حجة مؤشر مكدس لأنه لا يحتاج إليها. يجب إجراء SYSCALL من رمز التجميع، لأن غلاف المستخدمين مطلوبا لتغيير مؤشر المكدس في مؤشر مكدس في مؤشر "الطفل" للإشارة إلى المكدس المطلوب، وتجنب كتابة أي شيء إلى مكدس الوالد.

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

ليس فقط تعديل مؤشر المكدس المستحيل من ج، لكنك لم تتمكن أيضا من تجنب احتمال أن يقوم المحول البرمجي بإضواء كومة الوالدين بعد تغيير مؤشر المكدس.

كنت تريد العلم map_anonymate ل mmap. و map_growsdown لأنك تريد الاستفادة منها كتكدس.

شيء مثل:

void *stack = mmap(NULL,initial_stacksize,PROT_WRITE|PROT_READ,MAP_PRIVATE|MAP_GROWSDOWN|MAP_ANONYMOUS,-1,0);

راجع صفحة MMAP MAN لمزيد من المعلومات. وتذكر، استنساخ هو مفهوم منخفض المستوى، لا تهدف إلى استخدامه إلا إذا كنت بحاجة حقا إلى ما يقدمه. ويقدم الكثير من التحكم - مثل إعداد كومة خاصة - فقط في حال كنت ترغب في القيام ببعض الخصر (مثل وجود المكدس يمكن الوصول إليه في جميع العمليات ذات الصلة). ما لم يكن لديك سبب وجيه للغاية لاستخدام استنساخ أو عصا مع شوكة أو pthreads.

فيما يلي الكود الذي MMAPS منطقة مكدس وترشير مكالمة نظام استنساخ لاستخدام هذه المنطقة كتكدس.

#include sys/mman.h>
#include stdio.h>
#include string.h>
#include sched.h>
int execute_clone(void *arg)
{
    printf("\nclone function Executed....Sleeping\n");
    fflush(stdout);
    return 0;
}

int main()
{
    void *ptr;

    int rc;
    void *start =(void *) 0x0000010000000000;
    size_t len = 0x0000000000200000;

    ptr = mmap(start, len, PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED|MAP_GROWSDOWN, 0, 0);
    if(ptr == (void *)-1) 
    {
        perror("\nmmap failed");
    }

    rc = clone(&execute_clone, ptr + len, CLONE_VM, NULL);

    if(rc <= 0) 
    {
        perror("\nClone() failed");
    }
}

mmap هو أكثر من مجرد تعيين ملف في الذاكرة. في الواقع، ستستخدم بعض تطبيقات Malloc MMAP للمخصصات الكبيرة. إذا قرأت صفحة الرجل الجميلة، فستلاحظ العلم map_anonymous، وسترى أنك لا تحتاج إلى توفير واصف الملف على الإطلاق.

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

نلاحظ أن clone دعوة النظام لا خذ حجة لموقع المكدس. يعمل في الواقع مثل fork. وبعد انها مجرد غلاف glibc الذي يأخذ هذه الحجة.

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top