win32程序的执行单元

win32程序的执行单元

代码的执行单元 ---- 线程

CreateProcess函数创建了进程,同时也创建了进程的主线程。系统中的每个进程都至少有一个线程。

多线程

创建新的线程函数:CreateThread()

等待线程运行结束:WaitForSingleObject(), 该函数用于等待指定对象变成受信状态。

一个可执行对象有两种状态:未受信受信状态。线程对象只有当线程运行结束时才达到未受信状态。

线程内核对象:

每一次CreateThread函数的成功调用,系统都会在内部为新的线程分配一个内核对象。系统提供的管理线程的函数其实就是依靠访问

线程内核对象来实现管理的。包含以下几个基本成员:

1.CONTEXT(上下文, 即寄存器的状态):反应线程上次运行时CPU寄存器的状态。

2.Usage Count 使用计数:只要线程没有结束运行,Usage Count的值至少为1。创建一个新的线程后,初始状态下Usage Count的值

是2。每打开一次该内核对象,计数值就加1。

3.Suspend Count 暂停计数:初始化为1(暂停状态), 这可以阻止新创建的线程被调度到CPU中,当线程的暂停计数是0的时候,该线

程就处于可调度的状态。 单个线程可以被暂停若干次,如果一个线程被暂停了3次,它必须被唤醒3次才可以分配给一个CPU。

唤醒线程:ResumeThread(HANDLE hThread) 可以唤醒一个挂起的线程, 减少计数

暂停线程:SuspendThread(HANDLE hThread)  可以挂起一个线程, 增加计数

4.Exit Code 退出代码:指定了线程的退出代码,也可以说是线程函数的返回值。在线程运行期间,线程函数还没有返回,Exit Code

的值是STILL_ACTIVE。线程运行结束后,系统自动将Exit Code设为线程函数的返回值。GetExitCodeThread()函数得到线程的退出代

码。

5.Signaled 是否受信:线程运行期间,一直是未受信状态,只有当线程结束后,系统才把Signaled的值设为TRUE,即受信状态。、

线程的终止  最后的方法是让线程函数自然返回

使用ExitThread函数:终止当前线程的运行,促使系统释放掉所有此线程使用的资源,但是,C/C++资源却得不到正确的清除。

使用TerminateThread函数:在一个线程中强制终止另一个线程的执行。但是,系统不会释放线程使用的堆栈。

线程同步

同步可以保证一个时间内只有一个线程对某个共享资源有控制权。

共享资源:包括全局变量、公共数据成员、句柄等。

1.临界区对象:

临界区对象是定义在数据段中的一个CRITICAL_SECTION结构,windows内部使用这个结构记录一些信息,确保在同一时间只有一

线程访问该数据段中的数据。

初始化:InitialzeCriticalSection()

进入:EnterCriticalSection()

退出:LeaveCriticalSection()

删除:DeleteCriticalSection()

2.互锁函数:

互锁函数为同步访问多线程共享变量提供了一个简单的机制。

InterlockedIncrement():递增变量

InterlockedDecrement():递减变量

3.事件内核对象:

事件对象(event)是一种抽象的对象,它也有未受信和受信两种状态,不同于其他内核对象的是,一下函数可以使事件内核对象在这

两种状态之间转化。事件对象主要用于线程间通信,因为它是一个内核对象,所以也可以跨进程使用。

创建事件对象:CreateEvent()

4.信号量内核对象:

信号量(Semaphore)内核对象允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程的数目。

信号量的使用特点使其更适用于对Socket程序中线程的同步。

5.互斥内核对象:Mutex

只有拥有互斥内核对象的线程才具有访问资源的权限。与其它几种内核对象不同,互斥对象在操作系统中拥有特殊代码,并由操作

系统来管理,操作系统甚至还允许其进行一些其它内核对象不能进行的非常规操作。

6.线程局部存储(TLS: Thread Local Storage):

全局变量与函数内定义的静态变量是各个函数都可以访问的共享变量,如果需要一个在线程内部的各个函数都可以访问,但其它线

程不能访问的变量(被称为线程局部静态变量),这时就需要TLS。

线程局部存储在不同的平台有不同的实现,可移植性不太好,幸好实现线程局部存储并不难,最简单的方法就是建立一个全局表,

通过当前线程ID去查询相应的数据,因为各个线程的ID不同,查询的数据自然也就不同。

windows中如何实现线程局部存储:

windows系统采用了每个线程建线程专享的索引表,表的条目是线程局部存储的地址。windows仅为系统中的每一个进程维护一个

数组,再为该进程中的每一个线程申请一个同样长度的数组空间。

进程中的线程局部存储位数组,指示了本进程的线程数组中哪一个成员在使用中。

动态使用TLS的步骤:

(1).主线程调用TlsAlloc函数为线程局部存储分配索引:

函数原型:DWORD TlsAlloc(void); 返回一个TLS索引;

(2).每个线程调用TlsSetValue和TlsGetValue设置或读取线程数组中的值:

(3).主线程调用TlsFree释放局部存储索引:该函数唯一的参数是TlsAlloc返回的索引。

发布了37 篇原创文章 · 获赞 16 · 访问量 7万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章