Core summary of Windows core programming (chapter fourth process (i)) (2018.6.8)

Source: Internet
Author: User

Learning Goals

The fourth chapter of the process of learning can be a heavy and far, although not difficult, but a lot of knowledge, but also more fragmented, need to summarize, mind the process of the framework. So, I'll divide this chapter into several subsections. I still add auxiliary content as always, hope for small white help. And more than I have a lot of abuses, the gods can skip the auxiliary content. The learning objectives in this section are as follows:
1.c/c++ Program Compilation process
2.c/c++ use of command line arguments
3. What is a process
Entry point function for 4.Windows
5. Process instance handle (executable file instance handle or DLL file instance handle)

C + + program compilation process

The compile and link process of C/C + + is to convert a C + + program (source code) that we write into a program that can run on hardware (executable code) that needs to be compiled and linked. Compiling is the process of translating text form source code into a target file in the form of machine language. A link is the process of organizing the target file, the operating system's startup code, and the library file used to form the resulting executable code. The process plots are as follows:

The command line for C + +

The main function in C + + language, often with parameter argc,argv, is as follows:

int main(int argc, char** argv)int main(int argc, char* argv[])

From the formal view of the function parameter, it contains an integer and an array of pointers. When the source program is compiled and linked, the extension is generated. EXE executable file, which is a file that can be run directly under the operating system, in other words, is started by the system to run. Since the main () function cannot be called and passed by other functions, the parameter can only be passed by the system at startup run time. In an operating system environment, a complete run command should consist of two parts: the command and the corresponding parameters. The format is: Command parameter 1 parameter 2 .... Parameter n? This format is also known as the command line. commands on the command line are the file names of the executable file, followed by a space-delimited argument, and a further complement to the command, which is the argument passed to the main () function.
The command line has the following relationship to the parameters of the main () function:

设命令行为:program str1 str2 str3 str4 str5

Where program is the file name, which is a compiled by PROGRAM.C, linked to the generated executable file Program.exe, followed by 5 parameters. For the main () function, its parameter ARGC records the number of commands and arguments in the command line, a total of 6, the size of the pointer array is determined by the value of the parameter argc, that is, char*argv[6], the value of the array of pointers as shown:

Each pointer to an array points to a string, respectively. It should be noted that each pointer to the array of pointers received is received from the beginning of the command line, first received is the command, followed by the parameter.

What is a process

(1) Concept of the process
It is written in the original book: A process, is a running program! A program that can produce multiple processes.
1. A kernel object, which is used by the system to manage the process, contains some policy information about the process.
2. An address space, this address space contains executable code, dynamic link Library module code, data, program dynamic memory allocation obtained memory, also in this memory address space.

In the operating system related to the book is said: by the program section, the relevant data section and the three parts of the PCB process, so, in fact, the program section, the relevant data section is an address space, and the PCB (Process Control block) is the kernel object.
(1) Process and thread relationships
The text in the book reads: The process is "inert", and the process must have a thread running in its context to do everything. The thread is responsible for executing the code contained in the process address space. In fact, a process can have multiple threads, and all Threads "execute code simultaneously" in the address space of the process. ... Some words are omitted here .... Each process must have at least one thread to execute the code contained in the process address space. When the system creates a process, the first thread is automatically created for the process, called the main thread. The main thread then creates more threads, and the latter creates more threads. A single CPU, which allocates CPUs for threads, uses loops, allocates time slices for each thread, and multiple CPUs, taking more sophisticated algorithms to allocate CPUs to threads.
How do you understand the relationship between processes and threads? An example would be very thorough. When double-clicking a program produces a factory (process) that also produces the first person----director (primary thread: The main thread), the director only does one thing is to recruit (create) employees (threads), let other employees (threads) to help him do things. There are two ways the factory will collapse (process destruction), the first is that the factory employees (threads, including the main thread) all exit or destroy, then the factory will naturally collapse (process destruction). The second method is to call the ExitProcess function to end the process directly, the second method will be described later, it is now known that this method to end the process.

Entry point functions for Windows

Windows supports two types of applications: GUI programs (graphical user interface programs) and Cui programs (console user interface programs). When we use Visual Studio to create an application project, the integrated development environment sets up a variety of linker switches that allow the linker to embed the correct C + + + + Run startup function of the subsystem into the resulting executable file. For GUI programs, the linker switch is/subsystem:console; for the CUI program, the linker switch is/subsystem:windows. When learning C and C + +, when running an executable file, we all think that the first function of the system call is the entry point function (for example: main function), but actually the operating system does not actually call the entry point function we write (for example: main function), actually the first call is the C/D + + Runtime's startup function. The application type and the corresponding entry function:

