A Free Trial That Lets You Build Big!
Start building with 50+ products and up to 12 months usage for Elastic Compute Service
Today finally have time to study a very large project compiled into an EXE and a number of DLLs, the program is the first command to execute it? What rules does the operating system use to find the first instruction that should be executed (or how to find the first entry function)?
When we wrote the Windows program before, we wrote a main () function, then wrote our own logic, then compiled, and then click on the EXE to run our program, if we use the VS2005 tool to generate a non-empty project, the project will provide us with an int _tmain (int ARGC, _tchar* argv) or the entrance to the WinMain () function, then we add the program inside and so on. That's what we did when we went to school, but a lot of people take it for granted that few people ask why.
I read the MSDN inside the explanation to make a point, in fact, we have written before the main () function to start the program is a semi-finished, the rest of the system is closely related to the work by the compiler to help us do. What's going on here? How does the compiler help us? Then when the program is loaded by the system, it is accurate to say that the loader in the system is loaded and how to know that the compiler in our written program to do the hands and feet? Is there a contract between the compiler and the loader? These are some of the columns of the problem, as the first line of whether you have asked yourself in the heart did not!?
The program we wrote before is compiled into a module (possibly an obj file or other form), and then the connector connects some of the required library files with the files that were generated by the compiler, eventually generating an EXE file that contains the CRT runtime library in the attached library file. This is the main character we are talking about today. In the run-time library there is a function function that has the following definition:
(1) mainCRTStartup (or wmainCRTStartup)//applications using/subsystem:console
(2) WinMainCRTStartup (or wWinMainCRTStartup)//applications using/subsystem:windows
(3) _DllMainCRTStartup//Call DllMain (if present), DllMain must be defined with __stdcall
Where W begins the function when the Unicode version, the delimiter '//' followed by the entry point function matches the Subsystem property setting.
If the/dll or/subsystem (that is, the SUBSYSTEM option) option is not specified, the linker chooses the subsystem and entry point based on whether main or WinMain is defined. The functions main, WinMain, and DllMain are three user-defined entry point forms.
By default, if your program uses the main () or _main () function, this connector will connect your use (1) function to your EXE, and if your function starts with the Winwain () function, the connector uses the function in (2) to connect to the EXE. If we are writing a DLL program, this connection into the DLL is a function in (3).
When the exe that we write is executed, it starts with one of the above functions, not the main or WinMain that our program writes. So why does the connector do this? This is because the program we write must use a variety of run-time library functions to function properly, all of the necessary libraries must be prepared before we can execute our own program, oh, understand, the reason to connect them is because they have a very important mission, which is to initialize the runtime library, Ready to be called when our program executes.
So what do these functions specifically do? With MSDN we can tell---they go further and invoke other functions, allowing C/+ + Runtime library code to invoke constructors and destructors on static non-local variables.
The first excerpt from MSDN is explained below:
When you link your image, you either explicitly or implicitly specify a entry point, the operating system would call I Nto after loading the image. For a DLLs, the default entry point is DllMainCRTStartup. For an EXE, it iswinmaincrtstartup. You can override the default with THE/ENTRY linker option. The CRT provides an implementation for DllMainCRTStartup, WinMainCRTStartup, and wWinMainCRTStartup (the Unicode entry poi NT for an EXE). These crt-provided entry points call constructors on global objects and initialize other data structures that is use D by some CRT functions. This startup code adds on 25K to your image if it is linked statically. If It is a linked dynamically, the most of the code was in the DLL, so your image size stays small.
You see, I use the red flag above, we can use the linker's link selection to set our function entry point, but it is best not to do so, because I use the blue flag, if we re-set the entry point function, you have to write in the entry point function of the initialization of the work, This is not a hassle, all we'd better use the default entry point function.
Modify entry point method: Proerties->linker->advanced->entrypoint
If the function is consistent with the subsystem properties of the connector:
If the/dll or/SUBSYSTEM option is not specified, the linker chooses the subsystem and entry point based on whether main or WinMain is defined. The functions main, WinMain, and DllMain are three user-defined entry point forms.
From the above analysis, it is known that in the original operating system in the Microsoft System loader and the connector is a protocol, or it will not be successful when loading the running program, such as you put the Windows program on the Apple system to run, can not run, Because Apple's loader doesn't know the protocol to load Windows EXE at all.
* These routines do the C runtime initialization, call the appropriate
* User entry function, and handle termination cleanup. For a managed
* app, they then return the exit code back to the calling routine, which
* is the managed startup code. For a unmanaged app, they call exit and
* Never return.
* Function:user entry called:
* mainCRTStartup Main
* wmainCRTStartup wmain
* WinMainCRTStartup WinMain
* wWinMainCRTStartup wWinMain
Give a blog post that says it better:
There is an executable file under the Win32 MyApp.exe, which is a WIN32 application that conforms to the standard PE format. MyApp.exe's main execution code is concentrated in its source file MyApp.cpp, the first function to be executed is WinMain. Beginners will think that the program is the first to start from this WinMain function, not actually.
Before the WinMain function is executed, there is a series of complex loading actions, and a large number of startup code is executed. When running the program MyApp.exe, the operating system loader first assigns a 4GB virtual address space to the process, and then maps the disk space occupied by the program MyApp.exe as virtual memory into this 4GB virtual address space. In general, it maps to the location of the 0x00400000 in the virtual address space. Loading an application is less time than most people think, because loading a PE file does not take the entire one-time read from disk into memory, but rather simply makes a memory map, mapping a large file and mapping a small file takes a little longer. Of course, when the code in the file is actually executed, the operating system is still swapping the code in the virtual memory that exists on disk into physical memory (RAM). However, this exchange does not swap all the virtual address space occupied by the entire file from disk to physical memory at once, and the operating system swaps one or more pages as needed and memory usage. Of course, this exchange is bidirectional, that is, a part of the physical memory that is not currently in use may also be swapped to disk.
The system then creates the process object and the main thread object and other content in the kernel.
The loader of the operating system then searches the introduction table in the PE file to load the dynamic-link libraries used by all applications. Loading a dynamic-link library is exactly like loading an application.
Then, the operating system executes the code at the address specified in the PE file header, starting the execution of the main thread of the application. The first code executed is not the WinMain function in MyApp, but the WinMainCRTStartup function called C Runtime startup code, which is attached to the file MyApp.exe by the connector. This function obtains a pointer to all command-line pointers and environment variables for the new process, completes some C run-time global variables, and initializes the C run-time memory allocation function. If you are programming with C + +, you also execute constructors for global class objects. Finally, the WinMainCRTStartup function calls the WinMain function.
The 4 parameters passed to the WinMain function by the WinMainCRTStartup function are: hinstance, hPrevInstance, lpCmdLine, nCmdShow, respectively.
HINSTANCE: The handle to the current instance of the application that corresponds to the process. The WinMainCRTStartup function obtains the value of the parameter by calling the Getstartupinfo function. This parameter is actually the address of the application being loaded into the virtual address space of the process, and typically, for most processes, the parameter is always 0x00400000.
hPrevInstance: The handle to the previous instance of the application. Because each instance of an WIN32 application is always running in its own separate process address space, the value passed to the parameter by the WinMainCRTStartup function is always null for WIN32 applications. If the application wants to know if another instance is running, you can create a mutex with a unique name through thread synchronization technology, and you can know if there is another instance running by detecting whether the mutex exists.
lpCmdLine: A pointer to a command-line argument. The pointer points to a string that ends with 0, which does not include the application name.
nCmdShow: Specifies how the application window is displayed. If the program is run by double-clicking the icon in Explorer, the WinMainCRTStartup function passes the value of the parameter to Sw_shownormal. If you run by calling the Creatprocess function in another application, the parameter is specified by the parameter Lpstartupinfo (Startupinfo.wshowwindow) of the creatprocess function.
After the operating system loads the application, it goes to the program's entry point to do the initialization work. The default entry point for a program is set by the linker, and the entry functions selected by different connectors are not the same. Under VC + +, the entry function of the connector to the console program is Maincrtstartup,maincrtstartup and then the main function is called, and the entry function set on the GUI program is WinMainCRTStartup, WinMainCRTStartup calls you to write your own WinMain function. The specific entry point is determined by the connector's "/SUBSYSTEM:" option, which tells the operating system how to run the compiled build. EXE file. There are four ways to specify: console| windows| native| Posix. If the value of this option parameter is WINDOWS, it means that the application does not need a console when it is run, and a detailed description of the connector parameter options is in the MSDN library.
The following four combinations of console and Windows mode can be combined to achieve the effect of not ejecting a DOS window, or to output printf information to the console in a Windows program.
#pragma COMMENT (linker, "/subsystem:windows/entry:winmaincrtstartup")
#pragma COMMENT (linker, "/subsystem:windows/entry:maincrtstartup")
#pragma COMMENT (linker, "/subsystem:console/entry:maincrtstartup")
#pragma COMMENT (linker, "/subsystem:console/entry:winmaincrtstartup")
int Apientry WinMain (hinstance hinstance,
int main (void)
Where is the entry point for the executable program? (Hardening concept: The real entrance to the program is mainCRTStartup)
Start building with 50+ products and up to 12 months usage for Elastic Compute Service