لا .bss قسم صفر تهيئة المتغيرات تشغل مساحة في قزم الملف ؟
سؤال
إذا فهمت بشكل صحيح ، .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
تختلف كثيرا عن الرأس الذي يحتوي على قسم bss
(وLOAD
ثانية واحدة):
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
وتطبيق جزءا لا يتجزأ من حيث عدم وجود محمل هذا أمر شائع.
وسومان