Anatomy of processes and threads under windows

Source: Internet
Author: User

Parsing of processes and threads

process : an instance of a running program, consisting of two parts :

1. A Kernel object , which the operating system uses to manage processes. The kernel object is also where the system saves process statistics.  
2. An address space that contains the code and data for all executable files or DLL modules. In addition, it contains dynamic memory allocations, such as thread stacks and heap allocations.
The process has to do anything to have a thread run in its context. 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. For this reason, each thread has its own set of CPU registers and its own stack. 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. Then, this thread creates more threads and the latter creates more threads ... If there is no thread to execute the code contained in the process address space, the process loses the reason for its existence. At this point, the system automatically destroys the process and its address space.


Threads are also made up of two parts:
a Kernel object that is a thread that the operating system uses to manage threads. The system also uses kernel objects to store thread statistics.
a thread stacks with a default size of 1M to maintain all the function parameters and local variables required for thread execution

The kernel object also includes: 1. Counter

2. Suspend counter (initial value is 0, each suspend a process, the counter plus one, each restore a process, the counter minus one, and its value can only be a non-negative integer)

3. Signal

The process never executes anything, it's just a container for a thread . Threads must be created in the context of a process and will "end their lifetime" within the process. This means that the thread executes the code and processes the data within the address space of its process. So, if more than two threads are running in a process context, these threads will share the same address space. These threads can execute the same code and work with the same data. In addition, these threads share kernel object handles because the handle table is for each process, not for each thread.

For all threads to run, the operating system will take turns to schedule some CPU time for each thread. It takes a loop (polling or rotation) to allocate a time slice (called a "quantum") for each thread, creating the illusion that all threads are running concurrently. 

Each thread has a context, which holds the kernel objects of threads. This context reflects the state of the CPU register at the time the thread was last executed. All currently existing thread kernel objects are viewed at approximately 20ms,windows intervals. Of these objects, only some are considered to be scheduled. Windows selects one of the scheduled thread kernel objects and loads the values from the last saved threads context into the CPU registers. This operation is referred to as a context switch. Threads execute code and manipulate the data in the address space of the process. It's over. 20ms,windows the CPU register back into the thread's context, and the thread no longer runs. The system checks the remaining scheduled thread kernel objects again, selects another thread's kernel object, loads the thread's context into the CPU register, and then continues. Loading the thread context, letting the thread run, saving the context, and repeating the operation begins when the system starts, and then the operation repeats until the system shuts down.

The creation process is used to occupy space, the real work is the thread
Creation of Threads:

Use MFC to write a small example to introduce the creation of threads: worker threads??

First, let's get the progress bar running.

1  while (1) 2     {3        m_process. StepIt (); 4         Sleep (+); // in order to make the progress bar more obvious, can sleep for a while, the role is to let the time slice 5         // because the CPU is the rotation time slice, represents the CPU to this thread when it discards this time slice, lets the CPU first assigns the task to others 6         // Note that the unit of sleep in Windows is in milliseconds, while Linux is seconds 7     }

We will find that the window is not movable when the progress bar is running, because there is only one thread working in the process, it can only be done in a certain period of time, in order to allow the progress bar to move the window at the same time, this requires us to create another thread


CreateThread (
lpsecurity_attributes Lpsa,


DWORD Cbstack,


lpthread_start_routine lpstartaddr,


lpvoid Lpvthreadparam,


DWORD Fdwcreate,


Lpdword);


where parameter lpstartaddr is the address that specifies the thread function that you want the new thread to execute.


the Lpvthreadparam parameter is a parameter to the thread function.


the thread function can perform any task that we want him to perform, and the function prototype resembles the following:


DWORD WINAPI threadfunc (lpvoid pvparam) {


DWORD dwresult;
... ..
return (dwresult);


}






When you call CreateThread, the system creates a thread kernel object. This thread kernel object is not the thread itself, but a smaller data structure that the operating system uses to manage threads.


the system allocates memory for the process address space to the thread stack for use. The new thread runs in the same process context as the thread responsible for creating it. Therefore, the new thread can access all the handles of the process kernel object, all the memory in the process, and the stack of all the other threads in the same process.  This way, multiple processes in the same process can easily communicate with each other.




the thread can terminate the operation in the following 4 ways.


1. The thread function returns (this is highly recommended).


2. The thread "kills" itself by calling the ExitThread function (to avoid using this method).


3. Call the TerminateThread function on the same process or thread in another process (to avoid using this method).


4. The process that contains the thread terminates running (this method avoids use).


 


The Ps:terminatethread function is asynchronous. That is, it tells the system that you want to terminate the thread, but when the function returns, there is no guarantee that the thread is terminated. If you need to determine that a thread has terminated, you also need to call WaitForSingleObject or a similar function and pass the thread handle to it.






initialization of the thread


Windows core Programming Learning Note (11) – Creation of threads-fly-day? Xing Khon




1. A call to the CreateThread function causes the system to create a thread kernel object. The object's initial usage count is 2.


(the thread kernel object is not destroyed unless the thread terminates and the handle returned from CreateThread is closed.) );


 


2. The pause count is set to 1;


(because the initialization of a thread takes time, we certainly do not want it to be executed before it is ready.) )


 


3. The exit code is set to Still_active (0x103);


(when the thread terminates, the thread exit code changes from Still_active (0x103) to the code passed to ExitThread or terminatethread);


 


4. The object is set to nonsignaled (not triggered) state.


 


5. The system allocates memory for use by the thread stack. The system then writes two values to the topmost of the new thread stack. The first value written to the thread stack is passed to the


The value of the Pvparam parameter of the CreateThread function. Immediately below it is the PFNSTARTADDR value passed to the CreateThread function.


stack: The size of the stack in Windows is fixed, the bottom of the stack at high address, the data into the stack from the high address start to put.


 


