في برنامج C/C++، كيف يقوم النظام (windows، linux، mac OS X) باستدعاء الوظيفة main()
سؤال
أنا أبحث عن شرح تقني أكثر ثم يقوم نظام التشغيل باستدعاء الوظيفة.هل يمكن لأي شخص مساعدتي أو توجيهي إلى موقع أو كتاب؟
المحلول
يحتوي الملف .exe (أو ما يعادله على الأنظمة الأساسية الأخرى) على عنوان "نقطة الدخول".كتقريب أولي، يقوم نظام التشغيل بتحميل الأقسام ذات الصلة من ملف .EXE إلى ذاكرة الوصول العشوائي، ثم ينتقل إلى نقطة الإدخال.
كما قال الآخرون، لن تكون نقطة الإدخال هذه "رئيسية"، ولكنها ستكون بدلاً من ذلك جزءًا من مكتبة وقت التشغيل - وستقوم بأشياء مثل تهيئة الكائنات الثابتة، وإعداد معلمات argc/argv، وإعداد stdin/stdout/stderr ، إلخ.عند الانتهاء من كل ذلك، سيتم استدعاء الدالة main() الخاصة بك.عند الخروج الرئيسي، يمر وقت التشغيل بعملية مماثلة لتمرير رمز الإرجاع مرة أخرى إلى البيئة، واستدعاء أدوات التدمير الثابتة، واستدعاء إجراءات _atexit، وما إلى ذلك.
إذا كانت لديك أدوات MS (ربما ليست أدوات الهدية الترويجية)، فلديك كل مصدر وقت التشغيل، والطريقة السهلة للنظر إليها هي وضع نقطة توقف على قوس الإغلاق لطريقة main() الخاصة بك، وخطوة واحدة احتياطية في وقت التشغيل.
نصائح أخرى
main()
جزء من مكتبة C وليس وظيفة نظام.لا أعرف بالنسبة لنظام التشغيل OS X أو Linux، لكن Windows عادةً ما يبدأ البرنامج باستخدام WinMainCRTStartup()
.يبدأ هذا الرمز عمليتك، ويستخرج وسيطات سطر الأوامر والبيئة (argc, argv, end
) والمكالمات main()
.كما أنه مسؤول عن استدعاء أي رمز يجب تشغيله بعد ذلك main()
, ، يحب atexit()
.
من خلال البحث في ملف Visual Studio الخاص بك، يجب أن تكون قادرًا على العثور على التنفيذ الافتراضي لـ WinMainCRTStartup
لنرى ماذا يفعل.
يمكنك أيضًا تحديد وظيفة خاصة بك للاتصال بها عند بدء التشغيل، ويتم ذلك عن طريق تغيير "نقطة الإدخال" في خيارات الرابط.غالبًا ما تكون هذه دالة لا تأخذ أي وسائط وترجع فراغًا.
بقدر ما يتعلق الأمر بالنوافذ، فإن وظائف نقطة الدخول هي:
- وحدة التحكم:
void __cdecl mainCRTStartup( void ) {}
- واجهة المستخدم الرسومية:
void __stdcall WinMainCRTStartup( void ) {}
- مكتبة الارتباط الديناميكي:
BOOL __stdcall _DllMainCRTStartup(HINSTANCE hinstDLL,DWORD fdwReason,void* lpReserved) {}
السبب الوحيد لاستخدامها عبر main/WinMain/DllMain العادي هو إذا كنت تريد استخدام مكتبة وقت التشغيل الخاصة بك (إذا كنت تريد حجم ملف أصغر أو ميزات مخصصة)
للتعرف على تطبيقات وقت التشغيل المخصصة والحيل الأخرى للحصول على ملفات PE أصغر، راجع:
خبير C++/CLI (راجع الصفحة 279) يحتوي على تفاصيل محددة للغاية حول سيناريوهات التمهيد المختلفة لتجميعات CLR الأصلية والمختلطة والنقية.
إنه يعتمد على نظام التشغيل.في OS X، يوجد إطار في رأس mach يحتوي على عنوان البدء لسجل EIP (مؤشر التعليمات).
بمجرد تحميل الملف الثنائي، يبدأ نظام التشغيل التنفيذ من هذا العنوان:
cristi:test diciu$ otool -l ./a.out | grep -A 10 LC_UNIXTHREAD cmd LC_UNIXTHREAD cmdsize 80 flavor i386_THREAD_STATE count i386_THREAD_STATE_COUNT [..] ss 0x00000000 eflags 0x00000000 eip 0x00001f8c cs 0x00000000 [..]
العنوان هو عنوان وظيفة "البدء" من الملف الثنائي:
cristi:test diciu$ nm ./a.out 0000200c D _NXArgc 00002008 D _NXArgv 00002000 D ___progname 00001fe0 t __dyld_func_lookup 00001000 A __mh_execute_header [..] 00001f8c T start
في نظام التشغيل Mac OS X، يتم استدعاء وظيفة "البدء" أولاً، حتى قبل الوظيفة "الرئيسية":
(gdb) b start Breakpoint 1 at 0x1f90 (gdb) b main Breakpoint 2 at 0x1ff4 (gdb) r Starting program: /Users/diciu/Programming/test/a.out Reading symbols for shared libraries ++. done Breakpoint 1, 0x00001f90 in start ()
إذا كنت مهتمًا بكتاب يتعلق بـ Windows وWin32 API، فحاول
"تطبيقات البرمجة لنظام التشغيل Microsoft Windows" بقلم جيفري ريختر.
يمكنك إلقاء نظرة على الروابط التالية: