Critical_section(关键段)

本文介绍了Win32环境下进程与线程的基本概念、创建及终止方法,并详细讲解了进程信息结构、线程优先级设置以及如何利用Win32 API函数实现线程同步。

进程是一个可执行的程序,由私有虚拟地址空间、代码、数据和其他操作系统资源(如进程创建的文件、管道、同步对象等)组成。一个应用程序可以有一个或多个进程,一个进程可以有一个或多个线程,其中一个是主线程。

一个进程的所有线程共享它的虚拟地址空间、全局变量和操作系统资源。

1.Win32的进程处理简介

因为MFC没有提供类处理进程,所以直接使用了Win32 API函数。

  1.  

  2. 进程的创建

调用CreateProcess函数创建新的进程,运行指定的程序。CreateProcess的原型如下:

BOOL CreateProcess(

LPCTSTR lpApplicationName,

LPTSTR lpCommandLine,

LPSECURITY_ATTRIBUTES lpProcessAttributes,

LPSECURITY_ATTRIBUTES lpThreadAttributes,

BOOL bInheritHandles,

DWORD dwCreationFlags,

LPVOID lpEnvironment,

LPCTSTR lpCurrentDirectory,

LPSTARTUPINFO lpStartupInfo,

LPPROCESS_INFORMATION lpProcessInformation

);

其中:

lpApplicationName指向包含了要运行模块名字的字符串。

lpCommandLine指向命令行字符串。

lpProcessAttributes描述进程的安全性属性,NT下有用。

lpThreadAttributes描述进程初始线程(主线程)的安全性属性,NT下有用。

bInHeritHandles表示子进程(被创建的进程)是否可以继承父进程的句柄。可以继承的句柄有线程句柄、有名或无名管道、互斥对象、事件、信号量、映像文件、普通文件和通讯端口等;还有一些句柄不能被继承,如内存句柄、DLL实例句柄、GDI句柄、URER句柄等等。

子进程继承的句柄由父进程通过命令行方式或者进程间通讯(IPC)方式由父进程传递给它。

dwCreationFlags表示创建进程的优先级类别和进程的类型。创建进程的类型分控制台进程、调试进程等;优先级类别用来控制进程的优先级别,分Idle、Normal、High、Real_time四个类别。

lpEnviroment指向环境变量块,环境变量可以被子进程继承。

lpCurrentDirectory指向表示当前目录的字符串,当前目录可以继承。

lpStartupInfo指向StartupInfo结构,控制进程的主窗口的出现方式。

lpProcessInformation指向PROCESS_INFORMATION结构,用来存储返回的进程信息。

从其参数可以看出创建一个新的进程需要指定什么信息。

从上面的解释可以看出,一个进程包含了很多信息。若进程创建成功的话,返回一个进程信息结构类型的指针。进程信息结构如下:

typedef struct _PROCESS_INFORMATION {

HANDLE hProcess;

HANDLE hThread;

DWORD dwProcessId;

DWORD dwThreadId;

}PROCESS_INFORMATION;

