《Windows核心编程》---内核对象和进程基础

《Windows核心编程》之“内核对象”     内核对象(Kernel Object)是Winodws操作系统中最核心的一个概念,本章主要介绍“内核对象”整个抽象概念的共性,而不针对具体的某个内核对象。     这一章介绍了“内核对象”的公共属性:usage count(使用计数) 和 Security Descriptor (SD,安全描述符)、进程的内核对象句柄、内核对象的命名空间和跨进程共享内核对象。        要理解本章... 阅读详情

80386处理器有3种工作模式:实模式、保护模式和虚拟86模式。其中,实模式和虚拟86模式是为了和8086处理器兼容而设置的,保护模式是80386处理器的主要工作模式。Windows操作系统运行在此模式下,保护主要是对存储器的保护。

80386对多任务操作系统的支持主要体现在两方面:一是在硬件上为任务之间的切换提供良好的条件;二是它实现了多任务隔离。多任务隔离技术可以使每个任务都有独立的地址空间,就像每个任务独享一个CPU一样。

在Windows中,任务被进程取代,进程是正在运行的应用程序的实例;但是占用CPU时间片执行指令的并不是进程,而是线程。

保护模式下,80386所有的32根地址线都可供寻址,处理器寻址的范围是0x00000000~0xFFFFFFFF(232,4GB),因此,32位Windows操作系统可寻址4GB的地址空间,这就允许一个指针有4 294 967 296个不同的取值,它覆盖了整个4GB的范围。

Windows为每个进程分配4GB的地址空间主要依靠CPU的支持。CPU在保护模式下支持虚拟存储,即虚拟内存,它可以帮助操作系统将磁盘空间当作内存空间来使用。在磁盘上应用于这一机制的文件被称为页文件(Paging File),它包含了对所有进程都有效的虚拟内存。

Windows实现虚拟内存机制就是基于上述的一个32位的线性地址空间。32位地址空间转化为4GB虚拟内存。在多数系统上,Windows将此空间的一半(4GB的前半部分,0x00000000~0x7FFFFFFF)留给进程作为私有存储,自己使用另一半(后半部分,0x80000000~0xFFFFFFFF)来存储操作系统内部使用的数据。

各进程的地址空间被分成了用户空间和系统空间两部分。用户空间是进程私有的地址空间;系统空间放置操作系统的代码,包括内核代码。设备驱动代码。设备I/O缓冲区等。系统空间在所有进程中是共享的。

 

内核对象是系统提供的用户模式下代码与内核模式下代码进行交互的基本接口。一个内核对象是一块内核分配的内存,它只能被运行在内核模式下的代码访问。内核对象记录的数据在整个系统中只有一份,所有它们也被称为系统资源。对于每一个内核对象,Windows都提供了在其上操作的API函数。内核对象和普通的数据结构之间最大的区别是其内部数据结构是隐藏的,必须调用一个对象服务才能从此对象中得到数据,或者向其输入数据,而不能直接读或者改变对象内部的数据。

引入内核对象之后,系统可以方便地完成下面4个任务:

1)为系统资源提供可识别的名字;

2)在进程间共享资源和数据;

3)保护资源不会被未经认可的代码访问;

4)跟踪对象的引用情况,这使得系统知道什么时候一个对象不再被引用了,以便释放它占用的空间。

 

内核对象的数据结构仅能够从内核模式访问,所以直接在内存中地位这些数据结构对应用程序来说是不可能的,应用程序必须使用API函数来访问内核对象。调用函数创建内核对象时,函数会返回标识此内核对象的句柄。为了使系统稳定,这些句柄是进程相关的,即仅对创建该内核对象的进程有效。如果将一个句柄值通过某种机制传给其他进程中的线程,那么,该线程以此句柄为参数调用相关函数就会失败。当然,多个进程共享一个内核对象也是可能的,调用DuplicateHandle函数复制一个进程句柄传给其他进程即可。

 

进程是一个正在运行的程序,它拥有自己的虚拟地址空间,拥有自己的代码、数据和其他系统资源,如进程创建的文件、管道、同步对象等。

组成Win32进程的两个部分:

1)进程内核对象:操作系统使用此内核对象来管理进程,这个内核对象也是操作系统存放进程统计信息的地方;

