关于Windows的进程处理(一)

  在Windows的多线程编程中,建立线程的函数主要有CreateThread和_beginthread(及_beginthreadex)。编程

  • CreateThread 和 ExitThread

  使用API函数CreateThread建立线程时,其中的线程函数原型:安全

HANDLE WINAPI CreateThread(
  _In_opt_  LPSECURITY_ATTRIBUTES  lpThreadAttributes,
  _In_      SIZE_T                 dwStackSize,
  _In_      LPTHREAD_START_ROUTINE lpStartAddress,
  _In_opt_  LPVOID                 lpParameter,
  _In_      DWORD                  dwCreationFlags,
  _Out_opt_ LPDWORD                lpThreadId
);

   当线程函数的起始地址无效(或者不可访问)时,CreateThread函数仍可能成功返回。若是该起始地址无效,则当线程运行时,异常将发生,线程终止。并返回一个错误代码。  在线程函数返回后,其返回值用做调用ExitThread函数的参数(由系统隐式调用)。可使用GetExitCodeThread函数得到该线程函数的返回值。服务器

  使用CreateThread建立的线程具备THREAD_PRIORITY_NORMAL的线程优先级。可使用GetThreadPriority和SetThreadPriority函数获取和设置线程优先级值。
  系统中的线程对象一直存活到线程结束,而且全部指向它的句柄都经过调用CloseHandle关闭后。多线程

  •  _beginthread 和 _endthread(_beginthreadex 和 _endthreadex)

  对于使用C运行时库里的函数的线程应该使用_beginthread和_endthread这些C运行时函数来管理线程,而不是使用CreateThread和ExitThread。不然,当调用ExitThread后,可能引起内存泄露。函数

uintptr_t _beginthread( // NATIVE CODE  
   void( __cdecl *start_address )( void * ),  
   unsigned stack_size,  
   void *arglist   
);  
uintptr_t _beginthread( // MANAGED CODE  
   void( __clrcall *start_address )( void * ),  
   unsigned stack_size,  
   void *arglist   
);  
uintptr_t _beginthreadex( // NATIVE CODE  
   void *security,  
   unsigned stack_size,  
   unsigned ( __stdcall *start_address )( void * ),  
   void *arglist,  
   unsigned initflag,  
   unsigned *thrdaddr   
);  
uintptr_t _beginthreadex( // MANAGED CODE  
   void *security,  
   unsigned stack_size,  
   unsigned ( __clrcall *start_address )( void * ),  
   void *arglist,  
   unsigned initflag,  
   unsigned *thrdaddr   
);

  在使用_beginthread或者_beginthreadex建立线程时,应该包含头文件<process.h>,而且须要设置多线程版 本的运行时库。「Project Settings」--> 「C/C++」-->「Category」-->「Code Generation」-->「Use Run-Time Library」-->「Multithreaded」和「Debug Multithreaded」。这至关于给编译添加了一个编译选项/MT,使编译器在编译时在.obj文件中使用libcmt.lib文件名而不是 libc.lib。链接器使用这个名字与运行时库函数链接。
  能够调用_endthread和_endthreadex显示式结束一个线程。然而,当线程函数返回时,_endthread和_endthreadex 被自动调用。endthread和_endthreadex的调用有助于确保分配给线程的资源的合理回收。_endthread自动地关闭线程句柄,然而 _endthreadex却不会。所以,当使用_beginthread和_endthread时,不须要显示调用API函数CloseHandle式关 闭线程句柄。该行为有别于API函数ExitThread的调用。_endthread和_endthreadex回收分配的线程资源后,调用 ExitThread。
   当_beginthread和_beginthreadex被调用时,操做系统本身处理线程栈的分配。若是在调用这些函数时,指定栈大小为0,则操做系统 为该线程建立和主线程大小同样的栈。若是任何一个线程调用了abort、exit或者ExitProcess,则全部线程都将被终止。ui

  • 小结

CreateThread、_beginthread和_beginthreadex都是用来启动线程的,_beginthread是_beginthreadex的功能子集,虽然_beginthread内部是调用_beginthreadex但他屏蔽了象安全特性这样的功能,因此_beginthread与CreateThread不是同等级别,_beginthreadex和CreateThread在功能上彻底可替代,这两个函数一个是运行时库函数(C Run-Time Library Reference),一个是WIN32 的库函数(Process and Thread Reference),CRT(C Run-Time)包含了像malloc(), fopen(), _open(), strtok(), ctime(), 或localtime()等函数须要专门的线程局部存储的数据块,这个数据块一般须要在建立线程的时候就创建,若是使用CreateThread,这个数据块就没有创建,而后会怎样呢?在这样的线程中仍是可使用这些函数并且没有出错,实际上函数发现这个数据块的指针为空时,会本身创建一个,而后将其与线程联系在一块儿,这意味着若是你用CreateThread来建立线程,而后使用这样的函数,会有一块内存在不知不觉中建立,遗憾的是,这些函数并不将其删除,而CreateThread和ExitThread也没法知道这件事,因而就会有Memory Leak,在线程频繁启动的软件中(好比某些服务器软件),早晚会让系统的内存资源耗尽!操作系统

相关文章
相关标签/搜索