14、Windows API 进程、线程、模块

简介: 一、基本概念  1、进程是应用程序的实例。进程包括一个虚拟地址空间及代码、数据、对象等程序运行所需环境和资源的集合。在内存空间中包括若干可执行的代码、数据、资源、一系列对系统对象操作的句柄,安全上下文、进程标识符(PID),环境变量等程序执行的环境。

一、基本概念 

1、进程是应用程序的实例。进程包括一个虚拟地址空间及代码、数据、对象等程序运行所需环境和资源的集合。在内存空间中包括若干可执行的代码、数据、资源、一系列对系统对象操作的句柄,安全上下文、进程标识符(PID),环境变量等程序执行的环境。同时,进程还包括一个或多个执行线程。 

        线程是程序的执行流程在操作系统层面,线程是需要操作系统为其分配执行时间片的基本单元。线程附属于进程,一个线程可以执行进程中任意部分的代码。一个系统中同一时间只能有少量线程执行(决定于CPU个数和核数),操作系统决定当前执行哪一个线程,并进行调度。每一个线程都包括一个上下文(主要是CPU寄存器值)。在进行线程调度时,系统会保存线程上下文。

        一个程序由多个模块组成。程序没有运行时,模块以可执行文件的形式存在(exe、dll等);程序运行后,所需要的模块都加载到进程的虚拟地址空间中,进行初始化的设置后,各模块就可以协同工作。每一个模块都可能包括代码、数据、资源等。

2、可执行文件

        程序的载体是可执行文件。可执行文件中包括运行所需的程序、数据及一些配置信息等。Windows平台的可执行文件包括exe、dll、sys等扩展名的文件。

        Windows平台的可执行文件基本都是PE格式的。

3、应用程序

应用程序是由一系列具有特定功能、能完成执行操作的可执行文件、数据的集合,一个应用程序可以包括若干个可执行程序、动态链接库、数据文件。Windows平台的应用程序根据与用户交互的方式区分为控制台应用程序与图形用户界面( GUI)程序;编译程序时通过/SUBSYSTE选择。

4、进程

        进程提供了程序运行所需要的资源、虚拟内存地址空间、各种数据、可执行的代码、需要使用到的各种内核对象、系统调用接口、优先级与权限配置、工作集、环境变量等,还包括至少一个执行过程(线程)。

进程是正在运行的程序,即程序的运行实例。

        每个进程都有一个标识符(PID)和一个句柄,系统和其他进程可以通过PID和进程的句柄对进程进行管理和操作。

5、动态链接库

        动态链接库是将应用程序模块化的重要方法

程序是在进程创建或程序运行时进行链接的,因此称为“动态链接”静态链接是在程序构建时由链接器进行链接,将代码和数据组织在同一个可执行文件中

6、模块

        每个可执行程序都可以称作一个模块,DLL文件是模块。exe文件也是模块,称为主模块。

7、线程

        进程的这种同时处理多个任务的能力是通过线程机制实现的。

        线程是附属在进程上的执行实体,是代码的执行流程。

       一个进程中可以有多个线程在并发执行。进程的所有线程都共享其虚拟地址空间、数据、系统资源等。每个线程都有自己的栈、上下文(context,包括CPU寄存器值等,线程调度时会进行线程上下文切换)、异常处理程序、调度优先级、标识符等。线程的切换依赖于中断。

        每个进程必须有至少一个线程,在进程创建时即开始执行的线程是进程的主线程,主线程可以再创建其他线程。

8、纤程( Fiber)

       纤程也是程序执行单元,与线程类似。不同的是纤程必须要应用程序自行调度,而线程是由系统进行调度的。纤程运行于线程的上下文中,一个线程可以调度很多纤程。

9、作业(Job,也称为工作项)

       作业是一种对象,可以将一组进程作为一个单元进行管理。作业包括命名对象(namable)安全对象(securable)和共享对象(sharable),可以控制进程组的属性。

二、进程相关API

Process and Thread Functions