2)私有的虚拟地址空间:此地址空间包含了所有可执行的或者DLL模块的代码和数据,它也是程序动态申请内存的地方,比如说线程堆栈和进程堆。

 

应用程序必须有一个入口函数main,在程序开始运行时被调用。操作系统事实上并不是真的调用main函数,而是去调用C/C++运行期启动函数,此函数会初始化C/C++运行期库。因此,在程序中可以调用malloc和free之类的函数,它也会保证在用户的代码执行之前所有全局或静态的C++对象能够被正确的创建。在控制台应用程序中,C/C++运行期启动函数会调用程序入口函数main。

在Win32应用程序的启动过程就是进程的创建过程,操作系统是通过调用CreateProcess函数来创建新的进程的。系统接着会为新进程创建一个主线程,这个主线程通过执行C/C++运行期启动代码开始运行,C/C++运行期启动代码又会调用main函数。系统在创建新的进程时会为新进程指定一个STARTUPINFO类型的变量,这个结构包含了父进程传递给子进程的一些显示信息。对图形界面应用程序来说,这些信息将影响新的进程中主线程的主窗口的显示;对控制台应用程序来说,如果有一个新的控制台窗口被创建的话,这些信息将影响这个控制台窗口。

STARTUPINFO结构定义如下:

typedef struct

{

       DWORD cb;       //结构的长度,总是应该被设为sizeof(STARTUPINFO)

       LPSTR lpReserved;     //保留字段

       LPSTR lpDesktop;      //指定桌面名称

       LPSTR lpTitle;            //控制台应用程序使用,指定控制台窗口标题

       DWORD dwX;   //指定新创建窗口的位置坐标和大小信息

       DWORD dwY;

       DWORD dwXSize;

       DWORD dwYSize;

       DWORD dwXCountChars;     //控制台程序使用,指定控制台窗口的行数

       DWORD dwYCountChars;

       DWORD dwFillAttributr;        //控制台程序使用,指定控制台窗口的背景色

       DWORD dwFlags;    //标志它的值决定了STARTUPINFO结构中哪些成员的值是有效的

       WORD wShowWindow;        //窗口的显示方式

       WORD cbReserved2;

       LPBYTE  lpReserved2;

       HANDLE hStdInput;         //控制台程序使用,几个标准句柄

       HANDLE hStdOutput;

       HANDLE hStdError;  

}STARTUPINFO, *LPSTARTUPINFO;

 

一个进程可以调用GetStartupInfo函数来取得父进程创建自己时使用的STARTUPINFO结果。事实上,Windows系统就是通过调用这个函数来取得当前进程的创建信息,以便对新进程中主窗口的属性设置默认值。函数定义如下:

VOID GetStartupInfo(LPSTARTUPINFO lpStartupInfo);     //取得当前进程被创建时指定的STARTUPINFO结构

定义一个STARTUPINFO结构的对象后,总要在使用此对象之前将对象的cb成员初始为

STARTUPINFO结构的大小:

STARTUPINFO si = {sizeof(si)};            //将cb成员初始化为asizeof(si),其他成员初始化为0

::GetStartupInfo(&si);

初始化cb成员是必须的,因为随着Windows版本的改变,API函数支持的结构体的成员有可能增加,

但又要兼容以前版本,所以Windows要通过结构体的大小来确定其成员的数目。

 

CreateProcess函数创建一个新的进程和该进程的主线程。新的进程会在父进程的安全上下文中运行指定的可执行文件:

CreateProcess(

       LPCSTR lpApplicationName,         //可执行文件的名称

       LPSTR lpCommandLine,          //指定了要传递给执行模块的参数

       LPSECURITY_ATTRIBUTES lpProcessAttributes,        //进程安全性,值为NULL的话表示使用默认的安全属性

       LPSECURITY_ATTRIBUTES lpThreadAttributes, //线程安全性,值为NULL的话表示使用默认的安全属性

       BOOL bInheritHandles,           //指定了当前线程中的可继承句柄是否可被新进程继承

       DWORD dwCreationFlags,     //指定了新进程的优先级以及其他创建标识

       LPVOID lpEnvironment,   //指定新进程使用的环境变量

       LPCSTR lpCurrentDirectory,    //新进程使用的当前目录

       LPSTARTUPINFO lpStartupInfo,    //指定新进程中主窗口的位置、大小和标准句柄等

       LPPROCESS_INFORMATION lpProcessInformation       //【out】返回新建进程的标志信息,如ID号、句柄等

       );

