Abstract: This article mainly introduces multi-process management techniques in multi-tasking management, which makes a more detailed explanation of the mutual exclusion operation of the process, the creation and end of the sub-process.
Key words: VC 6.0; process; environment variable; child process
process
The process is the current operating system next one is loaded.
Memory, an instance of running applications. Each process is composed of kernel objects and address space, kernel objects allow the system to store statistics about the process and enable the system to manage processes, while address space includes all program modules. And the data, and a dynamically allocated space such as a thread stack, a heap allocation space. The process is just an existence, and it is not possible to complete any operation alone, and must have at least one thread running in its environment and is responsible for executing code within the process address space. At the same time, it starts a thread while the process starts, the thread is referred to as a main thread or performs a thread, and thus thread can continue to create a sub-thread. If the main thread exits, the process does not exist, the system will automatically undo the process and complete the release of its address space.
The images of each executable or dynamic link library file loaded to the process address space are allocated a globally unique instance handle (Hinstance) associated with it. This example handle is actually a basic memory address that records the process loading position. The instance handle of the process passes the first parameter Hinstance Hinstexe in the program portable function WinMain (), which is the address of the basic address space used by the process. For programs generated by the VC link program, the default basic address space address is 0x00400000, if it is not necessary, do not modify this value. In the program, the basic address space used by the specified module can be obtained via the getModuleHandle () function.
The creation of the sub-process creation process is implemented via the CreateProcess () function, and createProcess () starts a new program by creating a new process and the main thread running in its address space. Specifically, when executing the createprocess () function, first by the operating system is responsible for creating a process kernel object, initializing counting is 1, and creates a virtual address space for the new process. The code and data of the executable or any other necessary dynamic link library file are then loaded into the address space. When creating a main thread, it is also the first to create a thread kernel object by the system and initialize it to 1. Finally, start the main thread and execute the entry function of the process WinMain (), complete the creation of the process and execution thread.
The prototype statement of the creageprocess () function is as follows:
BOOL CreateProcess (LPCTSTR lpApplicationName, // executable module name LPTSTR lpCommandLine, // command line string LPSECURITY_ATTRIBUTES lpProcessAttributes, security attributes LPSECURITY_ATTRIBUTES lpThreadAttributes // process, security attributes BOOL bInheritHandles // thread, // handle inheritance flag DWORD dwCreationFlags, // Create a flag LPVOID LPENVIRONMENT, / / Pointer LPCTSTAR LPCTSTSTARTSTARTSTARTSTARTSTARTSTARTSTARTSTARTSTARTSTARTARTARTARTARTUPINFO LPSTARTUPINFO to the current directory name LPstartupinfo, // Pointer to the startup information structure LPPROCESS_INFORMATION LPPROCESSINFORMATION / / Pointer to the process information structure;
In the program design, a specific functional module can be implemented in different forms such as a function or thread. For the same process, these functions, threads are present under the same address space, and most of them are processed with some of them related to them. If there is something wrong with an algorithm, it will be possible to destroy some other important contents with the same address space, which will cause more serious consequences. In order to protect the contents of the address space, it can be considered in the address space that needs to be accessed by the data in the address space, and only allows it to access relevant data in the original process address space. Specifically, you can create a child process through the CreateProcess () function in the process, and the child process is only accessible to the relevant data in the parent process address space during all processing, allowing the current sub-process in the Parent Process Address Space. Perform all the data that is not related to the task. For this situation, the role of the child process is similar to the function and thread, which can be seen as a process of the parent process during operation. To this end, you need to master the start, execution, and exit of the child process by the parent process. I.e. following code illustrates this procedure: // temporary variables CString sCommandLine; char cWindowsDirectory [MAX_PATH]; char cCommandLine [MAX_PATH]; DWORD dwExitCode; PROCESS_INFORMATION pi; STARTUPINFO si = {sizeof (si)}; // get the Windows directory GetWindowsDirectory (CWindowsDirectory, Max_path); // Start the command line of the "Notepad" program Scommandline = cstring (cwindowsDirectory) "//notepad.exe";::strcpy (ccommandline, scommandline); // Start" Notepad " Sub-process Bool Ret = CreateProcess (NULL, CCOMMANDLINE, NULL, NULL, FALSE, 0, NULL, NULL, & SI, & PI); IF (RET) {// Turk Close Handle CloseHandle (pi.hthread); / / Wait to exit WaitForsingleObject (PI.hProcess, Infinite); // Get an exit code of the child process getExitcodeProcess (pi.hprocess, & dwwexitcode; // Close sub-process handle CloseHandle (Pi.hprocess);
This code first creates a "Notepad" program that comes with CREATEPROCESS () for the child process, the sub-process starts the post-child process through the waitforsingleObject () function, waiting for its execution, in the child process, the parent process is always in In blocking state, the role of the sub-process is similar to the function in the single thread. Once the child is exited, the WaitForsingleObject () function WaitForsingleObject () function WaitForsingleObject object will be notified, the parent process will continue, if necessary, you can get the quit code of the child process via getExitCodeProcess ().
In contrast, more situations are that the parent process will never perform any data exchange and communications after starting the child process, and the successful execution of the sub-process created by it is independent of the parent process. Many large software uses this kind of idea when designing, which completes some functions through stand-alone applications. When you need to perform an operation, you can start the corresponding sub-process by the main program, and the specific processing work Different from the sub-process. The creation process of such sub-processes is simpler, for example, for the above code only needs to remove the child process handle PI.hprocess: BOOL RET = CreateProcess (Null, CCommandline, Null, Null, False, 0, Null , NULL, & SI, & PI; IF (RET) {// Turning off the main thread of the sub-process CloseHandle (pi.hthread); // Close sub-process handle closehandle (pi.hprocess);}
You can set the priority of the sub-process when you create a process via the DWCREATIONFlags parameter. The previous sample code is used by the subscript when creating a sub-process, and if you want to set the priority to high, you can modify the following:
Bool Ret = CreateProcess (Null, CCommandline, Null, Null, False, High_Priority_Class, Null, Null, & Si, & Pi;
If there is no special setting priority when the process is created, you can dynamically set by the setPriorityClass () function, which requires the handle of the process as an inlet parameter, and the function is:
Bool SetPriorityClass (Handle Hprocess, DWORD DWPRIRIRITYCLASS);
For example, the previous example code is not set, you can dynamically change its priority settings after starting after the child process is started:
SetPriorityClass (pi.hprocess, high_priority_class);
Or change the priority setting after it is started after it starts, it is important to note that the process handle should be set to the child process itself handle, which can be obtained by getCurrentProcess () function:
Handle hprocess = getCurrentProcess (); setPriorityClass (hprocess, high_priority_class);
Process mutual exclusion
Under normal circumstances, the operation of a process will generally not affect other running processes. However, for some special requirements, such as exclusive ways such as single-use serial ports are required to run programs that do not allow other tries to use this port device during their process, and such programs are often not allowed to run. Multiple instances of the same program. This leads out the problem of process mutual exclusion.
The core idea of implementing process mutual exclusion is relatively simple: the process first checks if there is an instance of this process in the current system, if not, the process will successfully create and set the label that the identity instance already exists. Thereafter, it will be known when you create a process, and it is known to exist, thereby ensuring that the process can only exist in the system. Specifically, multiple methods such as memory mapping files, famous events, laminated mutexes, and global sharing variables can be implemented. Below, it is introduced in the two methods with representative mutex and global sharing variables, respectively:
// Create a mutex handle m_hmutex = createmutex (NULL, FALSE, "Sample07)); // Check the error code IF (getLastError () == error_AlReady_exists) {// If there is a mutex, there is a handle and reset mutual Delivery closehandle (m_hmutex); m_hmutex = null; // Program Exit Return False;} The above code demonstrates the use of famous mutex in process mutual exclusion. The core of the code is created for CreateMutex () to a famous mutex. CreateMutex () function can be used to create a famous or unnamed mutex object, whose function prototype is:
Handle CreateMutex (LPSecurity_Attributes LPMUTEXATTRIBUTES, / / Pointer Bool Binitialowner, // Initialize the owner of the mutective object to point to the pointer of the mutually exclusive object name;
If the function is successfully executed, a handle of a mutex object will be returned. If there is a mutex of the same name before CreateMutex (), the function will return this handle that already presents the mutex, and can get the error code error_already_exist by getLastError (). It can be seen that CreateMutex () mutual exclusion can be implemented by detection of error code error_already_exist.
The method of using global shared variables is mainly implemented by compilers in the MFC framework program. Create a new section via the #pragma data_seg precompiled instruction, in which you can define a variable with the Volatile keyword and you must initialize it. The Volatile Keyword specifies that the variable can be accessed for external processes. Finally, in order to make the variables functions in the process mutex, it is also set to shared variables while allowing reading, write access. This can notify the compiler through the #pragma Comment precompilation instruction. The following is given the process mutual exclusive code list using global variables:
#pragma data_seg ("Shared") int volatile g_lappinstance = 0; #pragma data_seg () # Pragma Comment (Linker, "/ Section: Shared, RWS") ... IF ( g_lappinstance> 1) Return False;
The role of this code is to add 1 to the global shared variable g_nappinstancd when the process starts. If it is found to be greater than 1, then return false to the end of the notification process. It is important to specifically, in order to enable the above two segments to truly act as a function of mutual exclusive, it must be placed at the entry code of the application, that is, the beginning of the application class's initialization instance function initInstance (). .
end process
The process only provides an address space and kernel object, which is running through the main thread in its address space. When the entry point function of the primary thread is returned, the process ends. The termination method of this process is the normal exit of the process, and all thread resources in the process can be cleared. In addition to the normal introduction of this process, sometimes you need to enforce the operation of this process or other processes in the program. The EXITPROCESS () function can be used in a thread in the process and will immediately terminate the operation of the process. EXITPROCESS () Function is:
Void EXIXITPROCESS (UINT UEXITCODE);
Its parameter UEXITCODE sets an exit code for the process. This function is mandatory, and the process has been completed after the execution is completed, and therefore any code in it will not be executed. Although the EXITPROCESS () function can notify the dynamic link library associated with its associated process while the end process is notified, it will have a security hazard in use because of its mandatory of this execution. For example, if you apply for a memory before the program calls the exitprocess () function, it will be released by the DELETE operator due to the mandatory of the exitProcess () function, resulting in memory leakage. In view of the mandatory and unsafeness of the exitProcess () function, you must pay attention when used. EXITPROCESS () can only enforce the exit of this process. If you want to overcome other processes in a process, you must use TerminateProcess () to implement. Unlike EXITPROCESS (), the TerminateProcess () function is executed, and the term being terminated is not for any notification about the program exit. That is, the termination process is unable to perform the end of the end before running. So, usually only if any other methods cannot force the process to exit, consider using TerminateProcess () to enforce the process. The function prototype of TerminateProcess () is given below:
Bool TerminateProcess (Handle Hprocess, Uint Uexitcode);
Parameters HProcess and UEXITCODE are process handles and exit code, respectively. If the end is ended, you can get the handle via getCurrentProcess (). TERMINATEPROCESS () is asynchronously executed, and cannot determine if the stop process has really exit after calling the returns, if the process of calling the TerminateProcess () is concerned about this detail, you can wait for the truly end of the process through WaitForsingleObject ().
summary
Multi-process is an important part of multi-tasking management. The above part of the above part of the basic concept and the main technique, such as sub-process, and the mutual exclusion operation between processes, etc.. The readers of this article should have a preliminary understanding of multi-process management.