لا .bss قسم صفر تهيئة المتغيرات تشغل مساحة في قزم الملف ؟

StackOverflow https://stackoverflow.com/questions/610682

  •  03-07-2019
  •  | 
  •  

سؤال

إذا فهمت بشكل صحيح ، .bss القسم في قزم الملفات المستخدمة في تخصيص مساحة صفر-تهيئة المتغيرات.لدينا سلسلة أداة تنتج ملفات ELF ، وبالتالي سؤالي:لا .bss القسم فعلا يجب أن تحتوي على كل تلك الأصفار ؟ يبدو مثل هذا هدر المساحات أنه عندما أقول أنني تخصيص عالمي عشرة ميغا بايت مجموعة في عشرة ميغا بايت من الاصفار في الملف ELF.ما أرى الخطأ هنا ؟

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

المحلول

تم منذ بعض الوقت عملت مع ELF. ولكن أعتقد أنني ما زلت أتذكر هذه الأشياء. لا، انها لا تحتوي على جسديا تلك الأصفار. اذا نظرتم الى رأس ملف البرنامج ELF، ثم سترى كل رأس له رقمين: الأول هو حجم في الملف. وآخر هو حجم والقسم وعندما المخصصة في الذاكرة الظاهرية (readelf -l ./a.out):

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4
  INTERP         0x000114 0x08048114 0x08048114 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /lib/ld-linux.so.2]
  LOAD           0x000000 0x08048000 0x08048000 0x00454 0x00454 R E 0x1000
  LOAD           0x000454 0x08049454 0x08049454 0x00104 0x61bac RW  0x1000
  DYNAMIC        0x000468 0x08049468 0x08049468 0x000d0 0x000d0 RW  0x4
  NOTE           0x000128 0x08048128 0x08048128 0x00020 0x00020 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4

ورؤوس من نوع LOAD هي واحدة التي يتم نسخها في الذاكرة الظاهرية عند تحميل ملف للتنفيذ. تحتوي على رؤوس أخرى معلومات أخرى، مثل المكتبات المشتركة التي يحتاجها. كما ترون، وFileSize وMemSiz تختلف كثيرا عن الرأس الذي يحتوي على قسم bssLOAD ثانية واحدة):

0x00104 (file-size) 0x61bac (mem-size)

لهذا المثال رمز:

int a[100000];
int main() { }

ومواصفات ELF تقول ان جزءا من شريحة إلى أن حجم ذاكرة أكبر من حجم ملف شغل للتو مع الأصفار في الذاكرة الظاهرية. الجزء إلى قسم الخرائط من رأس LOAD الثاني هو من هذا القبيل:

03     .ctors .dtors .jcr .dynamic .got .got.plt .data .bss

وحتى أن هناك بعض الأقسام الأخرى في ذلك أيضا. لC ++ منشئ / تالفة. ونفس الشيء بالنسبة للجافا. ثم أنه يحتوي على نسخة من قسم .dynamic وغيرها من الاشياء مفيدة لربط حيوي (وأعتقد أن هذا هو المكان الذي يحتوي على المكتبات المشتركة اللازمة بين الأشياء الأخرى). بعد أن القسم .data الذي يحتوي غلوبالس تهيئته والمتغيرات الثابتة المحلية. في النهاية، يظهر مقطع .bss، الذي شغل من قبل الأصفار في وقت التحميل لملف بحجم لا يغطي ذلك.

وبالمناسبة، يمكنك ان ترى في القسم الانتاج الذي رمز معين سوف يتم وضعها باستخدام الخيار -M رابط. لدول مجلس التعاون الخليجي، يمكنك استخدام -Wl,-M لوضع الخيار من خلال رابط. يظهر المثال أعلاه أن يتم تخصيص a داخل .bss. قد تساعدك على التحقق من أن الأجسام غير مهيأ بك تنتهي حقا في .bss وليس في مكان آخر:

.bss            0x08049560    0x61aa0
 [many input .o files...]
 *(COMMON) 
 *fill*         0x08049568       0x18 00
 COMMON         0x08049580    0x61a80 /tmp/cc2GT6nS.o
                0x08049580                a
                0x080ab000                . = ALIGN ((. != 0x0)?0x4:0x1) 
                0x080ab000                . = ALIGN (0x4) 
                0x080ab000                . = ALIGN (0x4) 
                0x080ab000                _end = .

ودول مجلس التعاون الخليجي يبقى غير مهيأ غلوبالس في القسم المشترك افتراضيا، من أجل التوافق مع المجمعين القديمة، التي تسمح لغلوبالس المحددة مرتين في البرنامج دون أخطاء تعريف متعددة. استخدام -fno-common لجعل استخدام دول مجلس التعاون الخليجي الأقسام .bss لملفات الكائن (لا تحدث فرقا لتنفيذ مرتبطة النهائي، لأنه كما ترون انها سوف ندخل في قسم الانتاج .bss على أي حال. يتم التحكم هذه من قبل رابط النصي . عرض مع ld -verbose). ولكن هذا لا ينبغي أن يخيف لكم، انها مجرد التفاصيل الداخلية. رؤية manpage من دول مجلس التعاون الخليجي.

نصائح أخرى

على .bss القسم في الملف ELF يستخدم البيانات الثابتة التي لم يتم تهيئة برمجيا ولكن ضمان أن يتم تعيين إلى الصفر في وقت التشغيل.هنا بعض الأمثلة التي سوف يشرح الفرق.

int main() {
    static int bss_test1[100];
    static int bss_test2[100] = {0};
    return 0;
}

في هذه الحالة bss_test1 يتم وضعها في .bss لأنه غير مهيأ. bss_test2 ومع ذلك يتم وضعها في .data الجزء جنبا إلى جنب مع مجموعة من الأصفار.وقت التشغيل محمل أساسا يخصص مقدار المساحة المخصصة .bss و أصفار من ذلك قبل أي يوزرلاند رمز يبدأ تنفيذ.

يمكنك أن ترى الفرق باستخدام objdump, nm, أو المرافق المماثلة:

moozletoots$ objdump -t a.out | grep bss_test
08049780 l     O .bss   00000190              bss_test1.3
080494c0 l     O .data  00000190              bss_test2.4

هذا هو عادة واحدة من أول مفاجآت جزءا لا يتجزأ من المطورين تصل الى...لم تهيئة السكون إلى الصفر صراحة.وقت التشغيل محمل (عادة) تأخذ الرعاية من ذلك.بمجرد تهيئة أي شيء صراحة, كنت تقول مترجم/رابط إدراج البيانات في الملف القابل للتنفيذ الصورة.

لا تخزن قسم .bss في ملف قابل للتنفيذ. من المقاطع الأكثر شيوعا (.text، .data، .bss.text فقط (رمز الفعلي) و.data (بيانات تهيئة) موجودة في ملف ELF.

وهذا هو الصحيح، .bss لم يتم تقديم فعليا في ملف، وليس فقط المعلومات حول حجمه موجودة لمحمل ديناميكية لتخصيص قسم .bss لتطبيق البرنامج. كما حكم الإبهام LOAD فقط، TLS الجزء يحصل على الذاكرة لتطبيق البرنامج، وتستخدم الباقي لمحمل الحيوية.

وعن ملف تنفيذي ثابت، BSS أقسام كما تعطى مساحة في execuatble

وتطبيق جزءا لا يتجزأ من حيث عدم وجود محمل هذا أمر شائع.

وسومان

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