上面的lpApplicationName和lpCommandLine参数指定了新的进程将要使用的可执行文件的名称和传递给新进程的参数。例如,下面代码启动了Windows自带的记事本程序:

STARTUPINFO si = {sizeof(si)};

PROCESS_INFORMATION pi;

char *szCommandLine = "notepad";    //"notepad.exe" is also OK

::CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE,

       NULL, NULL, NULL, &si, &pi);

LpCommandLine参数为新的进程指定了一个完整命令行,当CreateProcess函数复制此字符串时,它首先检查字符串中第一个单词,并假设该单词就是我们想要运行的可执行文件的名字,若此名字没有后缀,.exe后缀将被添加进来。CreateProcess函数会按以下路径搜索可执行文件:

1)调用进程的可执行文件所在的目录;

2)调用进程的当前目录;

3)Windows的系统目录(system32目录);

4)Windows目录;

5)在名称为PATH的环境变量中列出的目录。

当然,如果文件名中包含了目录,系统会直接在这个目录中查找,而不会再去其他目录中搜索。

如果系统找到了可执行文件,它会创建一个新的进程并将该可执行文件中的代码和数据映射到新进程的地址空间。之后系统会调用C/C++运行期启动函数,这个函数检查新进程的命令行,将文件名后第一个参数的地址传给新进程的入口函数。例如:

char *szCommandLine = "notepad readme.txt";      //指定了一个readme.txt参数,将使记事本打开此文件

 

lpProcessInformation参数是一个指向PROCESS_INFORMATION结构的指针,CreateProcess函数在返回之前会初始化此结构的成员:

typedef struct

{

       HANDLE hProcess, //新建进程的内核句柄

       HANDLE hThread,     //新建进程中主线程的内核句柄

       DWORD dwProcessId,     //新建进程的ID

       DWORD dwThreadId      //新建进程的主线程ID

}PROCESS_INFORMATION, *LPPROCESS_INFORMATION;

由上可见,创建一个新的进程将促使系统创建一个进程内核对象和一个现场内核对象。在创建它们时,系统将每个对象的使用计数初始化为1。然后,在CreateProcess返回之前,这个函数打开此进程内核对象和线程内核对象的句柄,并将它们的值传给上述结构的hProcess和hThread成员。CreateProcess在内部打开内核对象时,这两个对象的使用计数将会增加到2.。因此,父进程中必须有一个线程调用CloseHandle关闭CreateProcess函数返回的两个内核对象的句柄。否则即便是子进程已经终止了,该进程的进程内核对象和主线程内核对象仍然没有释放。

当进程内核对象或线程内核对象创建以后,系统会给其分配一个唯一的ID号,且进程和线程ID使用同一个号码分配器,因此同一时间不可能重复。但当一个内核对象销毁时,其拥有的ID号可能被重新分配给其他的对象,因此,应该避免使用ID号来跟随进程和线程。

创建进程的例子(打开Windows自带的命令行程序cmd.exe):

int main(int argc, char* argv[])

{

       char szCommandLine[] = "cmd";

       STARTUPINFO si = {sizeof(si)};

       PROCESS_INFORMATION pi;

       si.dwFlags = STARTF_USESHOWWINDOW;   //指定wShowWindow成员

       si.wShowWindow = TRUE;    //此成员设为TRUE,表示显示新建进程的主窗口

      

       BOOL bRet = ::CreateProcess(

              NULL,    //不在此指定可执行文件的文件名

              szCommandLine,       //命令行参数

              NULL,    //默认进程安全性

              NULL,    //默认主线程安全性

              FALSE,   //指定当前进程内的句柄不可以被子进程继承

              CREATE_NEW_CONSOLE,    //为新进程创建一个新的控制台窗口

              NULL,    //使用本进程的环境变量

              NULL,    //使用本进程的驱动器和目录

              &si,

              &pi

              );

       if(bRet)

       {

              //既然不使用两个句柄,最后立即关闭它们

              ::CloseHandle(pi.hThread);

              ::CloseHandle(pi.hProcess);

              printf("新进程的进程ID号为:%d/n", pi.dwProcessId);

              printf("新进程的主线程ID号位:%d/n", pi.dwThreadId);            

       }

}

 

