科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网网络频道在Linux上处理共享对象的同步事件

在Linux上处理共享对象的同步事件

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

调用进程或向这个对象发送消息的线程在发送消息调用完成之前都会接收并处理一系列事件。然而,如果产生这些事件的对象是由多个进程进行共享并且保存在共享内存中时,情况就稍微有些不同了。

作者:51cto 2007年10月14日

关键字:

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共3页)

清单 8. 控制台结果
$ ./shm_client
shm_client1.cpp:16 Message from pid(4332)  :
$ ipcs
------ Shared Memory Segments --------
key  shmidownerpermsbytesnattch  status
0x00001234 327686  sachin 666  136  0
$ ./shm_client
shm_client1.cpp:16 Message from pid(4333)  :
$ ipcrm -m 327686
ObjectWithEvents 实例中汇集了来自各个进程的事件。它可以只释放出当前进程所注册的事件。这种设计模式阐述了两点:
任何对一组事件的访问都由一个互斥对象来保护。
在事件发出前,使用进程 ID 进行过滤。
用于 IPC 的共享内存和事件缓存
现在让我们来看一下如何使用共享内存和事件的缓存进行进程间通信。如果事件是在共享对象中进行缓存的,那么它们可能会稍后才发出。接收进程必须要查询这个共享对象到底发生了什么事件。因此,通过采用一个同步模型,就可以实现进程间通信。这就是开发下面这种设计模式的动机。
给 IObjectWithEvents 添加两个方法,如下所示:
清单 9. 给 IObjectWithEvents 添加方法
class IObjectWithEvents
{
public:virtual bool EnqueueEvent(const char * msg) = 0;virtual bool PollForEvents() = 0;
};
EnqueueEvent() 简单地在共享对象中添加事件的缓存,PollForEvents() 则会对这些缓存数据进行检索。
shm_client1 将使用 EnqueueEvent() 方法,如下所示:
powe->EnqueueEvent("Message from shm_client1");
shm_client2(实际上是 shm_client1 的一个拷贝)会使用 PollForEvents() 方法,如下所示:
powe->EnqueueEvent("Message from shm_client2"); powe->PollForEvents();
另外,我们给 ObjectWithEvents 增加了点东西,如下所示:
清单 10.
class ObjectWithEvents : public IObjectWithEvents
{
public:virtual bool EnqueueEvent(const char * msg);virtual bool PollForEvents();
//The event cacheenum { MAX_EVENTS = 16, MAX_EVENT_MSG = 256, };long m_nEvents;pid_t m_alPIDEvents[MAX_EVENTS];char m_aaMsgs[MAX_EVENTS][MAX_EVENT_MSG];
};
这些生成了新的构造函数:
ObjectWithEvents::ObjectWithEvents() : m_npEI(0), m_nEvents(0) { }
EnqueueEvent() 将事件(例如每个发出的事件的消息和进程 id)加入一个队列中。 PollForEvents() 负责遍历这个队列,并逐一对队列中的事件调用 OnEvent()。
清单 11. EnqueueEvent
bool ObjectWithEvents::EnqueueEvent(const char * msg)
{if (NULL == msg){return false;}
if (MAX_EVENTS == m_nEvents){//IEventSink collection fullreturn false;}
int bRetVal = Initializer::LockMutex();
if (0 != bRetVal){return false;}
m_alPIDEvents[m_nEvents] = getpid();strncpy(m_aaMsgs[m_nEvents++], msg, MAX_EVENT_MSG - 1);
if ((0 == bRetVal) && (0 != Initializer::UnlockMutex())){// Deal with error.}
return true;
}
bool ObjectWithEvents::PollForEvents()
{if (0 == m_nEvents){return true;}
int bRetVal = Initializer::LockMutex();
if (0 != bRetVal){return false;}
pid_t pid = getpid();
for (long i = 0; i < m_npEI; i++){// Does the handler belongs to current process ?
if (pid != m_alPID[i]){continue;}
//Recheck for NULL
if (0 == m_apEI[i]){continue;}
for (long j = 0; j < m_nEvents; j++){m_apEI[i]->OnEvent(m_alPIDEvents[j], m_aaMsgs[j]);}}
if ((0 == bRetVal) && (0 != Initializer::UnlockMutex())){// Deal with error.}
return true;
}

现在试着运行一下编译脚本:
g++ -g -o shm_client1 shm_client1.cpp ObjectWithEvents.cpp Initializer.cpp g++ -g -o shm_client2 shm_client2.cpp ObjectWithEvents.cpp Initializer.cpp
控制台上的输出应该如下所示:
清单 12. shm_client1 和 shm_client2 的输出
$ ./shm_client1
$ ./ipcs
------ Shared Memory Segments --------
key  shmidownerpermsbytesnattch  status
0x00001234 360454  sachin 666  4300 0
$ ./shm_client2
shm_client2.cpp:16 Message from pid(4454)  : Message from shm_client1
shm_client2.cpp:16 Message from pid(4456)  : Message from shm_client2
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章