في برنامج C/C++، كيف يقوم النظام (windows، linux، mac OS X) باستدعاء الوظيفة main()

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

  •  08-06-2019
  •  | 
  •  

سؤال

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

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

المحلول

يحتوي الملف .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" بقلم جيفري ريختر.

يمكنك إلقاء نظرة على الروابط التالية:

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