1, Experimental purpose
(1) Learn to use VC to write basic Win32 console application (console application). (2) By creating processes, observing the programming and debugging operations of running processes and terminating processes, we can further get familiar with the process concept of the operating system and understand the "life" of Windows processes. (3) By reading and analyzing the experimental program, learn the basic programming methods of creating process, observing process, terminating process and parent-child process synchronization.
2, Experiment contents and steps
(1) Write basic Win32 console application
Step 1: log in to the Windows system and start VC++ 6.0.
Step 2: click the NEW submenu in the FILE menu, select Win32 console application in the projects tab, and then enter the Project name in Project name and the project directory in Location. Create a NEW control
Workbench application engineering.
Step 3: click the NEW submenu in the file menu, select C++ Source File in the Files tab, and then enter the file name of the C/C + + source program in the file field.
Step 4: copy the program list shown in listing 1-1 to the newly created C/C + + source program. Compile into executable file.
Step 5: click "program" - "accessories" - "command prompt" in the "start" menu to enter the Windows "command prompt" window, and then enter the debug subdirectory in the project directory to execute the compiled executable program and list the running results (if the operation is unsuccessful, what are the possible reasons?)
A: the path is wrong or there is no compiled file, etc.
(2) Create process
This experiment shows the basic framework for creating sub processes. The program just starts itself again, displaying its system process ID and its location in the process list.
Step 1: create a "Win32 console application" project, then copy the program in listing 1-2 and compile it into an executable file.
Step 2: run the executable generated in step 1 in the command prompt window and list the running results. Press ctrl+alt+del to call the windows Task Manager and record the process related behavior attributes.
Step 3: add parameters in the "command prompt" window, rerun the generated executable file, and list the running results. Press ctrl+alt+del to call the windows Task Manager and record the process related behavior attributes.
Step 4: modify the program in listing 1-2, modify the nClone definition and initialization method according to the modification method in the program comment, and compile it into an executable file (please save the completed work before execution). Then run as in step 2 to see what the results will be different. List the travel results. What conclusions can you draw from it? Explain the role of nClone. Does the definition and initialization method (location) of variables affect the execution results of the program? Why?
A: control the program execution process. When nClone > 5, the loop will jump out and the sub process will be created to end; Yes, in the second change, because nClone is initialized to 0 every time, it will fall into an endless loop and continue to create child processes.
(3) Simple communication between parent and child processes and process termination
Step 1: create a "Win32 console application" project, then copy the program in listing 1-3 and compile it into an executable file.
Step 2: click the "Execute Program" button on the VC toolbar, or press Ctrl + F5, or run the executable generated in step 1 in the "command prompt" window to list the running results.
Step 3: according to the prompts in the notes in the source program, modify the source program 1-3, compile and execute (please save the completed work before execution), and list the operation results. Add trace statements to the program, or debug and run the program. At the same time, refer to the help file CreateProcess() in MSDN to understand how parent-child processes pass parameters. Give a general description of the program execution process.
Step 4: modify the source program 1-3 according to the prompts in the notes in the source program, compile and execute, and list the running results.
Step 5: refer to the help files CreateMutex(), OpenMutex(), ReleaseMutex() and WaitForSingleObject() in MSDN to understand how parent-child processes use mutexes for synchronization. Give a general description of the synchronization process of parent-child processes
A: CreateMutex() creates a mutex hMutexSuicide signal, OpenMutex() opens the mutex, ReleaseMutex() releases the mutex, and WaitForSingleObject() detects the state of the Hhandle signal. Only one state is allowed to be created or used, that is, the semaphore is unique, so as to realize process synchronization.
3, Program list
Listing 1-1 A simple Windows Console Application // hello project # include <iostream> void main() { std::cout << "Hello, Win32 Consol Application" << std :: endl ; }
Listing 1-2 Create child process #include <windows.h> #include <iostream> #include <stdio.h> // Create a clone process of the passed process and assign its ID value void StartClone(int nCloneID) { // Extracts the file name used for the current executable TCHAR szFilename[MAX_PATH] ; GetModuleFileName(NULL, szFilename, MAX_PATH) ; // Format the command line for the child process and notify it of the EXE file name and clone ID TCHAR szCmdLine[MAX_PATH]; sprintf(szCmdLine,"\"%s\" %d",szFilename,nCloneID); // STARTUPINFO structure for child processes STARTUPINFO si; ZeroMemory(&si , sizeof(si) ) ; si.cb = sizeof(si) ; // Must be the size of this structure // The process information returned for the child process PROCESS_INFORMATION pi; // Use the same executable and command line to create a process and assign the properties of its child processes BOOL bCreateOK=::CreateProcess( szFilename, // The name of the application that generated this EXE szCmdLine, // A flag that tells it to behave like a child process NULL, // Default process security NULL, // Default thread safety FALSE, // Do not inherit handle CREATE_NEW_CONSOLE, // Using the new console NULL, // New environment NULL, // current directory &si, // Startup information &pi) ; // Returned process information // Release reference to child process if (bCreateOK) { CloseHandle(pi.hProcess) ; CloseHandle(pi.hThread) ; } } int main(int argc, char* argv[] ) { // Determine how many processes are derived and where the derived process is in the process list int nClone=0; //Modify statement: int nClone; //First modification: nClone=0; if (argc > 1) { // Extract the clone ID from the second parameter :: sscanf(argv[1] , "%d" , &nClone) ; } //Second modification: nClone=0; // Show process location std :: cout << "Process ID:" << :: GetCurrentProcessId() << ", Clone ID:" << nClone << std :: endl; // Check if there is a need to create child processes const int c_nCloneMax=5; if (nClone < c_nCloneMax) { // Send the command line and clone number of the new process StartClone(++nClone) ; } // Wait for response keyboard input to end the process getchar(); return 0; }
Listing 1-3 Simple communication of parent-child process and example program of terminating process // Proctermproject # include <windows.h> # include <iostream> # include <stdio.h> static LPCTSTR g_szMutexName = "w2kdg.ProcTerm.mutex.Suicide" ; // An easy way to create a clone process of the current process void StartClone() { // Extract the file name of the current executable TCHAR szFilename[MAX_PATH] ; GetModuleFileName(NULL, szFilename, MAX_PATH) ; // Format the command line for the child process, and the string "child" will be passed as a formal parameter to the main function of the child process TCHAR szCmdLine[MAX_PATH] ; //Experiment 1-3 step 3: change the string child in the next sentence to another string, recompile and execute. Please save the existing string before execution Completed work sprintf(szCmdLine, "\"%s\"child" , szFilename) ; // Start information structure of subprocess STARTUPINFO si; ZeroMemory(&si,sizeof(si)) ; si.cb = sizeof(si) ; // Should be the size of this structure // The process information returned for the child process PROCESS_INFORMATION pi; // Create a process with the same executable name and command line, and indicate that it is a child process BOOL bCreateOK=CreateProcess( szFilename, // Name of the generated application (this EXE file) szCmdLine, // Tell us this is the sign of a child process NULL, // Default security for processes NULL, // Default security for threads FALSE, // Do not inherit handle CREATE_NEW_CONSOLE, //Create new window NULL, // New environment NULL, // current directory &si, // Start information structure &pi ) ; // Returned process information // Release references to child processes if (bCreateOK) { CloseHandle(pi.hProcess) ; CloseHandle(pi.hThread) ; } } void Parent() { // Create a suicide mutex body HANDLE hMutexSuicide=CreateMutex( NULL, // Default security TRUE, // Originally owned g_szMutexName) ; // Mutex name if (hMutexSuicide != NULL) { // Create child process std :: cout << "Creating the child process." << std :: endl; StartClone() ; // The instruction subprocess "kills" itself std :: cout << "Telling the child process to quit. "<< std :: endl; //Waiting for keyboard response from parent process getchar() ; //Release the ownership of the mutex, and this signal will be sent to the WaitForSingleObject procedure of the child process ReleaseMutex(hMutexSuicide) ; // Eliminate handle CloseHandle(hMutexSuicide) ; } } void Child() { // Open the suicide mutex HANDLE hMutexSuicide = OpenMutex( SYNCHRONIZE, // Open for synchronization FALSE, // No need to pass down g_szMutexName) ; // name if (hMutexSuicide != NULL) { // Report that we are waiting for instructions std :: cout <<"Child waiting for suicide instructions. " << std :: endl; //The child process enters the blocking state and waits for the signal sent by the parent process through the mutex WaitForSingleObject(hMutexSuicide, INFINITE) ; //Step 4 of experiment 1-3: change the previous sentence to WaitForSingleObject(hMutexSuicide, 0), recompile and execute // Ready to terminate, clear handle std :: cout << "Child quiting." << std :: endl; CloseHandle(hMutexSuicide) ; } } int main(int argc, char* argv[] ) { // Determines whether its behavior is parent or child if (argc>1 && :: strcmp(argv[1] , "child" )== 0) { Child() ; } else { Parent() ; } return 0; }
4, Program flow chart
(1) Write basic Win32 console application
(2) Create process
(3) Simple communication between parent and child processes and process termination
5, Experimental results and analysis
1. Write a basic Win32 console application:
2. Create the process and test results:
After changing nClone=1 to 1, the running result:
Result analysis: starting from the main() function, first judge the value of argc (the initial value of argc is 1 by default). Because argc is not greater than 1, argv[1] cannot be assigned to nClone; Then nClone < C_ Nclonemax, call the StartClone (++nClone) function to create a child process; After the child process is created, the value of argc changes to 2, and then the self incremented nClone is assigned argv[1], and then the main() function will continue to be executed until (nClone > c_nclonemax), jump out and end the creation of a new process.
3. Simple communication and termination of parent-child process. Experimental results:
After modifying WaitForSingleObject(): only one state is allowed to be created or used, that is, the semaphore is unique to realize process synchronization.
Result analysis: starting from the main() function, we first determine the value of argc (the initial value of argc is defaults to 1), decide whether to carry out parent process or sub process, because argc is not more than 1, so we call parent() function and call StartClone() in the process of executing parent() function. Then assign argv[1] to child by sprintf(szCmdLine, "%s" child ", szFilename), and then call child() function after satisfying the condition. Because the mutex signal is set, only one process is allowed. Therefore, the child process detection will end the process only when the parent process releases the mutex signal hMutexSuicide.
6, Summary and experience
Through this experiment, I have deepened my understanding of the process concept of the operating system and understood the "life" of Windows processes. All processes start with calling CreateProcess()API function and end with ExitProcess function. Learned the basic programming methods of creating process, terminating process and parent-child process synchronization