使用ToolHelp函数可以获取当前正在运行的一系列进程。首先使用CreateToolhelp32Snapshot函数给当前系统内执行的进程拍快照,也就是获得一个进程列表,这个列表中记录着进程的ID、进程对应的可执行文件的名称和创建该进程的进程ID等数据。接着使用Process32First函数和Process32Next函数遍历快照中记录的列表,代码如下:

#include <windows.h>

#include <iostream>

#include <tlhelp32.h>    //声明快照函数的头文件

int main(int argc, char* argv[])

{

       PROCESSENTRY32 pe32;

       //在使用这个结构之前先设置它的大小

       pe32.dwSize = sizeof(pe32);

       //给系统内所有进程拍一个快照

       HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(

                     TH32CS_SNAPPROCESS, 0);

       if(hProcessSnap == INVALID_HANDLE_VALUE)

       {

              printf("CreateToolhelp32Snapshot调用失败/n");

              return -1;      

       }

       //遍历进程快照,依次显示每个进程的信息

       BOOL bMore = ::Process32First(hProcessSnap, &pe32);

       while(bMore)

       {

              printf("进程名称:%s/n", pe32.szExeFile);

              printf("进程ID号:%u/n/n", pe32.th32ProcessID);

              bMore = ::Process32Next(hProcessSnap, &pe32);   

       }

      

       //释放snapshot对象

       ::CloseHandle(hProcessSnap);

       system("pause");

       return 0;

}

CreateToolhelp32Snapshot用于获取系统内指定进程的快照,也可以获取被这些进程使用的堆、模块和线程的快照:

HANDLE WINAPI CreateToolhelp32Snapshot(

       DWORD dwFlags,     //用来指定快照中需要返回的对象

       DWORD th32ProcessID,//一个进程ID号,用来指定要获取哪一个进程的快照

                            //当获取系统进程列表或获取当前进程快照时可以设为0

       );

这个函数不仅可获取进程列表,也可以用来获取线程和模块等对象的列表。dwFlags参数指定了获取的列表的类型:

TH32CS_SNAPHEAPLIST---枚举th32ProcessID参数指定的进程中的堆

TH32CS_SNAPMODULE---枚举th32ProcessID参数指定的进程中的模块

TH32CS_SNAPPROCESS---枚举系统范围内的进程,此时th32ProcessID参数被忽略

TH32CS_SNAPTHREAD---枚举系统范围内的线程,此时th32ProcessID参数被忽略

 

Process32First和Process32Next函数的第一个参数是快照句柄,第二个参数是一个指向PROCESSENTRY32结构的指针,进程信息将会被返回到这个结构中:

typedef struct

{

       DWORD dwSize,       //结构的长度,必须预先设置

       DWORD cntUsage,    //进程的引用计数

       DWORD th32ProcessID,  //进程ID

       DWORD th32DefaultHeapID,       //进程默认堆的ID

       DWORD th32ModuleID, //进程模块的ID

       DWORD cntThreads, //进程创建的线程数

       DWORD th32ParentProcessID,      //进程的父进程ID

       LONG pcPriClassBase,      //进程创建的线程的基本优先级

       DWORD dwFlags,     //内部使用

       CHAR szExeFile[MAX_PATH]       //进程对应的可执行文件名

}PROCESSENTRY32;

 

终止进程也就是结束程序的执行,从内存中卸载它,进程终止的原因有4种:

1)主线程的入口函数返回;

2)进程中一个线程调用了ExitProcess函数;

3)此进程中的所有线程都结束了;

4)其他进程中的一个线程调用了TerminateProcess函数。

 

要结束进程一般让主线程的入口函数(main函数)返回。当用户的程序入口函数返回时,启动函数会调用C/C++运行期退出函数exit,并将用户的返回值传递给它。Exit函数会销毁所有全局的或静态的C++对象,然后调用系统函数ExitProcess此时操作系统终止应用程序:

void ExitProcess(UINT uExitCode);      //参数uExitCode为此程序的退出代码