Application Type entry point function the startup function that embeds the executable file
GUI applications that handle ANSI characters and strings _tWinMain (WinMain) WinMainCRTStartup
GUI applications that handle Unicode characters and strings _tWinMain (wWinMain) wWinMainCRTStartup
Cui applications that handle ANSI characters and strings _tmain (Main) mainCRTStartup
Cui application that handles Unicode characters and strings _tmain (Wmain) wmainCRTStartup

To generate an executable file, you must go through the process of compiling the link. When linked to an executable file, if the system discovers that the item specifies the/SUBSYSTEM:WINDOWS linker switch, the linker looks for the WinMain or wWinMain function in the program code. If these two functions are not found (either the entry point function is written as the main or WMAin function or the entry point function is not written), the linker returns a "unresolved external symbol" (an unresolved external symbol error), and if the two functions are found, Select the WinMainCRTStartup or wWinMainCRTStartup startup function depending on the case (Unicode or multibyte character set), and then embed the startup function in the executable file. Similarly, if the system discovers that the item specifies a/SUBSYSTEM:CONSOLE linker switch, the linker looks for the main or wmain function in the program code. If these two functions are not found (either the entry point function is written as a WinMain or wWinMain function or the entry point function is not written), the linker returns a "unresolved external symbol" (an unresolved external symbol error), and if the two functions are found, Select the mainCRTStartup or wmainCRTStartup startup function depending on the case (Unicode or multibyte character set), and then embed the startup function in the executable file.
So far, an executable file has been generated. So what happens next? When an executable file is run, what does the startup function do?

所有C/C++运行库启动函数所做的事情基本都是一样的,区别就在于它们要处理的是ANSI字符串,还是Unicode字符串;以及在初始化C运行库之后,它们调用的是哪一个入口点函数。这些C运行时库函数,主要完成以下任务:1.  获取进程命令行指针;2.  获取进程环境变量指针;3.  初始化C/C++运行时库的全局变量,如果你包含了头Stdlib.h,那么你就可以访问这些变量!初始化malloc函数的内存堆;4.  为C++全局类,调用构造函数。

Note: malloc function, not easy to use? Because this function is generally called the Windows API function, we call VirtualAlloc's WindowsAPI function directly, the efficiency will be high!
Let's see what global variables the startup function initializes, as shown below:


Well, we know what the startup function does. When all of these initialization operations are complete, the C/C + + Start function invokes the application's entry point function. If the source file writes a _twinmain, and the _UNICODE is defined (that is, the project property is set to the UNICODE character set), it is called in the following form:

GetStartupInfo(&StartupInfo);int nMainRetVal = wWinMain((HINSTANCE)&__ImageBase,   NULL, pszCommandLineUnicode,   (StartupInfo.dwFlags & STARTF_USESHOWWINDOW) ?    StartupInfo.wShowWindow:SW_SHOWDEFAULT);

If _UNICODE is not defined (that is, the project property is set to a multibyte character set), it is called in the following form:

GetStartupInfo(&StartupInfo);int nMainReLVal = WinMain((HINSTANCE)&__ImageBase,   NULL, pszCommandLineANSI,   (StartupInfo.dwFlags & STARTF_USESHOWWINDOW) ?    Startupinfo.wShowWindow:SW_SHOWDEFAULT);

Note that the above __imagebase is a linker-defined pseudo-variable that indicates that the executable file is mapped to a starting position in the process address space .
If the source file writes a _tmain, and the _UNICODE is defined (that is, the project property is set to the UNICODE character set), it is called in the following form:

If _UNICODE is not defined (that is, the project property is set to a multibyte character set), it is called in the following form:

int nMainRetVal = main(argc, argv, environ);

Children's shoes are sure to wonder why the passed arguments are not global variables argc,argv, or __WARGV (these three global variables are double-underlined, typesetting problems are not shown) when starting a function call entry function. Then we do the source code stripping test: I first wrote a cui program, only a _tmain function, and then debug, view the stack, double-click the blue area below me, to see where to go, you will find the jump to the entrance function of the call, it seems correct, the parameters are really argc and so on.

Then we look at these argc, argv, where Environ is assigned, in fact, a function (_wgetmainargs) call above this header is assigned, but since I can't see the definition of this function (_wgetmainargs), So I guess it's the function that uses the global variable of the double underscore we talked about earlier. In summary, Microsoft's Windows is too closed, the source code did not release it is really uncomfortable.

Process instance handle (executable file instance handle or DLL file instance handle)

We learned from the previous study that when a program is run, a process is generated, and then there are two parts of the process, one of which is the process address space, and each executable file or DLL file loaded into the process address space is given a unique instance handle. The two instance handles represent the loaded executable file, or DLL, which we call the executable or DLL as a module in the process address space! The essence of the process instance handle is the start address of the current module loading the process address space. The type of the process instance handle is hinstance. Children who have studied Windows programming are aware of the usefulness of instance handles, which are used in many places in the program, especially when loading a resource:

LoadIcon(    HINSTANCE hInstance;    PCTSTR pszIcon);

