Error Handling: error handling is classified into statusCodeReturn, exception handling, andBug checkThree, the third (Bug check) That is, we are98The blue screen that is frequently seen in the system,NTThe system is not common, but it can also happen. It is really annoying. However, if a serious error is found during the code execution process, it is best to give a blue screen, because it is a "serious" error, the operating system will be corrupted when the execution continues.
Status CodeNtstatusIs32The integer representing whether the code is successfully executed. Its structure is as follows:
SevIndicates the severity,CIndicates that the status code will be unblocked and sent back to the user,FacilitySpecifies the part from which the error is generated,CodeThe error message is saved. Generally, whether the execution is successful should be usedNt_successMacro to judge, directly lookNtstatusIs it0Yes.
Similar functions can be used in driver development.Try catchBut the Exception Handling Mechanism in the driver andC ++The Mechanism in is not the same. It is also worth noting that exceptions and errors should be strictly distinguished during the development process. do not consider errors as exceptions or do not treat exceptions as errors. According to my understanding, the difference between the two is that after an error occursProgramYou should quit, and you still have the opportunity to remedy the exception.
The driver uses the exception frames stored in the program stack to handle exceptions. When an exception occurs, the system scans the stack and finds the exception frame. A filter program and an exception handler are retained in the exception frame. If all the specified conditions in the filter program are met, the exception handler is executed. Otherwise, the exception handler is skipped. If no filter program exists, the system assigns a default action. If no exception handling program exists, the system also assigns a default action, which means the system crashes.
In the driver_ Try, _ partition tAnd_ FinallyKeyword meaning andC ++._ FinallyThe code in the block will be executed in any way, even if your_ TryBlock hasReturnOrGotoSuch a statement._ Limit tThe statement requires filtering code, which is generally one of the following:
Prediction_execute_handler: Tells the system to execute the exception handling program. If the Handler hasReturnOrGoto, Then what to execute is_ Limit tCode after the block instead of returning or redirecting to the specified location. This is strange,DDKBut the author of a book vowed that he had performed an experiment and he was right,DDKWrong. I choose people who believe in labs.
Prediction_continue_search: Tell the system to continue to find the next exception handling program. If not, the system crashes.
Prediction_continue_execution: Tells the system to return to the exception and continue execution. Generally, it doesn't make sense unless you can change the exception to disappear.
It is worth noting that arithmetic exceptions (0Page faults and invalid pointers cannot be handled by exception handling mechanisms. In fact, they are all errors. And can be usedNtstatusDo not use exceptions if possible because the Exception Handling Mechanism consumes a lot of resources.
Bug checkYesKebugcheckex ()Function, this function never returns, because it is already on the blue screen.
We all knowNTThe memory is divided into two parts. According to the security and integrity, it can be divided into the user mode address and the kernel mode address. According to the paging capability, it can be divided into paging memory and non-Paging memory. In kernel-mode drivers, the memory in user mode cannot be used at will, because the user sends you an address that is a virtual address, and the content to be directed may not be in the memory or on the disk. If you access it rashly, A page error is thrown. The user mode can be used to access the user mode at will. Because the technology points to the content on the disk, the virtual memory component will also help you bring it back to the memory, so the kernel mode is not so good, it has to do everything on its own.
The kernel mode memory can be divided into paging memory and non-Paging memory. The user mode is full of paging memory, which does not allow access to non-Paging memory. The non-Paging memory area is always in the memory and won't be dumped to the disk. Therefore, it is a very valuable resource. The memory capacity is much smaller than the disk capacity. You can useAlloc_textThe compile command indicates that a program segment runs in a paging program, for example# Pragma alloc_text (page, adddevice)SpecifyAdddeviceThe program segment should run in paging memory. If not specified, it is in non-Paging memory by default. The same compilation command also hasData_seg ("page ")Indicates that the variable is stored in the paging memory;Code_seg ("page ")Indicates that the program segment runs in the paging memory. Remember to useData_seg ()AndCode_set ()Reply to default behavior.
The method for applying for dynamic memory in the kernel isExallocatepoll (type, size), AndMallocHowever, you need to specify the type of memory to be applied for. The common types are as follows:
Memory Pool Type |
Description |
Nonpagedpool |
Allocate memory from non-Paging Memory Pool |
Pagedpool |
Allocate memory from the paging Memory Pool |
Nonpagedpoolmustsucceed |
Allocate memory from non-Paging memory pool.Bugcheck |
Nonpagedpoolcachealigned |
Allocate memory from the non-Paging memory pool and ensure that the memory andCPU CacheAlignment |
Nonpagedpoolcachealignedmusts |
AndNonpagedpoolcachealignedSimilar to, but if it cannot be allocatedBugcheck |
Pagedpoolcachealigned |
Allocate memory from the paging memory pool and ensure that the memory andCPU CacheAlignment |
Note that the requested memory should at least be8Byte alignment.
Release dynamic memoryExfreepool(PvoidYou must be careful when releasing dynamic memory applications. Memory leakage in the kernel is terrible. Another function for applying for dynamic memory is
Exallocatepoolwithtag (type, size, tag );AndExallocatepollThe difference is that this function also needs to specify a tag, which is placed at the beginning of the requested content. Microsoft recommends that we keep usingExallocatepoolwithtagTo add our own labels to the applied memory.
The driver provides a set of data structures to facilitate data storage.STLInList,QueueIt is dangerous that other data structures cannot be used in driver development. Instead, we should always use the built-in data structure. Taking the linked list as an example, the kernel providesList_entrySo that we can generate the desired linked list. This structure is only used to construct a linked list and a linked list. You have to define the data stored in the linked list. The strange thing here is that you create a linked listNodeAfter the structure,List_entryIt is stored as its subitem, notList_entryThere is a pointer that can point to our data block. For exampleNode:
Struct Node
{
Int value;
}
HowNodePut inList_entryIn? The correct method is
Struct Node
{
Int value;
List_entry linkfield;
}
Instead of something similarLinkfield-> DATA = node.
GeneratedListIs saved inList_entryAnd want to passList_entryAccessNode, You need to useContaining_recordMacro. For example:
Node pselement = (node) containing_record (PSLINK, node, linkfield );
By the way,IfOrElseIt is best to enclose the operations after a statement in braces, because you cannot determine whether the operation is a function or macro definition. If it is a macro, it will cause unnecessary trouble.
The operating string in the kernel also has its own mechanism. The functions are described as follows:
Operation |
ANSIString Functions |
UnicodeString Functions |
Length |
Strlen |
Wcslen |
Concatenate |
Strcat, strncat |
Wcscat, wcsncat, rtlappendunicodestringtostring, rtlappendunicodetostring |
Copy |
Strcpy, strncpy, rtlcopystring |
Wcscpy, wcsncpy, rtlcopyunicodestring |
Reverse |
_ Strrev |
_ Wcsrev |
Compare |
Strcmp, strncmp, _ stricmp, _ strnicmp, rtlcomparestring, rtlequalstring |
Wcscmp, wcsncmp, _ wcsicmp, _ wcsnicmp, rtlcompareunicodestring, rtlequalunicodestring, rtlprefixunicodestring |
Initialize |
_ Strset, _ strnset, rtlinitansistring, rtlinitstring |
_ Wcsnset, rtlinitunicodestring |
Search |
Strchr, strrchr, strspn, strstr |
Wcschr, wcsrchr, wcsspns, wcsstr |
Upper/lowercase |
_ Strlwr, _ strupr, rtlupperstring |
_ Wcslwr, _ wcsupr, rtlupcaseunicodestring |
Character |
Isdigit, islower, isprint, isspace, isupper, isxdigit, tolower, toupper, rtlupperchar |
Towlower, towupper, rtlupcaseunicodechar |
Format |
Sprintf, vsprintf, _ snprintf, _ vsnprintf |
Swprintf, _ snwprintf |
String Conversion |
Atoi, atol, _ ITOA |
_ Itow, rtlintegertounicodestring, rtlunicodestringtointeger |
Type conversion |
Rtlansistringtounicodesize, rtlansistringtounicodestring |
Rtlunicodestringtoansistring |
Memory release |
Rtlfreeansistring |
Rtlfreeunicodestring |
Please be careful when you tell meANSIAndUnicode.
You can also operate on large memory blocks in the kernel. The specific descriptions are as follows:
Service functions or macros |
Description |
Memchr |
InBlobTo find a byte |
Memcpy, rtlcopybytes, rtlcopymemory |
Duplicate byte, not allowed to overlap |
Memmove, rtlmovememory |
Copy byte, overlapping allowed |
Memset, rtlfillbytes, rtlfillmemory |
Fill in with the given valueBlob |
Memcmp, rtlcomparememory, rtlequalmemory |
Compare twoBlob |
Memset, rtlzerobytes, rtlzeromemory |
BlobReset |