继续上一篇,这篇来对比事件在win32和Linux下的区别.
在 Windows 中,事件对象是那些需要使用 SetEvent() 函数显式地将其状态设置为有信号状态的同步对象.事件对象来源有两种类型:
- 在 手工重置事件(manual reset event) 中,对象的状态会一直维持为有信号状态,直到使用
ResetEvent() 函数显式地重新设置它为止.
- 在 自动重置事件(auto reset event) 中,对象的状态会一直维持为有信号状态,直到单个正在等待的线程被释放为止.当正在等待的线程被释放时,其状态就被设置为无信号的状态.
事件对象有两种状态,有信号(signaled)状态 和 无信号(non-signaled)状态.对事件对象调用的等待函数会阻塞调用线程,直到其状态被设置为有信号状态为止.
在进行平台的迁移时,需要考虑以下问题:
- Windows 提供了 有名(named) 和 无名(un-named) 的事件对象.有名事件对象用来在进程之间进行同步,而在 Linux 中, pthreads 和 POSIX 都提供了线程间的同步功能.为了在 Linux 实现与 Windows 中有名事件对象相同的功能,可以使用 System V 信号量或信号.
- Windows 提供了两种类型的事件对象 —— 手工重置对象和自动重置对象.Linux 只提供了自动重置事件的特性.
- 在 Windows 中,事件对象的初始状态被设置为有信号状态.在 Linux 中,pthreads 并没有提供初始状态,而 POSIX 信号量则提供了一个初始状态.
- Windows 事件对象是异步的.在 Linux 中,POSIX 信号量和 System V 信号量也都是异步的,不过 pthreads 条件变量不是异步的.
- 当在一个等待函数中使用事件对象时,可以指定 Windows 的事件对象的超时时间值.在 Linux 中,只有 pthreads 在等待函数中提供了超时的特性.
还有几点非常重要,需要说明一下:
- 尽管 POSIX 信号量是计数器信号量,但是当这个计数器被设置为 1 时,它们可以提供与 Windows 事件对象相似的功能.它们并不能在等待函数中提供超时时间.如果在进行移植时,超时并不是一个影响因素,那么建议您使用 POSIX 信号量.
- 当与互斥一起使用时,pthreads 条件变量可以在线程之间提供基于事件的同步机制,不过这是同步的.根据应用程序的逻辑,这可以将此作为移植过程中在 Linux 上实现这种功能的一个选择.
创建/打开事件对象
在 Windows 中,我们使用 CreateEvent() 来创建事件对象.
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCTSTR lpName
)
|
在这段代码中:
lpEventAttributes 是一个指针,它指向一个决定这个句柄是否能够被继承的属性.如果这个指针为 NULL,那么这个对象就不能被初始化.
bManualReset 是一个标记,如果该值为 TRUE,就会创建一个手工重置的事件,应该显式地调用 ResetEvent() ,将事件对象的状态设置为无信号状态.
bInitialState 是这个事件对象的初始状态.如果该值为 true,那么这个事件对象的初始状态就被设置为有信号状态.
lpName 是指向这个事件对象名的指针.对于无名的事件对象来说,该值是 NULL.
这个函数创建一个手工重置或自动重置的事件对象,同时还要设置改对象的初始状态.这个函数返回事件对象的句柄,这样就可以在后续的调用中使用这个事件对象了.
OpenEvent() 用来打开一个现有的有名事件对象.这个函数返回该事件对象的句柄.
HANDLE OpenEvent(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName
)
|
在这段代码中:
dwDesiredAccess 是针对这个事件对象所请求的访问权.
bInheritHandle 是用来控制这个事件对象句柄是否可继承的标记.如果该值为 TRUE,那么这个句柄就可以被继承;否则就不能 |