(1) Since it is often necessary to use this process instance handle elsewhere in the program, consider saving the HINSTANCE parameter in a global variable, but as the saying goes, you can use global variables without global variables. To cater to the slang, here are a few ways to get a handle to a process instance:

1.  (w)WinMain函数的第一个参数,可执行文件的实例句柄会在启动函数调用入口函数 (w)WinMain时传入。2.  GetModuleHandle()函数返回指定文件名的实例句柄

Here is the GetModuleHandle () function signature:

HMODULE WINAPI GetModuleHandle(  __in_opt  LPCTSTR lpModuleName//模块名称,其实就是可执行文件或者DLL文件的名称。);

The GetModuleHandle () function gets the first address of the process module (executable module or DLL file module) in the process address space! Precautions for using this function:

1.  如果这个函数的参数是NULL的话,那么这个函数只返回当前可执行的模块地址!!2.  在DLL中,调用GetModuleHandle,参数为NULL,那么这个函数返回的不是DLL模块的地址,而是当前可执行的模块地址!3.  这个函数只检查本进程地址空间,不检查别的进程的地址空间。例如:如果一个ComDlg32.dll文件被载入了另一个B进程地址空间,那么 这个函数在A进程地址空间的代码中调用这个函数,这个函数不检查B的进程地址空间,所以在A进程地址空间没找到就返回NULL。

In fact, either the first argument of the (W) WinMain function or the process instance handle obtained by the GetModuleHandle function, this process instance handle refers to the base address of the executable file or DLL file module that is loaded into the process address space. The base site defaults to 0x00400000, which can be adjusted at the base address, the random base address at the high level of the project------------------set the random base address to no, and then fill in the base address with "0x00100000", so that each time The executable file or DLL file starts at the 0x00100000 base address.
The following is a test of the use of the GetModuleHandle function:

#include<windows.h>#include<tchar.h>int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, PTSTR pszCmdLine, int nCmdShow){    //(1)测试点1:GetModuleHandle函数的使用,参数是模块文件名    //windows程序中,一般都会有Kernel32.dll这个模块,那么现在我们就获得这个模块的句柄;    HMODULE hModule1 = GetModuleHandle(L"Kernel32.dll");//Kernel32.dll动态链接库文件一般在程序中都会被嵌入到进程的地址空间去。    HMODULE hModule2 = GetModuleHandle(NULL);    HMODULE hModule3 = GetModuleHandle(L"Win32Project28.exe");    //hInstance、hModule2和hModule3的值都是相等,因为GetModuleHandle(NULL)返回的是主调进程的可执行文件的实例句柄值。    Return 0;}

(2) What is the file name of the process module if you want to get it? You can call the Getmodulefilehandle function.
Function Signature:

DWORD GetModuleFileName(    HMODULE     hInstance,//进程句柄    PTSTR       pszPath,//文件名    DWORD       cchPath);//pszPath指向的内存的大小

In the function signature we can see, what type of data is hmodule? In 16-bit Windows, HINSTANCE and hmodule represent different types of data. And now the VS compiler has such a statement: typedef hinstance HMODULE; the fact that hinstance and hmodule are the same thing now.
The following is a test of the use of the GetModuleFileName function:

#include<windows.h>#include<tchar.h>int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, PTSTR pszCmdLine, int nCmdShow){    //(2)测试点2:GetModuleFileName函数的使用,    //参数1是模块(加载到进程地址空间的每一个可执行文件或者DLL文件都属于一个模块)的实例句柄    //参数2是模块文件的名称(绝对地址)    //参数3是文件名的大小,可以设置为MAX_PATH->最大的路径长度    TCHAR path1[MAX_PATH];    TCHAR path2[MAX_PATH];    GetModuleFileName(hModule1, path1, MAX_PATH);    GetModuleFileName(hModule2, path2, MAX_PATH);    Return 0;}

(3) If your own code is in a DLL file, then what do you want to know about the module address after the DLL file is loaded into the process control? Note that there are two scenarios for using the following two methods, since both the __imagebase and Getmodulehandleex functions return the base address of the current module (the module that calls the function, such as the _tWinMain function below), so If the following two methods are used in the code of the executable file, then the base address of the executable is returned. If the following two methods or functions are used in the code of the DLL file, then the base address of the DLL module is returned. As an example:

#include<windows.h>#include<tchar.h>extern "C" HANDLE __ImageBase;int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, PTSTR pszCmdLine, int nCmdShow){    __ImageBase;    HMODULE hModule4;    GetModuleHandleEx(        GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,        (PCTSTR)_tWinMain, &hModule4);//获取函数_tWinMain函数在哪个模块中运行。    return 0;}

The results of the test are as follows, and the values of __imagebase and hModule4 are equal.

Core summary of Windows core programming (chapter fourth process (i)) (2018.6.8)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.