我们也可以在程序的任何地方调用ExitProcess强制当前程序立即结束。对操作系统,这是很正常的;但对C/C++应用程序来说,应该避免直接调用这个函数,因为这会使C/C++运行期库得不到通知,而没有机会去调用全局或静态的C++对象的析构函数。

 

ExitProcess函数只能用来结束当前进程,不能用于结束其他进程。如果要结束其他进程的执行,可以使用TerminateProcess函数:

BOOL TerminateProcess(

       HANDLE hProcess,     //要结束的进程(目标进程)的句柄

       UINT uExitCode //指定目标进程的退出代码,

 //可以使用GetExitCodeProcess取得一个进程的退出代码

);

在使用TerminateProcess函数之前,我们首先需要取得目标进程的句柄,可以使用OpenProcess函数来取得这个进程的访问权限:

HANDLE OpenProcess(

       DWORD dwDesiredAccess,     //想得到的访问权限(PROCESS_ALL_ACCESS等)

       BOOL hInheritHandle,     //指定返回的句柄是否可继承

       DWORD dwProcessId             //指定要打开的进程的ID号

);

一般使用下面代码来终止一个进程:

BOOL TerminateProcessFromId(DWORD dwId)

{

       BOOL bRet = FALSE;

       //打开目标进程,取得进程句柄

       HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwId);

       if(hProcess != NULL)

       {

              bRet = ::TerminateProcess(hProcess, 0);

       }

       CloseHandle(hProcess);

       return bRet;

}

一旦进程终止,会有如下事件发生:

1)所有被这个进程创建或打开的对象句柄就会关闭;

2)此进程内的所有线程将会终止执行;

3)进程内核对象变成受信状态,所有等待在此对象上的线程开始运行,即WaitForSingleObject函数返回;

4)系统将进程对象中退出代码的值由STILL_ACTIVE改为指定的退出码。

 

 

 

Sentence-BERT 语义相似度双塔模型 论文介绍 发表:2019,EMNLP 论文题目:《Sentence-BERT:sentence embeddings using siaese BERT-networks》 论文地址:https://arxiv.org/abs/1908.10084 Github:https://github.com/UKPLab/sentence-transformers 适用领域: 句向量生成 语义相似度计算 语义搜索 无监督任务(聚类) 1 概述 在20年之前的各种预训练模型中,比如bert,XLNet,Alb 阅读详情

相关推荐

深入浅出PWM:用示波器带你理解占空比与滤波效果

本文通过示波器实测,深入浅出地解析了PWM(脉宽调制)的核心原理。从占空比与平均电压的关系入手,详细演示了RC及有源滤波器如何将数字方波“翻译”为平滑模拟电压,并探讨了PWM-DAC的精度、响应速度等关键设计考量,为硬件调试与电路设计提供了实用的实践指导。

weixin_29292431的博客 346

一篇文章带您了解操作系统的运行机制

是操作系统提供给应用程序(程序员/编程人员)使用的接口,可以理解为一种可供应用程序调用的特殊函数,应用程序可以通过系统调用来请求获得操作系统内核的服务。普通应用程序可以直接进行系统调用,也可以使用库函数。有的库函数涉及系统调用,有的不涉及编程语言向上提供库函数。有时会将系统调用翻转成库函数,以隐藏系统调用一些细节,使得程序员编程更加方便。操作系统向上提供系统服务,是得上层程序能请求内核的服务。

weixin_54454406的博客 1452

vue 获取el-table多选的选中行

<el-table :data='tableData' ref="multipleTable" v-loading='loading' border max-height='700' style='width: 100%' size="mini"> <el-table-column type="selection" width="55"></el-table-column> <el-table-column label

且听风吟的博客 6649

操作系统内核kernel

操作系统内核是操作系统的核心组成部分,负责协调和管理计算机的硬件资源,并为应用程序提供基础服务。它是实现多任务、资源共享和系统安全的关键部分,确保系统能够高效、稳定地运行。

眷怀的博客 1472

告别盲目调参:手把手教你用RKISP2.x Tuner理解AWB、AE、NR等核心模块

本文详细介绍了如何使用RKISP2.x Tuner工具进行ISP调试,重点解析AWB、AE、NR等核心模块的调参技巧。通过RV1126平台的实际操作演示,帮助工程师快速掌握可视化对比实验方法,告别盲目调参,提升图像信号处理效率。