http://msdn.microsoft.com/en-us/library/ms684847%28VS.85%29.aspx

    如果进程知道其他进程的标识符( PID),还可以通过OpenProcess函数获取进程的句柄,也可以通过GetProcessId通过句柄获取PID。

创建进程示例

创建进程示例
 
   
**************************************/
/* 头文件  */
#include
< windows.h >
#include
< stdio.h >

DWORD CreateChildProcess(LPSTR szChildProcessCmd);

/* ************************************
* int main(void)
* 功能 演示进程创建
*
* 参数 未使用
*************************************
*/
int main()
{
CreateChildProcess(
" Child.exe abc 123 " );
}
/* ************************************
* DWORD CreateChildProcess(LPSTR szChildProcessCmd)
* 功能 演示创建子进程
*
* 参数 LPSTR szChildProcessCmd 启动子进程的命令行
* 返回值 成功返回,失败返回
*************************************
*/
DWORD CreateChildProcess(LPSTR szChildProcessCmd)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
// 将启动信息结构清零
ZeroMemory( & si, sizeof (si) );
// 设置结构大小,cb属性应为结构的大小
si.cb = sizeof (si);
// 将进程信息结构清零
ZeroMemory( & pi, sizeof (pi) );

// 创建子进程,并判断是否成功
if ( ! CreateProcess( NULL, // 使用命令行
szChildProcessCmd, // 命令行
NULL, // 不继承进程句柄
NULL, // 不继承线程句柄
FALSE, // 不继承句柄
0 , // 没有创建标志
NULL, // 使用父进程环境变量
NULL, // 使用父进程目录作为当前目录
& si, // STARTUPINFO 结构
& pi ) // PROCESS_INFORMATION 保存相关信息
)
{
// 创建失败
printf( " CreateProcess failed (%d).\n " , GetLastError() );
return 1 ;
}
// 在创建成功后父进程也可直接退出,这里等待子进程执行结束

// 等待子进程结束
// 使用到了通过PROCESS_INFORMATION 返回的相关信息,hProcess为子进程句柄
// 父进程也可以不等待子进程运行完成而直接退出
WaitForSingleObject( pi.hProcess, INFINITE );
// 关闭进程句柄和线程句柄
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
return 0 ;
}

创建线程示例

创建线程示例
 
   
**************************************/
/* 头文件  */
#include
< windows.h >
#include
< stdio.h >
/* 常量定义  */
#define MAX_THREADS 5
/* 结构类型  */
typedef
struct _THREAD_PARAM {
DWORD i;
DWORD dwRandom;
DWORD dwData;
} THREAD_PARAM,
* LPTHREAD_PARAM;

/* ************************************
* DWORD WINAPI ThreadProc( LPVOID lpParam )
* 功能 线程函数
* 将参数打印出
*
* 参数 LPVOID lpParam THREAD_PARAM 结构类型
*************************************
*/
DWORD WINAPI ThreadProc( LPVOID lpParam )
{
LPTHREAD_PARAM pData;
// 参数数据类型
pData = (LPTHREAD_PARAM)lpParam;
// 显示参数
printf( " TID = %u,\t Parameters = %u, %u, %u\n " ,
GetCurrentThreadId(),
pData
-> i, pData -> dwRandom, pData -> dwData);
// 释放保存参数的内存(在主线程中分配的).
HeapFree(GetProcessHeap(), 0 , pData);
return 0 ;
}
/* ************************************
* void main()
* 功能 主线程函数,创建了多个线程
*************************************
*/
void main()
{
LPTHREAD_PARAM pData;
DWORD dwThreadId[MAX_THREADS];
HANDLE hThread[MAX_THREADS];
int i;

// 创建MAX_THREADS 个线程.
for ( i = 0 ; i < MAX_THREADS; i ++ )
{
// 为线程函数参数分配内存
pData = (LPTHREAD_PARAM)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof (THREAD_PARAM));
if ( pData == NULL )
{
printf(
" HeapAlloc error;\n " );
ExitProcess(
2 );
}
// 设置参数
pData -> i = i;
pData
-> dwRandom = rand();
pData
-> dwData = 100 ;
// 创建线程
hThread[i] = CreateThread(
NULL,
// 默认安全属性
0 , // 默认堆栈大小
ThreadProc, // 线程函数
pData, // 参数
0 , // 默认创建标志
& dwThreadId[i]); // 返回TID
// 判断是否创建成功
if (hThread[i] == NULL)
{
ExitProcess(i);
}
}
}

