[讨论] 同步互斥问题
一块共享内存. 有多个进程进行写操作,比如发送消息, 有一个进程进行读操作(也可以是多个),比如接收消息.消息的长度是不定长的,应该怎样设计这个方案呢?
首先想到的是设置信号量sem, 初值为1, 并实现原子操作的lock和unlock
当需要访问shared memory时,进行lock,然后操作shared memory,操作完后,调用unlock解除信号锁.
那么消息的数据结构怎样组织才好呢? 毕竟消息长度是不定长的.
另外如果写进程是多个而读进程是一个,这样会不会读进程的调度量及不上写进程,而使shared memory很快就满.
欢迎讨论. 数据结构的设计
在shared memory的头部留下一小块空间, 作为整个消息队列的头, 存放头第一条消息的指针,最后一条消息的消息尾的指针, 和消息数目.
每次操作都先访问这个head.
构建成一个循环队列... 消息长度不定长,消息总数目也不定长,只有首指针尾指针和总数目的话可以定位到第N条消息吗? 明白了,LZ指的是每条消息都留一个位置指向下一消息 “读”消息是指把消息取出并且清空相应内存吧?
能不能让读消息进程排队排在最前面(读消息的前提是有消息可读)
LZ遇到的问题有点像操作系统课程里的例子...不知是不是我理解错了。。 原帖由 dreamwalker 于 2008-4-3 13:13 发表 https://www.gdutbbs.com/images/common/back.gif
消息长度不定长,消息总数目也不定长,只有首指针尾指针和总数目的话可以定位到第N条消息吗?
初步设想是在每条消息头放置消息长度.
shared memory的总数目应该是与定位消息干系不大. 原帖由 dreamwalker 于 2008-4-3 13:20 发表 https://www.gdutbbs.com/images/common/back.gif
“读”消息是指把消息取出并且清空相应内存吧?
能不能让读消息进程排队排在最前面(读消息的前提是有消息可读)
LZ遇到的问题有点像操作系统课程里的例子...不知是不是我理解错了。。
读出来,不一定要清空内存.下次写就覆盖吧... 可否考虑这样的结构?
msgInfo
{
msgHeader ;
msgLength ;
msgContent;/* 用一块内存来保存消息的具体内容 */
}
这样,可以在msgHeader里面定义不同的消息类型之类什么的,然后不同的类型对应不同的msgContent,然后可以对应不同的type定义msgContent的内容的解析方式
这样的结构是,在读取的时候可以得到读取的地方,同时可以把内容完整地存在内存中,同时定义不同的类型的解析方式的话,就很灵活地可以定义不同的消息,
不过,溢出始终是一个问题,可不可以用多线程的方式读取?
都还没有想出怎么样的一个解决方式,只有考虑具体的应用,比如,多个进程写到这个共享内存,但是写的频率不大,这样可以考虑更大地共享内存,然后更快地读取方式(直接根据读出的length来把后面的内存的内容copy到自己的内存,然后再处理...) 用循环队列实现.
每条消息的首字节保存该消息的长度.
shared memory首部的全局信息如下定义:
headinfo
{
void *pFirst; //第一条可读消息的首地址
void *pLast; //最后一条消息的尾地址(也即下一条要写入的消息开始写的地址).
}
每次读时从整个shared memory的headinfo保存的pFirst所指示的地址处开始读,
写时从headinfo保存的pLast指示的地址处开始写.
其实与蝎子的做法有点类似.
关于溢出问题, 队列满时是写不进的,会返回error给调用者.
但当没有消息在shared memory时, 怎样把read process idle掉.
当有消息时,怎样wake up它? 看实现的方式了,对于read process来说,可以做成一个无限的循环,然后在循环里面读取函数,如果无消息报可读的时候就sleep一步段时间,linux直接有这样的系统函数,可以s,或者ns为单位
然后对于write process来说是一样的,同时看应用的需要,是把这个进程sleep掉等待shared memory 有空闲区域来写,还是直接丢弃这个消息,然后下次的可以直接写shared memory 而不管是否有空闲区域...
在线程的编写中通常这都是一个的无限循环,然后如果需要等待一定信号而阻塞的就用sleep等待一小段时间然后再检测是否符合条件去继续走下去 初定使用sleep.
到时review不通过再想其它办法了. 其实应该以实现的难度来考虑这个了,
如果要求进程通信来wakeup的话,这样肯定对于写进程和,读进程都是一个负担,要另外加消息处理的部分,但是用这个自己检查自己sleep的方式来实现的话可以各自模块更独立,进程间的交互也减少,但是应该考虑实际的应用场景以及可能的扩展.... sleep的难度最低了吧...
读进程的话, 我的设想是做一个线程池, 每读一条消息后, 就从池中取一个线程去处理.. so,应该在检视会议上坚持用sleep的方法..否则可能会做得很复杂,进程间交互的话,复杂度成倍上升..... sleep配上alarm和信号基本上可以实现到handup和wakeup了.
页:
[1]