weixin_30300225的博客 394

Ansys Lumerical FDTD仿真加速策略与高性能硬件选型指南

本文深入探讨了Ansys Lumerical FDTD仿真的核心加速策略,涵盖算法优化与硬件选型两大维度。通过合理运用非均匀网格、对称边界条件等算法技巧,并精准匹配CPU/GPU计算资源与高性能硬件配置,可显著提升仿真效率,将计算时间从数天缩短至数小时。

a0b1c2d3的专栏 614

Windows内核原理与实现--Windows进程线程基本概念(1)

操作系统需要做的事情是:维护一个全局的进程表,记录下当前有哪些进程正在被执行,把时间分成适当的片段

XboxMicro 1633

QT+QTimer+QThread实现线程内的定时任务并且和主线程进行交互

在制作qt软件时,我们经常会用到qtimer定时器以及将其在非主线程中进行使用,甚至有的时候还需要和主线程进行交互。我总结了两种用法,仅供参考。以上即为QTimer和QThread联合使用的学习记录。

u011826081的博客 5685

Windows 内核结构 摘抄自《windows内核原理与实现》

2.2.1 Windows 内核结构 正如图2.2 所示,Windows 内核分为三层,与硬件直接打交道的这一层称为硬件抽象层(Hardware Abstraction Layer,简称HAL),这一层的用意是把所有与硬件相关联的代码逻辑隔离到一个专门的模块中,从而使上面的层次尽可能做到独立于硬件平台。HAL之上是内核层,有时候也称为微内核(micro-kernel),这一层包含了基本的操作系统

Invoker's Tower 3834

使用 DEM 模拟金属烧结过程

了解离散元素法 (DEM) 如何彻底改变烧结工艺,提高制造业的效率和精度。

jkh920184196的博客 1129

《测绘综合能力》——大地测量

《测绘综合能力》大地测量 部分重要(常考)知识点(精简版)。

C_xxy's blog 805

Windows的消息机制和通信机制

应用程序可以定义自定义消息,以实现特定功能。自定义消息通常使用WM_APP以上的值。Windows操作系统的核心机制涵盖了内核架构、进程和线程管理、内存和文件系统管理等多个方面。窗口消息和消息机制是Windows与应用程序交互的基础,而DLL框架和进程间通信则为应用程序提供了模块化和高效的通信手段。深入理解这些机制有助于开发高效、稳定和安全的Windows应用程序。

远方雪的专栏 2010

使用Qt和MX Component插件实现与菱PLC的通信

在本文中,我们介绍了如何使用Qt和MX Component插件实现与菱PLC的通信。我们首先安装和配置了MX Component插件,并在Qt项目中初始化和使用MX Component来连接、读取和写入PLC的数据。安装完成后,您需要在Qt项目中配置MX Component的路径,以便Qt可以找到所需的库文件。在本文中,我们将探讨如何使用Qt和MX Component插件来实现与菱PLC的通信。在主函数中,我们将初始化MX Component,并创建一个与PLC通信的示例。在上面的代码中,我们使用了。

TlScratch的博客 996

windows核心编程

主要用于记录windows核心编程这本书籍的学习。

weixin_45002961的博客 1341

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

《谈谈Windows核心编程系列》导读

《谈谈Windows核心编程系列》导读         谈谈Windows核心编程系列终于发布完了。        发布这些文章的目的:          一是为了总结之用,当需要的时候可以迅速的找出。         二也是在记录学习轨迹。         慢慢的养成了一种习惯,好像不写笔记就不算读过书一样。读书的时候会不自觉的加快速度,有时候看的不是很仔细,有时甚至看了很多遍还是

ithzhang 1万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Windows核心编程

Windows核心编程学习01.Winwods核心编程:字符和字符串处理02.Windows核心编程:内核对象03.Windows核心编程:进程04.Windows核心编程:线程基础05.Windows核心编程:作业06.Windows核心编程:线程调度07.

shenzi的天空 2567

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Window核心编程

Window核心编程 第一章:错误处理 FormatMessage/LocalLock\LocalFree 第二章: TEXT("..") TCHAR(CHAR,WCHAR)  安全字符串函数 (必须在包含其他所有文件之后才包含StrSafe.h) _tcscpy  _tcscpy_s _CrtSetReportMode(_CRT_ASSERT,0); //禁止可能由C运行时触发的所