进程信息结构包括进程句柄,主线程句柄,进程ID,主线程ID。

 

  • 进程的终止

     

    进程在以下情况下终止:

    •  

    • 调用ExitProcess结束进程;

       

       

    • 进程的主线程返回,隐含地调用ExitProcess导致进程结束;

       

       

    • 进程的最后一个线程终止;

       

       

    • 调用TerminateProcess终止进程。

       

       

    • 当要结束一个GDI进程时,发送WM_QUIT消息给主窗口,当然也可以从它的任一线程调用ExitProcess。

       

    1.  
      1.  

      2. Win32的线程

         

        1.  

        2. 线程的创建

    使用CreateThread函数创建线程,CreateThread的原型如下:

    HANDLE CreateThread(

    LPSECURITY_ATTRIBUTES lpThreadAttributes,

    DWORD dwStackSize,

    LPTHREAD_START_ROUTINE lpStartAddress,

    LPVOID lpParameter,

    DWORD dwCreationFlags, // creation flags

    LPDWORD lpThreadId

    );

    其中:

    lpThreadAttributes表示创建线程的安全属性,NT下有用。

    dwStackSize指定线程栈的尺寸,如果为0则与进程主线程栈相同。

    lpStartAddress指定线程开始运行的地址。

    lpParameter表示传递给线程的32位的参数。

    dwCreateFlages表示是否创建后挂起线程(取值CREATE_SUSPEND),挂起后调用ResumeThread继续执行。

    lpThreadId用来存放返回的线程ID。

     

    •  

    • 线程的优先级别

       

    进程的每个优先级类包含了五个线程的优先级水平。在进程的优先级类确定之后,可以改变线程的优先级水平。用SetPriorityClass设置进程优先级类,用SetThreadPriority设置线程优先级水平。

    Normal级的线程可以被除了Idle级以外的任意线程抢占。

    1.  
      1.  
        1.  

        2. 线程的终止

           

    以下情况终止一个线程:

    •  

    • 调用了ExitThread函数;

       

       

    • 线程函数返回:主线程返回导致ExitProcess被调用,其他线程返回导致ExitThread被调用;

       

       

    • 调用ExitProcess导致进程的所有线程终止;

       

       

    • 调用TerminateThread终止一个线程;

       

       

    • 调用TerminateProcess终止一个进程时,导致其所有线程的终止。

       

    当用TerminateProcess或者TerminateThread终止进程或线程时,DLL的入口函数DllMain不会被执行(如果有DLL的话)。

    1.  
      1.  

      2. 线程同步

         

        同步可以保证在一个时间内只有一个线程对某个资源(如操作系统资源等共享资源)有控制权。共享资源包括全局变量、公共数据成员或者句柄等。同步还可以使得有关联交互作用的代码按一定的顺序执行。

        Win32提供了一组对象用来实现多线程的同步。

        这些对象有两种状态:获得信号(Signaled)或者没有或则信号(Not signaled)。线程通过Win32 API提供的同步等待函数(Wait functions)来使用同步对象。一个同步对象在同步等待函数调用时被指定,调用同步函数地线程被阻塞(blocked),直到同步对象获得信号。被阻塞的线程不占用CPU时间。

        1.  

        2. 同步对象

           

    同步对象有:Critical_section(关键段),Event(事件),Mutex(互斥对象),Semaphores(信号量)。

    下面,解释怎么使用这些同步对象。

    1.  

    2. 关键段对象:

       

      首先,定义一个关键段对象cs:

      CRITICAL_SECTION cs;

      然后,初始化该对象。初始化时把对象设置为NOT_SINGALED,表示允许线程使用资源:

      InitializeCriticalSection(&cs);

      如果一段程序代码需要对某个资源进行同步保护,则这是一段关键段代码。在进入该关键段代码前调用EnterCriticalSection函数,这样,其他线程都不能执行该段代码,若它们试图执行就会被阻塞。

      完成关键段的执行之后,调用LeaveCriticalSection函数,其他的线程就可以继续执行该段代码。如果该函数不被调用,则其他线程将无限期的等待。

       

    3. 事件对象

       

      首先,调用CreateEvent函数创建一个事件对象,该函数返回一个事件句柄。然后,可以设置(SetEvent)或者复位(ResetEvent)一个事件对象,也可以发一个事件脉冲(PlusEvent),即设置一个事件对象,然后复位它。复位有两种形式:自动复位和人工复位。在创建事件对象时指定复位形式。。

      自动复位:当对象获得信号后,就释放下一个可用线程(优先级别最高的线程;如果优先级别相同,则等待队列中的第一个线程被释放)。

      人工复位:当对象获得信号后,就释放所有可利用线程。

      最后,使用CloseHandle销毁创建的事件对象。

       

    4. 互斥对象

       

      首先,调用CreateMutex创建互斥对象;然后,调用等待函数,可以的话利用关键资源;最后,调用RealseMutex释放互斥对象。

      互斥对象可以在进程间使用,但关键段对象只能用于同一进程的线程之间。

       

    5. 信号量对象

       

      在Win32中,信号量的数值变为0时给以信号。在有多个资源需要管理时可以使用信号量对象。

      首先,调用CreateSemaphore创建一个信号量;然后,调用等待函数,如果允许的话,则利用关键资源;最后,调用RealeaseSemaphore释放信号量对象。

       

    6. 此外,还有其他句柄可以用来同步线程:

       

    文件句柄(FILE HANDLES)

    命名管道句柄(NAMED PIPE HANDELS)

    控制台输入缓冲区句柄(CONSOLE INPUT BUFFER HANDLES)

    通讯设备句柄(COMMUNICTION DEVICE HANDLES)

    进程句柄(PROCESS HANDLES)

    线程句柄(THREAD HANDLES

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值