6. Each thread has its own set of CPU registers, called the context of the thread. The context reflects when the thread was last executed, the thread's


the status of the CPU registers. The CPU registers of the threads are all stored in a context structure (defined in the WinNT.h header file). Context Structure


itself is saved in the thread kernel object.


 


7. The instruction pointer and the stack pointer register are the most important two registers in the thread context. When a thread's kernel object is initialized, the context structure's stack pointer register is set to PFNSTARTADDR (the address of the thread execution function) to address in the threads stack. The instruction pointer register is set to the address of the Rtluserthreadstart function (the thread actually executes from here), and this function is exported by the NTDLL.dll module.


 


8. After the thread is fully initialized, the system checks to see if the create_suspended flag is passed to the CreateThread function. If this tag is not passed, the system increments the thread's pause count to 0, and then the thread can dispatch it to a processor to execute. The system then loads the value saved in the last thread context in the actual CPU register. Threads can now execute code and manipulate data in the address space of their processes.


 


conversion of pseudo- handles


HANDLE getcurrentprocess ();


HANDLE GetCurrentThread ();


 


Both of these functions return a pseudo-handle (Pseudohandle) to the process or thread kernel object of the keynote thread. They do not create a new handle in the handle table of the keynote process. Also, calling these two functions does not affect the usage count of the process or thread kernel objects. If you call CloseHandle and pass in a pseudo-handle as a parameter, CloseHandle simply ignores the call and returns FALSE. In this case, GetLastError will return Error_invalid_handle.


convert a pseudo-handle to a true handle
    


Sometimes you might need a real thread handle instead of a pseudo handle. The so-called "real handle" refers to a handle that identifies a thread clearly and unambiguously. To carefully analyze the following code:


 


DWORD WINAPI parentthread (PVOID pvparam) {


HANDLE hthreadparent = GetCurrentThread ();


CreateThread (null, 0, Childthread, (PVOID) hthreadparent, 0, null);


//Function continues ...





DWORD WINAPI childthread (PVOID pvparam) {


HANDLE hthreadparent = (HANDLE) pvparam;


FILETIME ftcreationtime, Ftexittime, Ftkerneltime, Ftusertime;


getthreadtimes (hthreadparent,


&ftcreationtime, &ftexittime, &ftkerneltime, &ftusertime);


//Function continues ...





 


can you see the problem with this code snippet? The intent is for the parent thread to pass a Cheng thread that can identify a handle to the parent. However, the parent thread is passing a pseudo-handle,


instead of a real handle. When a child thread starts executing, it passes the pseudo-handle to the Getthreadtimes function, which causes the child thread to get its own CPU


The timing data, not the parent thread. This happens because the pseudo handle of the thread is a handle to the current thread;


point to the thread that issued the function call.


 


to fix this code, you must convert the pseudo-handle to a true handle. The DuplicateHandle function can perform this transformation:


BOOL DuplicateHandle (


HANDLE hsourceprocess,


HANDLE Hsource,


HANDLE htargetprocess,


Phandle Phtarget,


DWORD dwDesiredAccess,


BOOL bInheritHandle,


DWORD dwoptions);


 


Normally, using this function, you can create a new handle based on a handle to a kernel object associated with process A, and make it relevant to process B. However, we can take a special way to use it to correct the previous code snippet error. The following code is corrected:


 


DWORD WINAPI parentthread (PVOID pvparam) {


HANDLE hthreadparent;


DuplicateHandle (


getcurrentprocess (),//Handle of process that thread pseudohandle are relative to


GetCurrentThread (),//parent pseudo handle


getcurrentprocess (),//Handle of process, the new, real, thread Handle is relative to


&hthreadparent,//would receive the new, real, handle identifying the parent thread


0,//ignored due to duplicate_same_access


FALSE,//New thread handle is not inheritable


duplicate_same_access); New thread handle has same access as Pseudohandle


 


CreateThread (null, 0, Childthread, (PVOID) hthreadparent, 0, null);


//Function continues ...





 


DWORD WINAPI childthread (PVOID pvparam) {


HANDLE hthreadparent = (HANDLE) pvparam;


FILETIME ftcreationtime, Ftexittime, Ftkerneltime, Ftusertime;


getthreadtimes (hthreadparent, &ftcreationtime, &ftexittime, &ftkerneltime, &ftUserTime);


CloseHandle (hthreadparent);


//Function continues ...





 


now, when the parent thread executes, it transforms the ambiguous pseudo-handle that identifies the parent thread into a new, true handle, which explicitly and unambiguously identifies the parent thread. It then passes this real handle to CreateThread. When a child thread starts executing, its Pvparam parameter contains the true thread handle. When any function is called, the parent thread, not the child thread, is the only thing that passes through the handle. Because DuplicateHandle increments the usage count for the specified kernel object, it is necessary to pass the target handle to CloseHandle after the copied object handle is exhausted to decrement the object's usage count. This is reflected in the preceding code. After calling Getthreadtimes, the child thread immediately calls CloseHandle to decrement the usage count of the parent thread object. In this code, I assume that the child thread does not invoke any other function with this handle. If you also pass in a handle to the parent thread when other functions are called, you can call CloseHandle only if the child thread does not need the handle at all.


 


It is also important to emphasize that the DuplicateHandle function can also be used to convert a process's pseudo-handle to a true process handle, as follows:


HANDLE hprocess;


DuplicateHandle (


getcurrentprocess (),//Handle of process, the process pseudohandle is relative to


getcurrentprocess (),//Process ' Pseudohandle


getcurrentprocess (),


&hprocess,


0,


FALSE,


duplicate_same_access


)

http://blog.csdn.net/hubinbin595959/article/details/47083019

Anatomy of processes and threads under windows

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.