240 likes | 376 Views
Win32 Programming. Lesson 8: Processes. Where are we?. We’re starting to have some foundational understanding of Windows But really, we don’t know how to get any work done (doesn’t that sound like your Sophomore year?). Executing Code.
E N D
Win32 Programming Lesson 8: Processes
Where are we? • We’re starting to have some foundational understanding of Windows • But really, we don’t know how to get any work done (doesn’t that sound like your Sophomore year?)
Executing Code • The Operating System organizes executing code into a logical hierarchy • Processes • Threads • Fibers
Definition • A Process is defined as • An instance of a running program, which consists of two components: • A kernel object used by the operating system to manage the process • An address space which contains all the DLLs, executable code and data used by the process • Processes are inert: to accomplish anything, a process must have at least one thread that runs in its context
Threads • Each thread executes “simultaneously” (in some sense of the word… why, why not?) • Each thread has its own stack frame, and set of CPU registers
Scheduling • The OS schedules some time for each thread • Each thread gets a time slice or quantum from the CPU which provides the illusion of concurrency • We can think of it as a “round robin” scheduler… but it is significantly much more complicated • When a process is created, it is generally created with one thread, called the primary thread – this thread can create other threads
Windows Applications • Two flavors • GUI (all that Windowsy stuff) • CUI (command line – the One True Way™) • Of course, life isn’t so simple – it’s not a binary decision • Every program needs an entry point – WinMain, wWinMain etc. • The Operating System doesn’t call this – it calls a special startup function
Startup Code • The Runtime Libraries do a number of things • Retrieve a pointer to the command line parameters of the process • Retrieve a pointer to the new environment variables of the process • Initialize the RTL’s global variables • Initialize the heap for the RTL • Call constructors for global and static objects
A Process’ Instance Handle • Every DLL or executable gets its own Instance Handle, which is unique • Used when we load resources (like icons) • Can get the handle of a DLL with something like: • HMODULE GetModuleHandle(PCTSTR pszModule);
The Command Line • Can use the global variables __argv • Can call down to PTSTR GetCommandLine() • Can go from here to an argv-like structure using: • PWSTR CommandLineToArgvW( PWSTR pszCmdLine, int* pNumArgs);
Free alloced memory • int nNumArgs; PWSTR *ppArgv = CommandLineToArgvW( GetCommandLineW(), &nNumArgs); // Use the arguments… if (*ppArgv[1] == L'x') { } // Free the memory block HeapFree(GetProcessHeap(), 0, ppArgv);
Environment Variables • Associated on a per-process basis • Stored in the environment block • Stored in the form: • VarName1=Value1\0VarName2=Value2\0…VarNameX=ValueX\0\0
Associated Functions • GetEnvironmentVariable( PCTSTR pszName, PTSTR pszValue, DWORD dwSize); • Often in the form “%USERPROFILE%\My Documents” • Windows supplies a helper function for this case
ExpandEnvironmentString • ExpandEnvironmentStrings( PCTSTR pszSrc, PTSTR pszDst, DWORD nSize); • Where nSize is the maximum space available for expansion
ErrorModes • A process can choose to trap certain errors itself instead of having the Operating System trap those errors • UINT SetErrorMode(UINT fuErrorMode)
CurrentDirectory and Directory • Example: CreateFile • DWORD GetCurrentDirectory ( DWORD cchCurDir, PTSTR pszCurDir); • BOOL SetCurrentDirectory(PCTSTR pszCurDir); • Current Directories are also stored in the environment variables
Finally… • GetVersion and GetVersionEx • Read the history, it’s somewhat amusing
Creating a Process • Simple: use CreateProcess: • BOOL CreateProcess( PCTSTR pszApplicationName, PTSTR pszCommandLine, PSECURITY_ATTRIBUTES psaProcess, PSECURITY_ATTRIBUTES psaThread, BOOL bInheritHandles, DWORD fdwCreate, PVOID pvEnvironment, PCTSTR pszCurDir, PSTARTUPINFO psaStartInfo, PPROCESS_INFORMATION ppiProcInfo); • I could write out the usage, but let’s just look it up…
Terminating a Process • Four ways • The primary thread’s entry-point function returns (YES) • One thread in the process calls ExitProcess (NO) • A thread in another process calls TerminateProcess (NO) • All the threads just happen to die on their own (Never happens)
Entry point returns • When the primary thread dies • Any C++ objects are destroyed using destructors • Memory from the stack is correctly freed • The process’ exit code is set • The process’ kernel object is decremented
ExitProcess • Fine from an OS perspective • Horrible from the RTL perspective as Destructors aren’t called – you can prove this to yourself if you want to
ChildProcesses PROCESS_INFORMATION pi; DWORD dwExitCode; // Spawn the child process. BOOL fSuccess = CreateProcess(..., &pi); if (fSuccess) { // Close the thread handle as // soon as it is no longer needed! CloseHandle(pi.hThread); // Suspend our execution until // the child has terminated. WaitForSingleObject(pi.hProcess, INFINITE); // The child process terminated; //get its exit code. GetExitCodeProcess(pi.hProcess, &dwExitCode); // Close the process handle as soon as it // is no longer needed. CloseHandle(pi.hProcess); }
Detaching a Process • In the previous example, the processes are linked – the child process won’t be destroyed until the Parent reads the exit code • However, you can detach a process by closing the associated handles in the parent process
Enumerating Processes • Assignment time! • Easily create a simple application which enumerates all the processes on a machine. You may use a command-line application if you wish, or a GUI. Print out as much information about each process as you can. • This looks really nice in .NET… but that’s a little more tricky. • Your call – CLI is okay, but a nice GUI gets you extra marks…