零点起步 802

[笔记]Windows核心编程《二十二》注入DLL和拦截API

文章目录前言一、插入DLL:一个例子二、使用注册表来插入DLL三、使用Windows挂钩来插入DLL四、使用远程线程来插入DLL4.1 Inject Library示例应用程序4.2 Image Walk DLL五、使用特洛伊DLL来插入DLL六、将DLL作为调试程序来插入七、用Windows 98上的内存映射文件插入代码八、用CreateProcess插入代码九、挂接A P I的一个示例9.1 通过改写代码来挂接API、9.2 通过操作模块的输入节来挂接API9.3 LastMsgBoxInfo示例应用程

二次元怪兽的博客 2042

《Windows核心编程》读书笔记 上

[C++]《Windows核心编程》读书笔记   这篇笔记是我在读《Windows核心编程》第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入,但应该是合理的。开头几章由于我追求简洁,往往是很多单独的字句,后面的内容更为连贯。   海量细节。     第1章    错误处理   ...

weixin_33756418的博客 148

[笔记]Windows核心编程《十五》在应用程序中使用虚拟内存

文章目录前言一、预定地址空间区域1.1 VirtualAlloc函数二、给区域调拨物理存储器三、同时预定和调拨物理存储器四、何时调拨物理存储器五、撤销调拨物理存储器及释放区域六、改变保护属性七、重置物理存储器的内容 前言 Microsoft Windows 提供三种机制来对内存进行操控: 虚拟内存 最适合用来管理大型对象数组或大型结构数组 内存映射文件 最适合用来管理大型数据六(通常是文件) 堆 最用来适合管理大量的小型对象 一、预定地址空间区域 1.1 VirtualAlloc函数 LPVOID W

二次元怪兽的博客 1121

Windows的4种主要的同步对象(原)

同步对象Windows共设置了4种主要的同步对象,分别是临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)和事件(Event)。MFC封装了它们,分别是类CCriticalSection、CMutex、CSemaphore和CEvent,它们都以CSyncObject为基类。1、临界区(1)创建:CCriticalSection myCritical

893

[笔记]Windows核心编程《二》内核对象

文章目录进程和程序内核对象何为内核对象系统4环结构内核对象数据结构句柄使用计数Counter安全描述符SecurityDescriptor内核对象的安全性SECURYITY_ATTRIBUTES 结构体进程内核对象句柄表进程的句柄表结构创建一个内核对象关闭内核对象跨进程边界共享内核对象使用对象句柄继承改变句柄的标志为对象命名终端服务命名空间专有命名空间复制对象句柄工具winObj 查看所有内核对象及当前计数ProcessExplorer 查看所有进程状态总结 进程和程序 一、 进程是动态的,程序是静态的

二次元怪兽的博客 1752

Windows核心编程笔记——内核对象

本节讨论的不是具体某一种类型的内核对象,而是所有内核对象共通的一些特性。

随手写下笔记和感悟 1333

WINDOWS核心编程-----3章,3.2 内核对象:进程的内核对象句柄表,创建内核对象,关闭内核对象

WINDOWS核心编程-----3章,内核对象:进程的内核对象句柄表,创建内核对象,关闭内核对象。

zhyjhacker的博客 1214

windows核心编程:第3章 3.1内核对象,什么是内核对象,内核对象的使用计数,安全性

作为一个Windows软件开发人员,你经常需要创建、打开和操作各种内核对象。系统要创建和操作若干类型的内核对象,比如存取符号对象、事件对象、文件对象、文件映射对象、I0完成端口对象、作业对象、信箱对象、互斥对象、管道对象、进程对象、信标对象、线程对象和等待计时器对象等。这些对象都是通过调用函数来创建的。例如,CreateFileMapping函数可使系统能够创建一个文件映射对象。每个内核对象只是内核分配的一个内存块,并且只能由该内核访问。该内存块是一种数据结构,它的成员负责维护该对象的各种信息。

zhyjhacker的博客 1358
上一篇: 《Windows核心编程》---ADO基础
下一篇: 《Windows核心编程》---Windows服务
ACE1985
博客等级 码龄17年 1307粉丝 308原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值