三、进程状态信息

两类API

进程状态帮助(Process Status Helper,PSAPI),工具帮助(Tool helper)两类API

PSAPI

http://msdn.microsoft.com/en-us/library/ms684884%28VS.85%29.aspx

Tool helpr API:

http://msdn.microsoft.com/en-us/library/ms686832%28VS.85%29.aspx

Dynamic-Link Library Functions

http://msdn.microsoft.com/en-us/library/ms682599%28VS.85%29.aspx

导出dll有两种方法:

一是在函数声明是使用__declspec(dllexport)关键字;

二是在模块定义文件(.def)中进行说明。

参考

[1] 精通Windows API

 

 

目录
相关文章
|
3月前
|
Windows
windows环境下根据端口号查询进程编号并杀掉此进程
windows环境下根据端口号查询进程编号并杀掉此进程
|
3月前
|
API Python Windows
python3应用windows api对后台程序窗口及桌面截图并保存的方法
python3应用windows api对后台程序窗口及桌面截图并保存的方法
86 1
|
消息中间件 监控 安全
探究如何在Linux系统中修改进程资源限制:四种方法调整进程限制,让你的系统高效运行(包含应用层getrlimit和setrlimit API)
探究如何在Linux系统中修改进程资源限制:四种方法调整进程限制,让你的系统高效运行(包含应用层getrlimit和setrlimit API)
41 0
|
28天前
|
Linux API C++
【Linux C/C++ 线程同步 】Linux API 读写锁的编程使用
【Linux C/C++ 线程同步 】Linux API 读写锁的编程使用
17 1
|
2月前
|
调度 Python
如何使用`asyncio`模块实现多线程?
【2月更文挑战第4天】【2月更文挑战第10篇】如何使用`asyncio`模块实现多线程?
|
2月前
|
Java Python
使用Python的concurrent.futures模块简化多线程与多进程编程
使用Python的concurrent.futures模块简化多线程与多进程编程
|
3月前
|
C# 数据安全/隐私保护 开发者
Windows平台RTMP推送|轻量级RTSP服务录像模块如何支持中文路径?
Windows平台RTMP推送|轻量级RTSP服务录像模块如何支持中文路径?
|
4月前
|
Java API 调度
Java多线程基础(线程与进程的区别,线程的创建方式及常用api,线程的状态)
Java多线程基础(线程与进程的区别,线程的创建方式及常用api,线程的状态)
52 0
Java多线程基础(线程与进程的区别,线程的创建方式及常用api,线程的状态)
|
4月前
|
Windows
5.4 Windows驱动开发:内核通过PEB取进程参数
PEB结构`(Process Envirorment Block Structure)`其中文名是进程环境块信息,进程环境块内部包含了进程运行的详细参数信息,每一个进程在运行后都会存在一个特有的PEB结构,通过附加进程并遍历这段结构即可得到非常多的有用信息。在应用层下,如果想要得到PEB的基地址只需要取`fs:[0x30]`即可,TEB线程环境块则是`fs:[0x18]`,如果在内核层想要得到应用层进程的PEB信息我们需要调用特定的内核函数来获取。
48 0
5.4 Windows驱动开发:内核通过PEB取进程参数
|
4月前
|
API Windows
5.3 Windows驱动开发:内核取应用层模块基址
在上一篇文章`《内核取ntoskrnl模块基地址》`中我们通过调用内核API函数获取到了内核进程`ntoskrnl.exe`的基址,当在某些场景中,我们不仅需要得到内核的基地址,也需要得到特定进程内某个模块的基地址,显然上篇文章中的方法是做不到的,本篇文章将实现内核层读取32位应用层中特定进程模块基址功能。
31 0
5.3 Windows驱动开发:内核取应用层模块基址

热门文章

最新文章