摘要: 在系统中,对象分两类:核心对象和用户对象。如进程对象,线程对象,文件映射对象等就是核心对象;而向窗口,菜单等都是用户对象。两者的差别是:用户对象的句柄是系统唯一的。一个进程完全可以对另外一个进程中的用户对象进行操作。比如两个进程间通信的方法之一就是发送消息。正是由于窗口是用户对象,所以句柄是系统唯一,通过FindWindow(),得到另外一个进程的窗口句柄,然后用SendMessage(),让hWnd的窗口过程来处理消息,实现了进程间的通信。因此,对于用户对象,可以直接把句柄拿来用就行了。核心对象需要考虑系统的稳定性,因此,核心对象句柄是进程相关的。在每一个进程中都有一个核心对象表,每一个对象 阅读全文
posted @ 2011-01-05 21:22 xyecho 阅读(931) 评论(0) 推荐(0) 编辑
摘要: 互斥对象(mutex)内核对象能够确保线程拥有对单个资源的互斥访问权。互斥对象包含一个使用数量,一个线程ID和一个递归计数器。互斥对象的行为特性与关键代码段相同,但是互斥对象属于内核对象,而关键代码段则属于用户方式对象。这意味着互斥对象的运行速度比关键代码段要慢。但是这也意味着不同进程中的多个线程能够访问单个互斥对象,并且这意味着线程在等待访问资源时可以设定一个超时值。 ID用于标识系统中的哪个线程当前拥有互斥对象,递归计数器用于指明该线程拥有互斥对 象的次数。作用:通常来说,它们用于保护由多个线程访问的内存块。如果多个线程要同时访问内存块,内存块中的数据就可能遭到破坏。互斥对象能够保证访问内 阅读全文
posted @ 2011-01-05 21:13 xyecho 阅读(528) 评论(0) 推荐(0) 编辑
摘要: 信标内核对象用于对资源进行计数。它们与所有内核对象一样,包含一个使用数量,但是它们也包含另外两个带符号的3 2位值。一个是最大资源数量,用于标识信标能够控制的资源的最大数量。一个是当前资源数量,用于标识当前可以使用的资源的数量。(FangSH注:有些书称之为信息量内核对象)为了正确地说明这个问题,让我们来看一看应用程序是如何使用信标的。比如说,我正在开发一个服务器进程,在这个进程中,我已经分配了一个能够用来存放客户机请求的缓冲区。我对缓冲区的大小进行了硬编码,这样它每次最多能够存放5个客户机请求。如果5个请求尚未处理完毕时,一个新客户机试图与服务器进行联系,那么这个新客户机的请求就会被拒绝,并 阅读全文
posted @ 2011-01-05 20:48 xyecho 阅读(764) 评论(0) 推荐(0) 编辑
摘要: 等待定时器是在某个时间或按规定的间隔时间,发出自己的信号通知的内核对象。它们通常用来在某个时间执行某个操作。(程序可以定时地做一些工作,而不需要人参与进去。比如每天定时地升级病毒库,定时地下载电影,定时地更新游戏里的人物。要想实现这些功能,就可以使用定时器的API函数CreateWaitableTimer和SetWaitableTimer来实现了,这对API函数创建的时钟是比较精确的,可以达到100倍的10亿分之一秒。)若要创建等待定时器,只需要调用CreateWaitableTimer函数: [代码]与事件的情况一样,fManualReset参数用于指明人工重置的定时器或自动重置的定时器。当 阅读全文
posted @ 2011-01-05 20:36 xyecho 阅读(712) 评论(0) 推荐(0) 编辑
摘要: 在所有的内核对象中,事件内核对象是个最基本的对象。它们包含一个使用计数(与所有内核对象一样),一个用于指明该事件是个自动重置的事件还是一个人工重置的事件的布尔值,另一个用于指明该事件处于已通知状态还是未通知状态的布尔值。事件能够通知一个操作已经完成。有两种不同类型的事件对象。一种是人工重置的事件,另一种是自动重置的事件。当人工重置的事件得到通知时,等待该事件的所有线程均变为可调度线程。当一个自动重置的事件得到通知时,等待该事件的线程中只有一个线程变为可调度线程。当一个线程执行初始化操作,然后通知另一个线程执行剩余的操作时,事件使用得最多。事件初始化为未通知状态,然后,当该线程完成它的初始化操作 阅读全文
posted @ 2011-01-05 17:37 xyecho 阅读(663) 评论(0) 推荐(0) 编辑
摘要: 对于有些内核对象来说,成功地调用WaitForSingleObject和WaitForMultipleObjects,实际上会改变对象的状态。成功地调用是指函数发现对象已经得到通知并且返回一个相对于WA I T _O BJECT_ 0的值。如果函数返回WAIT_TIMEOUT或WAIT_FAILED,那么调用就没有成功。如果函数调用没有成功,对象的状态就不可能改变。当一个对象的状态改变时,我称之为成功等待的副作用。例如,有一个线程正在等待自动清除事件对象。当事件对象变为已通知状态时,函数就会发现这个情况,并将WAIT_OBJECT_0返回给调用线程。但是就在函数返回之前,该事件将被置为未通知状 阅读全文
posted @ 2011-01-05 17:11 xyecho 阅读(471) 评论(0) 推荐(0) 编辑
摘要: 两个等待函数 一个单线程,一个多线程。等待函数可使线程自愿进入等待状态,直到一个特定的内核对象变为已通知状态为止。(FangSH注:如果内核对象没有变为通知即线程永远等待下去。)这些等待函数中最常用的是WaitForSingleObject :[代码]第一个参数hObject标识一个能够支持被通知/未通知的内核对象(前面列出的任何一种对象都适用)。(FangSH注:句柄)第二个参数dwMilliseconds指明等待对象变为已通知状态所需的等待时间。(时间间隔以毫秒为单位,INFINITE表示直到等到hHandle为已通知状态)。传递INFINITE有些危险。如果对象永远不变为已通知状态,那么 阅读全文
posted @ 2011-01-05 16:48 xyecho 阅读(1281) 评论(1) 推荐(0) 编辑
摘要: [代码]说明 :1 用法:用类定义一个对象, 然后调用函数。 如下:CritSect sect;Lock lock(sect);或CLock t;CSCopedLocker st(&t);2 但是,感觉这两种方法用的时候不是最安全的。具体的可以看一下《Effective C++》里面的条款13: 以对象管理资源。里面讲更好些。FangSH15:44 2011-1-5 阅读全文
posted @ 2011-01-05 15:45 xyecho 阅读(626) 评论(0) 推荐(0) 编辑
摘要: 可以从例子学习,更好的掌握[代码]应该注意的:1 关键代码段(临界区)工作在用 用户方式下2 关键代码段(临界区)是指一个小代码段,在代码够执行前。它必须独占对某些资源的访问权。3 关键代码段是工作在用户方式下。同步速度较快,但在使用关键代码段时,很容易进入死锁状态。因为在等待进入关键代码段时无法设定超时值。4 线程死锁线程1拥有了临界区对象A。等待临界区对象B的拥有权。线程2拥有了临界区对象B,等待临界区对象A的拥有权,就造成了死锁。5 无法用它们对多个进程中的各个线程进行同步以下的例子就是进入了死锁。[代码] 阅读全文
posted @ 2011-01-05 15:28 xyecho 阅读(449) 评论(0) 推荐(0) 编辑
摘要: 线程需要在下面两种情况下互相进行通信:•当有多个线程访问共享资源而不使资源被破坏时。•当一个线程需要将某个任务已经完成的情况通知另外一个或多个线程时。所谓原子访问,是指线程在访问资源时能够确保所有其他线程都不在同一时间内访问相同的资源。以InterLocked开始的函数都是户数函数。使用互锁函数的优点是:他的速度要比其他的CriticalSection,Mutex,Event,Semaphore快很多。调用一个互锁函数通常会导致执行几个CPU周期(通常小于50),并且不会从用户方式转换为内核方式(通常这需要执行1000个CPU周期)。可以查看msdn(http://msdn2.microsof 阅读全文
posted @ 2011-01-05 15:21 xyecho 阅读(507) 评论(0) 推荐(0) 编辑
摘要: 线程运行时,常常想要调用windows函数来改变它们的运行环境。例如,线程可能 想要改变它的优先级或它的进程的的优先级。线程常常要改变它的(或它进程的)环境,所以Windows提供一些函数,使得线程能够容易地引用它的进程内核对象。或者用它的线程内核对象 :(FangSH:获得当前的线程和进程的函数)[代码]1、这两个函数都能返回调用线程的进程的伪句柄或线程内核对象的伪句柄。这些函数并不在创建进程的句柄表中创建新句柄。2、调用这些函数对进程或线程内核对象的使用计数没有任何影响。3、如果调用CloseHandle,将伪句柄作为参数来传递,那么CloseHandle就会忽略该函数的调用并返回FALS 阅读全文
posted @ 2011-01-05 15:12 xyecho 阅读(635) 评论(0) 推荐(0) 编辑
摘要: 调用CreateThread可使系统创建一个线程内核对象。该对象的初始使用计数是2(在线程停止运行和从CreateThread返回的句柄关闭之前,线程内核对象不会被撤消)。线程的内核对象的其他属性也被初始化,挂起计数(suspend count)被设置为1,退出代码始终为STILL_ACTIVE(0x103),该对象设置为未通知状态。内核对象一旦创建完成,系统就分配用于线程栈有内存。该内存是从进程的地址空间分配而来的,因为线程并不拥有它自己的地址空间。然后,系统将两个值写入新线程的栈的上端(线程栈总是从内存的高地址向低地址建立)。写入栈的第一个值是传递给CreateThread的pvParam 阅读全文
posted @ 2011-01-05 14:50 xyecho 阅读(429) 评论(0) 推荐(0) 编辑
摘要: 系统提供了一个称为SwitchToThread的函数,使得另一个可调度线程(如果存在能够运行):BOOL SwitchToThread();当调用这个函数的时候,系统要查看是否存在一个迫切需要CPU时间的线程。如果没有线程迫切需要CPU时间,SwitchToThread就会立即返回。如果存在一个迫切需要CPU时间的线程,SwitchToThread就对该线程进行调度(该线程的优先级可能低于调用SwitchToThread的线程)。这个迫切需要CPU时间的线程可以运行一个时间段,然后系统调度程序照常运行。该函数允许一个需要资源的线程强制另一个优先级较低、而目前却拥有该资源的线程放弃该资源(抢占资 阅读全文
posted @ 2011-01-05 14:36 xyecho 阅读(3325) 评论(0) 推荐(0) 编辑
摘要: 线程也能告诉系统,它不想在某个时间段内被调度。这是通过调用Sleep函数来实现的:VOID Sleep(DWORDdwMilliseconds);该函数可使线程暂停自己的运行,直到dwMilliseconds过去为止。关于Sleep函数。有下面几个重要问题值得注意:1、调用Sleep,可使线程自愿放弃它剩余的时间片。2、系统将在大约的指定毫秒数内使线程不可调度。如果告诉系统,想睡眠100ms,那么可以睡眠大约这么长时间,但是也可能睡眠数秒钟或者数分钟。记住, Windows不是个实时操作系统。虽然线程可能在规定的时间被唤醒,但是它能否做到,取决于系统中还有什么操作正在进行。3、可以调用Slee 阅读全文
posted @ 2011-01-05 14:32 xyecho 阅读(1603) 评论(0) 推荐(0) 编辑
摘要: 在线程内核对象的内部有一个用于指明线程的挂起计数的值。当调用CreateProcess或CreateThread函数时,就创建了线程的内核对象,并且它的挂起计数被初始化为1。这可以防止线程被调度到CPU中。原因是因为线程的初始化需要时间,希望在系统做好充分的准备之后再开始执行线程。当线程完全初始化好了之后, CreateProcess或CreateThread要查看是否已经传递了CRE ATE_ SUSPENDED标志。如果已经传递了这个标志,那么这些函数就返回,同时新线程处于挂起状态。如果尚未传递该标志,那么该函数将线程的暂停计数递减为0。当线程的暂停计数是0的时候,除非线程正在等待其他某种 阅读全文
posted @ 2011-01-05 14:27 xyecho 阅读(6317) 评论(0) 推荐(0) 编辑
摘要: [代码]说明: 此函数调用成功返回TRUE,失败返回FALSE,只表示这个函数是否调用成功而己.不能根据返回值来判断一个线程是否结束,而重点是要根据lpExitCode的值来确定,lpExitCode 值STILL_ACTIVE 表示线程正在运行.若线程己经结束,则lpExitCode中存储指定线程的返回值.FangSH2011-01-05 阅读全文
posted @ 2011-01-05 14:18 xyecho 阅读(2349) 评论(0) 推荐(0) 编辑
摘要: 之所以写成宏定义。是因为觉得每一次对参值进行类型转换很麻烦。[代码]unsignedlong _beginthreadex( void *security, unsigned stack_size, unsigned ( __stdcall*start_address )( void * ), void *arglist, unsigned initflag, unsigned*thrdaddr );//第1个参数:安全属性,NULL为默认安全属性//第2个参数:指定线程堆栈的大小。如果为0,则线程堆栈大小和创建它的线程的相同。一般用0//第3个参数:指定线程函数的地址,也就是线程调用执行的函 阅读全文
posted @ 2011-01-05 14:10 xyecho 阅读(396) 评论(0) 推荐(0) 编辑
摘要: 进程是由两部分构成的 一个是进程对象,一个是地址空间。线程也有两个部分组成: 一个是线程的内核对象,一个线程栈。进程是不活泼的,进程从来不所选任何东西,它只是线程依存的地方。线程在它的进程空间执行代码。并在进程的地址空间中对操作。CreateThread函数 (是用来创建线程的Windows函数。不过,如果你正在编写C/C++代码,决不应该调用CreateThread。相反,应该使用VisualC++运行期库函数_beginthreadex)[代码]参数说明:psa 指向SECURITY_ATTRIBUTES结构的指针。传递NULL,为线程的内核对象的默认属性。设定为SECURITY_ATTR 阅读全文
posted @ 2011-01-05 14:02 xyecho 阅读(421) 评论(0) 推荐(0) 编辑