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; sub-process process process is an instance of the current operating system that is loaded into memory and is running. 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.
Prototype declaration CreateProcess () 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 sign LPVOID lpEnvironment, // pointer to point to the new environment block LPCTSTR lpCurrentDirectory, // pointer to lPSTARTUPINFO lpStartupInfo the current directory name, // pointer to start LPPROCESS_INFORMATION lpProcessInformation information structure / / Pointer to the process information structure; when the program is designed, a particular 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 for the quit waitforsingleObject (pi.hprocess, infinite); // Get an exit code getExitcodeProcess (pi.hprocess, & dwwexitcode); // Turns the sub-process handle CloseHandle (PI.hprocess);} This section first The "Notepad" program that comes with CREATEPROCESS () is created for the child process, the sub-process launched the post-child process waits for the end through the waitforsingleObject () function, and the child process does not exit before the parent process is always blocked. The role of the child 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) {// Turpary Close Handle CloseHandle (PI.hthread); // Turning the sub-process handle CloseHandle (PI.hprocess);} You can create a process through dwcreationFlags parameters Set the priority of the sub-process.
The previous sample code is used when creating a sub-process. It is the default priority. 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 through the setPriorityClass () function, which requires the handle of the process to operate as an entry parameter, and the function is: Bool setPriorityClass (Handle HPRocess, DWPRIORIRIRIRIRIRIRIRIRIRIRITYCLASS); For the previous example code, you can dynamically change its priority settings by the parent process after startup: setPriorityClass (PI.hprocess, high_priority_class); or The process changes the priority settings after it starts, it is necessary to note that the process handle should be set to the child process itself handle, can be obtained by getCurrentProcess () function: handle hprocess = getCurrentProcess (); setPriorityClass (hign, high_priority_class) The process of mutual exclusion is normal, and 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, the two methods of representative mutex and global sharing variables respectively: // Create a mutex handle m_hmutex = createmutex (null, false, "sample07)); // Check error code IF (GetLasterror () == Error_Already_exists) {// If there is already the mutex exists, the handle is released and the mutex of the mutex closehandle (m_hmutex); m_hmutex = null; // The program exits return false;} The above code demonstrates the name The use of mutual exclusion in process mutual exclusion. The core of the code is created for CreateMutex () to a famous mutex. The CreateMutex () function can be used to create a famous or unnamed mutex object whose function prototype is: Handle CreateMuteX (LPSecurity_Attributes LPMUTETRIBUTES, / / Pointer Bool Binitialowner, // Initialize the owner of the mutually exclusive object LPCTSTR LPNAME / / Pointer to the name of the mutex); 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. Below will now use 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; This code is to add 1 for global shared variables 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 (). . The end process 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. The EXITPROCESS () function original is: void exitProcess (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.