您的位置:首页 > 编程语言

windows基础编程 - 进程和线程

2016-03-06 00:03 399 查看

前言

微软鼓励大家多用线程,而弱化子进程的使用,所以和unix不同,windows下进程的通信很少,内存映射文件是一种。


进程

进程环境信息(进程上下文)

每个进程启动时系统都会生成相关的环境表,获取里面的环境变量可使用下面函数

GetEnvironmentStrings FreeEnvironmentStrings 可以获得该环境表的首地址

SetEnvironmentVariable GetEnvironmentVariable 可以设置和得到环境变量的值

获取进程ID和进程句柄

GetCurrentProcessId 获取id

GetCurrentProcess 获得句柄,但是一个假句柄,值为-1,可正常使用

OpenProcess 通过id获得进程句柄,通常拿来获得别的进程的句柄,也可调用OpenProcess(GetCurrentProcessId)获得本进程真实句柄

创建和结束进程

BOOL CreateProcess(

LPCTSTR lpApplicationName,应用程序全路径名

LPTSTR lpCommandLine, // 命令行参数

LPSECURITY_ATTRIBUTES lpProcessAttributes, // 安全属性 设为NULL

LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程安全属性NULL

BOOL bInheritHandles, // 继承标识 NULL

DWORD dwCreationFlags, // 创建方式 给0立即启动

LPVOID lpEnvironment, // 设置环境信息 可为NULL

LPCTSTR lpCurrentDirectory, // 设置工作目录 可为NULL

LPSTARTUPINFO lpStartupInfo, // 保存起始信息 需放入结构体地址

LPPROCESS_INFORMATION lpProcessInformation // 创建的进程相关信息,需放入结构体地址

);

ExitProcess 可以结束当前进程

TerminateProcess 可以结束别的进程

CloseHandle 将句柄置为 -1,进程不结束

进程间的等候,即阻塞函数等待别的进程返回

DWORD WaitForSingleObject(

HANDLE hHandle, // 进程句柄

DWORD dwMilliseconds // 等待时间(INFINITE为无限长)

);

DWORD WaitForMultipleObjects(

DWORD nCount, // 句柄数量

CONST HANDLE *lpHandles, // 存放句柄的数组

BOOL fWaitAll, // 等候方式TRUE等待所有 FALSE任何一个

DWORD dwMilliseconds // 等待时间(INFINITE为无限长)

);

这两个等候的函数一个可以等待单个进程,一个可以等候多个,里头的HANDLE其实可以不光只是进程,也可以是线程,只要是带信号的句柄,这些句柄包括

Change notification

Console input 控制台输入

Event 事件

Job

Mutex 互斥

Process 进程

Semaphore 信号

Thread 线程

Waitable timer 可等候定时器



线程

进程如果对应电脑的内存,线程对应着电脑的CPU,线程也就是执行的代码的实例。
系统是以线程为单位调度程序。
线程的调度: 将CPU的执行时间划分成时间片,依次根据时间片执行不同的线程。


- 创建

HANDLE CreateThread(

LPSECURITY_ATTRIBUTES lpThreadAttributes, //安全属性

DWORD dwStackSize, // 线程栈大小为0向1M靠拢

LPTHREAD_START_ROUTINE lpStartAddress, // 线程处理函数

LPVOID lpParameter, // 处理函数参数

DWORD dwCreationFlags, //创建方式 挂起还是执行

LPDWORD lpThreadId // 接收的线程ID

);

- 结束 TerminateThread / ExitThread

结束后依旧需要调用CloseHandle释放句柄资源

- 挂起/执行 SuspendThread ResumeThread

- 线程信息 GetCurrentThreadId / GetCurrentThread

线程同步

线程同步技术是解决线程之间的资源竞争和线程之间的协调工作。

其中,原子锁、临界区(段)、互斥 是给线程间加锁,

原子锁

直接对一个数据的内存操作,任一时间只有一个线程访问该内存,可对这个数据进行增,减,改变数值

InterlockedIncrement, InterlockedExchange, InterlockedDecrement

临界区

可以锁定一段代码,防止多个线程同时使用该段代码

VOID InitializeCriticalSection(

LPCRITICAL_SECTION lpCriticalSection // 临界区结构体的地址

); //初始化一个临界区

VOID EnterCriticalSection(

LPCRITICAL_SECTION lpCriticalSection

); //进入临界区,放在要锁定的代码前

VOID LeaveCriticalSection(

LPCRITICAL_SECTION lpCriticalSection //

); //离开临界区,放在锁定的代码结尾

VOID DeleteCriticalSection(

LPCRITICAL_SECTION lpCriticalSection

); //释放临界区资源

互斥

用于多线程下代码或资源的共享使用

HANDLE CreateMutex(

LPSECURITY_ATTRIBUTES lpMutexAttributes,

// 安全属性

BOOL bInitialOwner, // 初始拥有着,TRUE立刻获得互斥锁

LPCTSTR lpName // 互斥名

); //返回互斥句柄

一个进程调用WaitForSingleObject时,如果持锁,则无需等待,否则等待持锁线程调用ReleaseMutext时立刻获得互斥锁

CloseHandle 可以释放互斥锁句柄资源,OpenMutex可以根据互斥名获得互斥锁句柄,也可以使用在两个进程间的通信。

注: 互斥和临界区的区别,

临界区 - 运行在用户态,执行效率高,只能在同一个进程中使用

互斥 - 运行在内核态,执行效率低,可以通过命名方式跨进程使用(配合内存映射文件)

事件

事件用于程序之间的通知的问题,是最常用的线程同步技术,事件句柄也分为有信号和无信号两种状态,无信号时会被WaitFor..函数等待,而SetEvent和ResetEvent可以手动设置事件句柄的信号状态

HANDLE CreateEvent(

LPSECURITY_ATTRIBUTES lpEventAttributes,

// 安全属性

BOOL bManualReset, // 手动还是自动复位

BOOL bInitialState, // 初始状态(有无信号)

LPCTSTR lpName // 事件名字

);

另一进程调用WaitFor..函数等待时间句柄变为有信号状态,如果是自动复位,会在调用结束后信号立马变成无信号状态,如果是手动,需要在调用结束后使用ResetEvent将信号置为无信号状态

不使用以后使用CloseHandle关闭事件句柄

信号量

类似于事件,解决通知的相关问题,可以提供一个计数器,设置信号有效的次数

HANDLE CreateSemaphore(

LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,

// 安全属性

LONG lInitialCount, // 初始计数值

LONG lMaximumCount, // 最大值

LPCTSTR lpName // 信号量名字

);

当一个线程调用WaitFor..函数会使信号量计数值减1,直到该值为0这个信号量会变为无信号状态。使用ReleaseSemaphore可以重置信号量的计数值。使用结束后依旧使用CloseHandle释放资源
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: