Windows2000 process / thread analysis (1)
---reading notes
First, kernel object
1.1 What is a kernel object?
Systems and applications use kernel objects to manage a wide variety of resources, such as processes, threads, and files. Each kernel object is just a memory block allocated by the kernel and can only have kernel access. The memory block is a data structure that is responsible for maintaining various information of the object. Some data members (such as: security descriptors, using counts, etc.) are the same in all object types, but most data members belong to a specific object type. For example: Process object has a process ID, a basic priority, and an exit code, and the file object has a byte displacement, a shared mode, and an open mode.
The data structure of the kernel object can only be accessed by kernel, so the application cannot find these data structures in memory and directly changing their content. Microsoft specifies this restriction condition to ensure that the structure of the kernel object is capable of maintaining the consistency. This limitation also enables Microsoft to add, delete, and modify data members without destroying any application.
Windows provides a set of functions to create and access kernel objects. (For example: createProcess, createFileMapping) When a function for creating a kernel object is called, the function returns a handle for identifying the object. The handle can be considered an opaque value, and any thread in the process can use this value. By passing the handle of each kernel object to the various functions of Windows, the system can know that you want to operate the kernel object.
In order to make the OS more robust, the handle of the kernel object is closely related to the process. Therefore, if the handle is passed to a thread in another process (communication between the processes between some forms), the call to use this handle will fail. Of course, this is not absolute, using the "Crossing Process Boundary Shared Core Object" technology, you can share a single kernel object.
Guess: The kernel object is not located in the 4GB virtual space of a single process, but is located in a block memory area under kernel control. In this case, multiple processes share single kernel objects can be implemented. What is the handle of the kernel object, there is no exact document to explain, but it can be sure that the same kernel object can correspond to multiple handles, and the same handle can only correspond to one kernel object, which can explain why it is named by the kernel object Methods, two unrelated processes can access the same kernel object, but the handle of these two processes is not the same, which is the difference between the sub-process inherits the method of the parent process handle table.
1.1.1 Use of kernel objects
The kernel object is owned by the kernel, which means that if your process calls a function of creating a kernel object, then your process is terminated. Then the kernel object is not necessarily revoked. Of course, in most cases, the kernel object will be revoked. But if another process is using the kernel object created by your process (such as: sub-process inherits the handle table of the parent process, or using the "Crossing Process Boundary Shared Core" technology), then the kernel knows that in another process is terminated. This object cannot be revoked before using this object, you must remember that there is a time of the kernel object to be longer than the process of creating the object.
Each kernel object contains one count, and the count is one of the commonly used data members of all kernel object types. When an object has just created, its usage count is set to 1. Then, when another process accesses an existing kernel object, use the count to increment 1. When the process is terminated, the kernel automatically determines the usage count of all kernel objects that the process is still open. If the usage count of kernel objects will be 0, the kernel will revoke the object. This ensures that the system will not continue to retain it when there is no process reference to the kernel object. 1.1.2 security
The kernel object can be protected by a security descriptor. Safety descriptors are used to describe who created this object, who can access and use this object, who is free to access the object. Safety descriptors are typically used when writing server applications.
The default security of kernel objects is: Any member and creator in the object management group have all access rights to the object.
In addition to kernel objects, applications can also use other types of objects, such as menus, windows, mouse light, brush and fonts, etc. These objects belong to the user object or GDI object, not a kernel object. If the function of creating an object does not use the psecurity_attributes parameter, the created is not a kernel object. E.g:
Hicon Createicon
Hinstance hinst,
Int nwidth,
Int nheight,
Byte Cplanes,
Byte Cbitspixel,
Const byte * pBandbits,
Const byte * pbxorbits;
1.2 Core kernel object handle table
When a process is initialized, the system is to assign him a handle table. This handle is only used for kernel objects, not for user objects or GDI objects. The handle of the handle is not the same in Windows 2000, Windows98, and Windows CEs. And there is no detailed information on the detailed structure and management method of the handle, so the following description does not guarantee that all details are correct.
1.2.1 Creating a kernel object
When the process is initialized for initialization, its handle is empty. Then, when the thread in the process invokes a function of creating a kernel object, the kernel assigns a memory block for the object and initializes it. At this time, the kernel object scans the handle of the process to find an empty position. Then, the memory address of the data structure of the corresponding kernel object is then set, and the mask bit, and the flag bit are accessed.
All functions for creating a kernel object returns a handle associated with a process that can be used by all threads in the process. These handle values are actually the index in the handle of the process, which is used to identify the location where the kernel object is stored. In actually in Windows2000, the return value of the function is the number of bytes written in the process handle when creating a kernel object. Instead of index itself. With regard to the meaning of the handle, there is no documentation, and its implementation will change at any time.
Some functions used to create kernel objects:
Handle CreateThread
Psecurity_attributes PSA,
DWOD DWSTACKSIZE,
LPTHREAD_START_ROUTINE PFNSTARTDR,
PVOID PVPARAM,
DWORD DWCREATIONFLAGS,
PDWORD PDWTHREADID;
Handle CreateSemaphore
Psecurity_attributes PSA,
Long Linitialcount, Long Lmaximumumcount,
PCTSTR PSZNAME);
Guess: First, you can affirm that each process kernel object will be generated every process under Windows 2000, and Windows itself maintains a system global process table. Each line in this process table corresponds to a process kernel object, ie one Actual process. When a process creates a child process, the kernel object handle corresponding to the child does not write into the handle of its parent process. It is directly written to the system global process table. Similarly, a thread kernel object is also generated for each thread, and information about the kernel object is also saved in the system global thread table. Windows is based on these two forms of process and threads in the management and scheduling system. The process kernel object mentioned here should be the process control block PCB mentioned in the Process Control Structure section in the "Operating System" book. The process image (Process Image) mentioned in this book should actually be saved in the disk or other media.
Windows provides the following methods to share data between different processes:
l Dynamic Data Exchange (DDE)
l ole, com
l pipeline and mailbox
l Memory map file
Second, the process
2.1 Overview
The process usually defines an instance of an object that is running, it has two parts:
l One is an operating system used to manage the kernel objects of the process. The kernel object is also a system where the system is used to store statistics about the process.
l The other is the address space, which contains all the code and data of all executable modules or DLLs. It also contains space for dynamic memory allocation. Such as thread stack and heaps allocate space.
The process is not lively. If the process completes an action, it must have a thread running in its environment, which is responsible for executing the code included in the address space included in the process. In fact, a single process may contain several threads, all of these threads are "simultaneously" execute code in the process address space. To do this, each thread has his own set of CPU registers (ie, thread context, defined in: Winnt.h header files) and its own stack. However, since Windows is for the process to assign system resources. So, the thread's stack is actually located in the virtual address space of its own process. Each process has at least one thread to perform code in the process address space. If there is no thread to execute the code in the address space of the process, then the process does not exist, the system will automatically undo the process and its address space.
To make all threads run, the operating system will arrange a certain CPU time slice for each thread. It provides a time slice (called: range) through a loop mode, causing a description, as if all threads are running simultaneously.
When you create a process, the system automatically creates its first thread and becomes the main thread. The thread then creates other threads or processes.
2.2 Windows Application Overview
Windows supports two types of applications:
l Based on graphical user interface (GUI) application
l Based on console user interface (CUI) application
The Windows application must have an entry point function that is called when the program is started. The entry point that can be used is as shown below:
2.3 Startup Process of Windows Applications The operating system does not actually call the entry point function you have written. It calls the C / C Run-Time Startup function. This function is responsible for initializing C / C Run-Time Library so that functions such as Malloc and FREE can be called. It also ensures that any global object and static objects have been able to create prior to code execution in code.
The role of all C / C Run-Time Startup functions is the same, and the difference is that it is to process the ANSI string or a Unicode string, and they call the entry point function after initializing C Run-Time Library. VC is equipped with the source code of C Run-Time Library. You can find the code of these 4 startup functions in the CRT0.C file.
The function of the start function can be summarized as follows:
l Retrieve the pointer to the full command line pointing to the new process
l Retrieve pointers that point to the environment variables of the new process
l Initialize C / C Run Time's Global Variables. If you contain stdlib.h header files, your code can access these variables. See the table below for details:
l In initialization of the HEAP (Pile) used by the C operation memory allocation function (Mallco and Calloc) and Low-Level Input / Output Routines
l call constructor for all global and static C class objects
When the above initialization operation is completed, the C / C Run-Time Startup function calls the application's entry point function.
If a Winmain function is written, it will be called as follows:
GetStartupInfo (& Startupinfo);
Int nmainRetval = WinMain (getModuleHandle (Null), NULL, PSZCommandlineansi,
(Startupinfo.dwflags & Startf_USESHOWWINDOW)
? Startupinfo.wshowwindow: sw_showdefault;
When the entry point function returns, the startup function calls the EXIT coldness of the C run period, passes the return value (NMAINRETVAL) to it.
The EXIT function is responsible for the following:
l Any function registered by the _ONEXIT function
l For all global and static C class object call destructor
l Call the EXITPROCESS function of the operating system and pass NMAINRETVAL to it. This allows the operating system to revoke this process and set its EXIT CODE (which saves the kernel object corresponding to the process).
Third, thread
Four, fiber
Microsoft adds a fiber to the Windows Add to be easier to enable application of existing UNIX to Windows. Applications under UNIX belong to a single-process application, but it can serve multiple client programs. Developers under UNIX use their own thread library to simulate pure threads. The thread package can create multiple stacks to save some CPU registers, and can be switched between them to provide services for client requests.
The fiber is implemented in user mode, the kernel does not know the existence of the fiber, which is different from the thread, and the thread is realized by the kernel. Moreover, the fiber is used in a non-seizuated call mode.
One or more fibers can be included in a thread. However, the thread can only perform a fiber code. When using a fiber, you must use the ConvertThreadTofiber function to convert the existing thread into a fiber. You can also use CreateFiber to create another fiber. (to be continued)