第六章线程的基础知识

2017-09-15  本文已影响0人  常春藤上的蜗牛

6.3编写第一个线程函数

针对线程函数的几点说明:

6.4CreateThread函数

HANDLE CreateThread(
    PSECURITY_ATTRIBUTES psa,
    DWORD cbStack,
    PTHREAD_START_ROUTINE pfnStarAddr,
    PVOID pvParam,
    DWORD fdwCreate,
    PDWORD pdwThreadID );

当CreateThread被调用时,系统创建一个线程内核对象。该线程内核对象不是线程本身,而是操作系统用来管理线程的较小的数据结构。

CreateThread的各个参数

typedef struct _SECURITY_ATTRIBUTES {
 DWORD  nLength;   //结构大小,可用sizeof取得
 LPVOID lpSecurityDescriptor; //指向一个对象的安全描述符 该安全描述符控制对象的共享 如果为NULL,则该对象使用调用进程的默认安全描述符 
 BOOL   bInheritHandle; //安全描述的对象能否被新创建的进程继承返回句柄 若为TRUE 则新进程继承该句柄
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;

安全描述符相关介绍

6.5终止线程的运行

一、终止线程的方法:

VOID EixtThread(DWORD dwExitCode);

该函数将终止线程的运行,并导致操作系统清除该线程使用的所有操作系统资源。但是,C++资源(如C++类对象)将不被撤消。可以使用 EXitThread的得ExitThread参数告诉系统将线程的退出代码设置为什么。

BOOL TerminateThread(HANDLE hThread,
  DWORD dwExitCode);

ExitThread总是撤消调用的线程, 而TerminateThread能够撤消任何线程。
hThread参数用于标识被终止运行的线程的句柄当线程终止运行时,它的退出代码成为你作为dwExitCode参数传递的值。同时,线程的内核对象的使用计数也被递减。
需要注意的地方:
1)Terminate函数是一部运行的函数,即它告诉系统说你想要线程终止运行,但是,当函数返回时,不能保证线程被撤销。
2)当使用返回或调用ExitThread的方法撤消线程时,该线程的内存堆栈也被撤消。但是,如果使用TerminateThread,那么在拥有线程的进程终止运行之前,系统不撤消该线程的堆栈。

二、线程终止运行时发生的操作

BOOL GetExitCodeThread(
    HANDLE hThread,
    PDWORD pdwExitCode);

退出代码的值在pdwExitCode指向的DWORD中返回。如果调用GetExitCodeThread时线程
尚未终止运行,该函数就用 STILL_ACTIVE标识符(定义为 0x103)填入DWORD。如果该函
数运行成功,便返回TRUE。

6.6线程的一些性质


每个线程都有它自己的一组CPU寄存器,称为线程的上下文。该上下文反映了线程上次运
行时该线程的CPU寄存器的状态。CPU寄存器保存在一个CONTEXT结构中,CONTEXT结构本身则包含在线程的内核对象中。
下面是BaseThreadStart函数执行的基本操作:
VOID BaseThreadStart(PTHREAD_START_ROUTINE
 pfnStartAddr, PVOID pvParam)
{
  __try {
    ExitThread((pfnStartAddr)(pvParam));
  }
  __except(UnhandExceptionFilter(GetExceptionInformation())){
    ExitProcess(GetExceptionCode());
  }
}

由于新线程的指令指针被置为BaseThreadStart,因此该函数实际上是线程开始执行的地方。
当执行BaseThreadStart函数时,将出现如下情况:

6.7 C/C++运行期库的考虑

若要创建一个新线程,绝对不要调用操作系统的CreateThread函数,必须调用C/C++运行期库函数_beginthreadex:

unsigned long _beginthreadex(
    void *securtiy,
    unsigned stack_size;
    unsigned (*start_adderss)(void*),
    void *arglist,
    unsigned initflag,
    unsigned *thrdaddr);

_beginthreadex函数的参数列表与CreateThread函数的参数列表是相同的,但是参数名和类型并不完全相同。
**_beginthreadex的一些要点:

关于_threadstartex的一些重点:

6.8 对自己的ID概念有所了解

HANDLE GetCurrentProcess();
HANDLE GetCurrentThread();
这个两个函数返回调用线程的进程的伪句柄或线程内核对象的伪句柄。
DWORD GetCurrentProcessId();
DWORD GetCurrentThreadId();
利用函数DuplicateHandle伪句柄转化为实句柄

BOOL DuplicateHandle(
  HANDLE hSourceProcess,
  HANDLE hSource,
  HANDLE hTargetProcess,
  PHANDLE  phTarget,
  DWORD fdwAcess,
  BOOL bInheritHandle,
  DWORD fdwOptions);
上一篇 下一篇

猜你喜欢

热点阅读