发明内容
鉴于上述问题,提出了本发明以便提供一种克服上述问题或者至少部分地解决上述问题的基于消息队列的共享内存写入及读取方法和系统,以解决进程间通信时阻塞的问题,减少资源消耗,充分利用系统资源,提高处理速度,从而提高服务器吞吐量。
依据本发明的一个方面,提供了一种基于消息队列的共享内存写入方法,所述消息队列包括第一消息队列,所述方法包括:
采用所述消息队列执行多线程进队push以及单线程出队pop的操作;
将所述单线程出队pop的数据写入共享内存;
其中,所述多线程进队push的操作包括:
判断所述消息队列是否已满;
若否,则分别计算n个线程进队push的偏移量;所述n为大于或等于1的正整数;
依据所述n个线程进队push的偏移量,分别计算所述n个线程进队push的实际位置Pos;
所述n个线程分别在其进队push的实际位置Pos执行进队push操作;
其中,所述将所述单线程出队pop的数据写入共享内存的步骤包括:
获得所述单线程出队pop的数据及其长度;
检查所述数据的长度是否超出共享内存的长度界限;
若否,则获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写;
若是,则在所述写入位置写入所述数据。
可选地,在采用所述消息队列执行多线程进队push以及单线程出队pop的操作的步骤之前还包括:
在存在多个消息队列时,选定用于当前通信的第一消息队列。
可选地,所述选定用于当前通信的第一消息队列的步骤包括:
读取所述数据的协议中的上下文参数intnId;
采用所述上下文参数intnId对所述多个消息队列的个数取模;
提取所述取模的值对应的消息队列为用于当前通信的第一消息队列。
可选地,所述判断消息队列是否已满的子步骤进一步包括:
读取可写计数参数CanWriteCount的值;
递减所述CanWriteCount的值;
若获得递减后的CanWriteCount的值为0,则判定所述消息队列为已满,否则,判定所述消息队列为未满。
可选地,所述分别计算n个线程进队push的偏移量的子步骤进一步包括:
读取进队push的偏移量Pushpos的值;
针对所述n个线程迭代增加所述Pushpos的值,分别获得所述n个线程进队push的偏移量。
可选地,所述分别计算所述n个线程进队push的实际位置Pos的子步骤进一步包括:
读取所述消息队列大小参数Size的值;
采用所述Size的值对所述Pushpos的值取模,获得对应的n个线程进队push的实际位置Pos。
可选地,在所述n个线程分别在其进队push的实际位置执行进队push操作的子步骤之后,所述多线程进队push的操作还包括:
读取可读计数参数CanReadCount的值;
按照所述n个线程进队push的操作,迭代增加所述CanReadCount的值。
可选地,所述单线程出队pop的操作的子步骤为:
单个线程依次在所述消息队列中执行出队pop操作。
可选地,所述多线程进队push的操作还包括:
若所述消息队列已满,则禁止执行进队push的操作。
可选地,所述将所述单线程出队pop的数据写入共享内存的步骤还包括:
若所述数据的长度超出共享内存的长度界限,则禁止写入。
可选地,所述依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写的子步骤进一步包括:
依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
当所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,判定所述数据可写。
可选地,所述依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写的子步骤还进一步包括:
依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
当所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,设置可写数据的长度小于或等于allsize-pRead+pWrite-head,其中allsize为共享内存的长度,所述head为文件头的长度;
判断所述数据的长度是否小于或等于所述可写数据的长度;
若是,则判定所述数据可写;
若否,则判定所述数据不可写。
可选地,所述依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写的子步骤还进一步包括:
依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
当所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,设置可写数据的长度小于或等于pRead-pWrite;
判断所述数据的长度是否小于或等于所述可写数据的长度;
若是,则判定所述数据可写;
若否,则判定所述数据不可写。
可选地,所述获取所述共享内存的读偏移指针pRead和写偏移指针pWrite的子步骤进一步包括:
获得所述共享内存的映射文件,所述映射文件包括文件头;
从所述文件头中读取写偏移指针pWrite;
从所述文件头中读取读偏移指针pRead并快照到临时变量中。
可选地,所述在所述数据所在共享内存的位置写入所述数据的子步骤进一步包括:
当所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,或,当所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,则从当前写偏移指针pWrite位置开始写入所述数据;
当写入到所述共享内存尾部的位置时,判断所述数据是否已全部写入;
若否,则从所述共享内存中文件头结束的位置开始继续写入所述数据,直至在所述读偏移指针pRead位置之前写入全部的数据。
可选地,所述在所述数据所在共享内存的位置写入所述数据子步骤进一步包括:
当所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,则从当前写偏移指针pWrite位置开始写入所述数据;
在所述读偏移指针pRead位置之前写入全部的数据。
可选地,采用内存拷贝memcpy的方式写入所述数据。
根据本发明的另一方面,提供了一种基于消息队列的共享内存读取方法,所述消息队列包括第二消息队列,所述方法包括:
从共享内存中读取数据;
将读出的数据通过单线程进队push的操作压入所述第二消息队列,同时,采用所述第二消息队列执行多线程出队pop的操作;
其中,所述从共享内存中读取数据的步骤包括:
定位待读取数据所在共享内存的位置;
获得所述待读取数据的长度;
获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述待读取数据的长度,判断所述待读取数据是否可读;
若是,则从所述待读取数据所在共享内存的位置,读出所述待读取数据;
其中,所述多线程出队pop的操作包括:
判断所述消息队列是否已空;
若否,则分别计算n个线程出队pop的偏移量;所述n为大于或等于1的正整数;
依据所述n个线程出队pop的偏移量,分别计算所述n个线程出队pop的实际位置Pos;
所述n个线程分别在其出队pop的实际位置执行出队pop操作。
可选地,所述从共享内存中读取数据的步骤还包括:
若所述数据不可读,则返回数据为空。
可选地,所述依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,判断所述数据是否可读的子步骤进一步包括:
当所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,设置可读数据的长度小于或等于pWrite-pRead;
判断所述数据的长度是否小于或等于所述可读数据的长度;
若是,则判定所述数据可读;
若否,则判定所述数据不可读。
可选地,所述依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,判断所述数据是否可读的子步骤还进一步包括:
当所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,设置可读数据的长度小于或等于allsize-pRead+pWrite-head,其中,所述allsize为共享内存的长度,所述head为文件头的长度;
判断所述数据的长度是否小于或等于所述可读数据的长度;
若是,则判定所述数据可读;
若否,则判定所述数据不可读。
可选地,所述依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,判断所述数据是否可读的子步骤还进一步包括:
当所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,则判定所述数据不可读。
可选地,所述获取所述共享内存的读偏移指针pRead和写偏移指针pWrite的子步骤进一步包括:
获得所述共享内存的映射文件,所述映射文件包括文件头;
从所述文件头中读取读偏移指针pRead;
从所述文件头中读取写偏移指针pWrite并快照到临时变量中。
可选地,所述从所述数据所在共享内存的位置,读出所述数据的子步骤进一步包括:
当所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,则从当前读偏移指针pRead位置开始读出所述数据;
在不超过所述写偏移指针pWrite位置读出全部的数据。
可选地,所述从所述数据所在共享内存的位置,读出所述数据的子步骤进一步包括:
当所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,则从当前读偏移指针pRead位置开始读出所述数据;
当读取至所述共享内存尾部的位置时,判断所述数据是否已全部读出;
若否,则从所述共享内存中文件头结束的位置开始继续读出所述数据,直至在不超过所述写偏移指针pWrite位置读出全部的数据。
可选地,采用内存拷贝memcpy的方式读出所述数据。
可选地,所述判断消息队列是否已空的子步骤进一步包括:
读取可读计数参数CanReadCount的值;
递减所述CanReadCount的值;
若获得递减后的CanReadCount的值为0,则判定所述消息队列为已空,否则,判定所述消息队列为未空。
可选地,所述分别计算n个线程出队pop的偏移量的子步骤进一步包括:
读取出队pop的偏移量Poppos的值;
针对所述n个线程迭代增加所述Poppos的值,分别获得所述n个线程出队pop的偏移量。
可选地,所述分别计算所述n个线程出队pop的实际位置Pos的子步骤还进一步包括:
读取所述消息队列大小参数Size的值;
采用所述Size的值对所述Poppos的值取模,获得对应的n个线程出队pop的实际位置Pos。
可选地,在所述n个线程分别在其出队pop的实际位置执行出队pop操作的步骤之后,还包括:
读取可写计数参数CanWriteCount的值;
按照所述n个线程出队pop的操作,迭代增加所述CanWriteCount的值。
可选地,所述单线程进队push的操作进一步包括:
单个线程依次在所述消息队列中执行进队push操作。
可选地,所述多线程出队pop的操作还进一步包括:
若所述消息队列已空,则禁止执行出队pop的操作。
根据本发明的另一方面,提供了一种基于消息队列的共享内存读写的方法,所述消息队列包括第一消息队列和第二消息队列,所述方法包括:
采用第一消息队列执行多线程进队push以及单线程出队pop的操作;
将所述单线程出队pop的数据写入共享内存;
从所述共享内存中读取数据;
将读出的数据通过单线程进队push的操作压入所述第二消息队列,同时,采用所述第二消息队列执行多线程出队pop的操作;
其中,所述多线程进队push的操作包括:
读取可写计数参数CanWriteCount的值;
递减所述CanWriteCount的值;
若获得递减后的CanWriteCount的值不为0,则判定所述消息队列为未满;
在所述消息队列未满时,分别计算n个线程进队push的偏移量;所述n为大于或等于1的正整数;
依据所述n个线程进队push的偏移量,分别计算所述n个线程进队push的实际位置;
所述n个线程分别在其进队push的实际位置执行进队push操作;
读取可读计数参数CanReadCount的值;
按照所述n个线程进队push的操作,迭代增加所述CanReadCount的值;
其中,所述多线程出队pop的操作包括:
读取可读计数参数CanReadCount的值;
递减所述CanReadCount的值;
若获得递减后的CanReadCount的值不为0,则判定所述消息队列为未空;
在所述消息队列未空时,分别计算n个线程出队pop的偏移量;所述n为大于或等于1的正整数;
依据所述n个线程出队pop的偏移量,分别计算所述n个线程出队pop的实际位置;
所述n个线程分别在其出队pop的实际位置执行出队pop操作;
读取可写计数参数CanWriteCount的值;
按照所述n个线程出队pop的操作,迭代增加所述CanWriteCount的值;
其中,将所述单线程出队pop的数据写入共享内存的步骤包括:
获得所述单线程出队pop的数据及其长度;
检查所述数据的长度是否超出共享内存的长度界限;
若否,则获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写;
若是,则在所述写入位置写入所述数据;
其中,所述从共享内存中读取数据的步骤包括:
定位待读取数据所在共享内存的位置;
获得所述待读取数据的长度;
获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述待读取数据的长度,判断所述待读取数据是否可读;
若是,则从所述待读取数据所在共享内存的位置,读出所述待读取数据。
根据本发明的另一方面,提供了一种基于消息队列的共享内存写入系统,所述消息队列包括第一消息队列,所述系统包括:
多线程进队push模块及单线程出队pop模块,用于采用所述消息队列执行多线程进队push以及单线程出队pop的操作;
数据写入模块,用于将所述单线程出队pop的数据写入共享内存;
其中,所述多线程进队push模块包括:
第一判断子模块,用于判断所述消息队列是否已满;
进队push偏移量计算子模块,用于在消息队列未满时,分别计算n个线程进队push的偏移量;所述n为大于或等于1的正整数;
进队push的实际位置Pos计算子模块,用于依据所述n个线程进队push的偏移量,分别计算所述n个线程进队push的实际位置Pos;
操作进队push子模块,用于所述n个线程分别在其进队push的实际位置Pos执行进队push操作;
其中,所述数据写入模块包括:
数据及其长度获得子模块,用于获得所述单线程出队pop的数据及其长度;
界限检查子模块,用于检查所述数据的长度是否超出共享内存的长度界限;
第一指针获取子模块,用于在所述数据的长度未超出共享内存的长度界限时,获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
可写判断子模块,用于依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写;
写入子模块,用于在数据可写时,在所述写入位置写入所述数据。
可选地,所述系统还包括:
第一消息队列选定模块,用于在存在多个消息队列时,选定用于当前通信的第一消息队列。
可选地,所述第一消息队列选定模块包括:
上下文参数读取子模块,用于读取所述数据的协议中的上下文参数intnId;
取模子模块,用于采用所述上下文参数intnId对所述多个消息队列的个数取模;
提取子模块,用于提取所述取模的值对应的消息队列为用于当前通信的第一消息队列。
可选地,所述第一判断子模块进一步包括:
可写计数参数读取子模块,用于读取可写计数参数CanWriteCount的值;
可写计数参数递减子模块,用于递减所述CanWriteCount的值;
第一判断子模块,用于在获得递减后的CanWriteCount的值为0,则判定所述消息队列为已满,否则,判定所述消息队列为未满。
可选地,所述进队push偏移量计算子模块进一步包括:
偏移量Pushpos读取子模块,用于读取进队push的偏移量Pushpos的值;
偏移量Pushpos获得子模块,用于针对所述n个线程迭代增加所述Pushpos的值,分别获得所述n个线程进队push的偏移量。
可选地,所述进队push的实际位置Pos计算子模块进一步包括:
第一大小参数Size读取子模块,用于读取所述消息队列大小参数Size的值;
进队push的实际位置Pos获得子模块,用于获得对应的n个线程进队push的实际位置Pos。
可选地,所述多线程进队push子模块还进一步包括:
可读计数参数读取子模块,读取可读计数参数CanReadCount的值;
可读计数参数读迭代增加子模块,按照所述n个线程进队push的操作,迭代增加所述CanReadCount的值。
可选地,所述单线程出队pop模块进一步包括:
出队pop子模块,用于单个线程依次在所述消息队列中执行出队pop操作。
可选地,所述多线程进队push模块还进一步包括:
进队push的操作禁止子模块,用于在所述消息队列已满时,禁止执行进队push的操作。
可选地,所述数据写入模块还进一步包括:
禁止写入子模块,用于在所述数据的长度超出共享内存的长度界限,则禁止写入。
可选地,所述可写判断子模块进一步包括:
第一写入位置确定子模块,用于依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
第一可写判定子模块,用于当所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,判定所述数据可写。
可选地,所述可写判断子模块还进一步包括:
第二写入位置确定子模块,用于依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
第一可写数据长度设置子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,设置可写数据的长度小于或等于allsize-pWrite+pRead-head,其中allsize为共享内存的长度,所述head为文件头的长度;
第三判断子模块,用于判断所述数据的长度是否小于或等于所述可写数据的长度;
第二可写判定子模块,用于所述数据的长度小于或等于所述可写数据的长度时,判定所述数据可写;
第一不可写判定子模块,用于所述数据的长度大于所述可写数据的长度时,判定所述数据不可写。
可选地,所述可写判断子模块还进一步包括:
第三写入位置确定子模块,用于依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
第二可写数据长度设置子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,设置可写数据的长度小于或等于pRead-pWrite;
第四判断子模块,用于判断所述数据的长度是否小于或等于所述可写数据的长度;
第三可写判定子模块,用于所述数据的长度小于或等于所述可写数据的长度时,判定所述数据可写;
第二不可写判定子模块,用于所述数据的长度大于所述可写数据的长度时,判定所述数据不可写。
可选地,所述第一指针获取子模块进一步包括:
第一映射文件获得子模块,用于获得所述共享内存的映射文件,所述映射文件包括文件头;
第一写偏移指针pWrite读取子模块,用于从所述文件头中读取写偏移指针pWrite;
第一读偏移指针pRead读取子模块,用于从所述文件头中读取读偏移指针pRead并快照到临时变量中。
可选地,所述写入子模块进一步包括:
第一开始写入子模块,用于在所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,或,在所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,则从当前写偏移指针pWrite位置开始写入所述数据;
尾部写入判断子模块,用于在写入到所述共享内存尾部的位置时,判断所述数据是否已全部写入;
第一全部写入子模块,用于所述数据未全部写入时,从所述共享内存中文件头结束的位置开始继续写入所述数据,直至在所述读偏移指针pRead位置之前写入全部的数据。
可选地,所述写入子模块进一步包括:
第二开始写入子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,则从当前写偏移指针pWrite位置开始写入所述数据;
第二全部写入子模块,用于在所述读偏移指针pRead位置之前写入全部的数据。
可选地,采用内存拷贝memcpy的方式写入所述数据
根据本发明的另一方面,提供了一种基于消息队列的共享内存读取系统,所述消息队列包括第二消息队列,所述系统包括:
数据读取模块,用于从共享内存中读取数据;
单线程进队push模块及多线程出队pop模块,用于将读出的数据通过单线程进队push的操作压入所述第二消息队列,同时,采用所述第二消息队列执行多线程出队pop的操作;
其中,所述数据读取模块包括:
定位子模块,用于定位待读取数据所在共享内存的位置;
数据长度获得子模块,用于获得所述待读取数据的长度;
第二指针获取子模块,用于获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
可读判断子模块,用于依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,判断所述待读取数据是否可读;
读取子模块,用于在所述数据可读时,从所述数据所在共享内存的位置,读出所述待读取数据。
其中,所述多线程出队pop模块包括:
第二判断子模块,用于判断所述消息队列是否已空;
出队pop的偏移量计算子模块,用于在消息队列未空时,分别计算n个线程出队pop的偏移量;所述n为大于或等于1的正整数;
出队pop的实际位置Pos计算子模块,用于依据所述n个线程出队pop的偏移量,分别计算所述n个线程出队pop的实际位置Pos;
操作出队pop子模块,用于所述n个线程分别在其出队pop的实际位置执行出队pop操作。
可选地,所述数据读取模块还进一步包括:
返回子模块,用于在所述数据不可读时,返回数据为空。
可选地,所述可读判断子模块进一步包括:
第一可读数据长度设置子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,设置可读数据的长度小于或等于pWrite-pRead;
第一判断子模块,用于判断所述数据的长度是否小于或等于所述可读数据的长度;
第一可读判定子模块,用于所述数据的长度小于或等于所述可读数据的长度时,判定所述数据可读;
第一不可读判定子模块,用于所述数据的长度大于所述可读数据的长度时,判定所述数据不可读。
可选地,所述可读判断子模块还进一步包括:
第二可读数据长度设置子模块,用于当所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,设置可读数据的长度小于或等于allsize-pRead+pWrite-head,其中,所述allsize为共享内存的长度,所述head为文件头的长度;
第二判断子模块,用于判断所述数据的长度是否小于或等于所述可读数据的长度;
第二可读判定子模块,用于所述数据的长度小于或等于所述可读数据的长度时,判定所述数据可读;
第二不可读判定子模块,用于所述数据的长度大于所述可读数据的长度时,判定所述数据不可读。
可选地,所述可读判断子模块还进一步包括:
第三不可读判定子模块,用于在所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,判定所述数据不可读。
可选地,所述第二指针获取子模块进一步包括:
第二映射文件获得子模块,用于获得所述共享内存的映射文件,所述映射文件包括文件头;
第二读偏移指针pRead读取子模块,用于从所述文件头中读取读偏移指针pRead;
第二写偏移指针pWrite读取子模块,用于从所述文件头中读取写偏移指针pWrite并快照到临时变量中。
可选地,所述读取子模块进一步包括:
第一开始读取子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,从当前读偏移指针pRead位置开始读出所述数据;
第一全部读取子模块,用于在不超过所述写偏移指针pWrite位置读出全部的数据。
可选地,所述读取模块进一步包括:
第二开始读取子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,从当前读偏移指针pRead位置开始读出所述数据;
尾部读取判断子模块,用于在读取至所述共享内存尾部的位置时,判断所述数据是否已全部读出;
第二全部读取子模块,用于在所述数据未全部读出时,从所述共享内存中文件头结束的位置开始继续读出所述数据,直至在不超过所述写偏移指针pWrite位置读出全部的数据。
可选地,采用内存拷贝memcpy的方式读出所述数据。
可选地,所述第二判断子模块进一步包括:
可读计数参数读取子模块,用于读取可读计数参数CanReadCount的值;
可读计数参数递减子模块,用于递减所述CanReadCount的值;
第二判断子模块,用于在获得递减后的CanReadCount的值为0,则判定所述消息队列为已空,否则,判定所述消息队列为未空。
可选地,所述出队pop的偏移量计算子模块还进一步包括:
偏移量Poppos读取子模块,用于读取出队pop的偏移量Poppos的值;
偏移量Poppos获得子模块,用于针对所述n个线程迭代增加所述Poppos的值,分别获得所述n个线程出队pop的偏移量。
可选地,所述出队pop的实际位置Pos计算子模块进一步包括:
第二大小参数读取子模块,用于读取所述消息队列大小参数Size的值;
出队pop的实际位置Pos计算子模块,用于采用所述Size的值对所述Poppos的值取模,获得对应的n个线程出队pop的实际位置Pos。
可选地,所述多线程出队pop模块还进一步包括:
可写计数参数读取子模块,用于读取可写计数参数CanWriteCount的值;
可写计数参数迭代增加子模块,用于按照所述n个线程出队pop的操作,迭代增加所述CanWriteCount的值。
可选地,所述单线程进队push模块进一步包括:
进队push子模块,用于单个线程依次在所述消息队列中执行进队push操作。
可选地,所述多线程出队pop模块还进一步包括:
出队pop的操作禁止子模块,用于在所述消息队列已空时,则禁止执行出队pop的操作。
根据本发明的另一方面,提供了一种基于消息队列的共享内存处理的系统,所述消息队列包括第一消息队列和第二消息队列,所述方法包括:
第一进队push模块和第一出队pop模块,用于采用第一消息队列执行多线程进队push以及单线程出队pop的操作;
共享内存写入模块,用于将所述单线程出队pop的数据写入共享内存;
共享内存读取模块,用于从所述共享内存中读取数据;
第二进队push模块和第二出队pop模块,用于将读出的数据通过单线程进队push的操作压入所述第二消息队列,同时,采用所述第二消息队列执行多线程出队pop的操作;
其中,所述第一进队push模块包括:
CanWriteCount参数读取子模块,用于读取可写计数参数CanWriteCount的值;
CanWriteCount参数递减子模块,用于递减所述CanWriteCount的值;
第三判断子模块,用于在获得递减后的CanWriteCount的值不为0,则判定所述消息队列为未满;
push的偏移量计算子模块,用于在所述消息队列未满时,分别计算n个线程进队push的偏移量;所述n为大于或等于1的正整数;
push的实际位置计算子模块,用于依据所述n个线程进队push的偏移量,分别计算所述n个线程进队push的实际位置;
push操作执行子模块,用于所述n个线程分别在其进队push的实际位置执行进队push操作;
CanReadCount参数读取子模块,用于读取可读计数参数CanReadCount的值;
CanReadCount参数迭加子模块,用于按照所述n个线程进队push的操作,迭代增加所述CanReadCount的值;
其中,所述第二出队pop模块包括:
CanReadCount参数读取子模块,用于读取可读计数参数CanReadCount的值;
CanReadCount参数递减子模块,用于递减所述CanReadCount的值;
第四判断子模块,用于在获得递减后的CanReadCount的值不为0,则判定所述消息队列为未空;
pop的偏移量计算子模块,用于在所述消息队列未空时,分别计算n个线程出队pop的偏移量;所述n为大于或等于1的正整数;
pop的实际位置计算子模块,用于依据所述n个线程出队pop的偏移量,分别计算所述n个线程出队pop的实际位置;
pop操作执行子模块,用于所述n个线程分别在其出队pop的实际位置执行出队pop操作;
CanWriteCount参数读取子模块,用于读取可写计数参数CanWriteCount的值;
CanWriteCount参数迭加子模块,用于按照所述n个线程出队pop的操作,迭代增加所述CanWriteCount的值;
其中,共享内存写入模块包括:
数据获得子模块,用于获得所述单线程出队pop的数据及其长度;
检查子模块,用于检查所述数据的长度是否超出共享内存的长度界限;
第三指针获取子模块,用于在所述数据的长度未超出共享内存的长度界限时,获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
数据可写判断子模块,用于依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写;
写入数据子模块,用于在数据可写时,在所述写入位置写入所述数据;
其中,所述共享内存读取模块包括:
数据定位子模块,用于定位待读取数据所在共享内存的位置;
长度获得子模块,用于获得所述待读取数据的长度;
第四指针获取子模块,用于获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
数据可读判断子模块,用于依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,判断所述待读取数据是否可读;
读取数据子模块,用于在所述数据可读时,从所述数据所在共享内存的位置,读出所述待读取数据。
与现有技术相比,本发明包括以下优点:
本发明通过采用第一消息队列执行多线程进队push以及单线程出队pop的操作,或,采用第二消息队列执行单线程进队push以及多线程出队pop的操作,可以保证多线程访问操作不碰撞,避免使用互斥锁来解决多线程并发争用安全性的问题,并且,多线程进队push和单线程出队pop的操作可以同时进行,解决了线程间通信时阻塞的问题,减少了资源消耗,充分利用了系统资源,提高了处理速度,从而提高了服务器吞吐量。
本发明通过将所述数据写入共享内存,可以不加锁的控制写入数据,避免了加锁造成的阻塞的问题,从而减少资源消耗,充分利用系统资源,提高处理速度,提高服务器吞吐量。
本发明通过从所述共享内存中读取数据,可以不加锁的控制读出数据,避免了加锁造成的阻塞的问题,从而减少资源消耗,充分利用系统资源,提高处理速度,提高服务器吞吐量。
本发明通过选定第一消息队列,均衡了各个消息队列上的负载,提高了处理速度,有效避免出现某个消息队列负载远远大于其他消息队列的负载的情况,从而减少各个CPU之间使用率的差值,提高服务器吞吐量。
本发明通过判断消息队列已满时,禁止执行进队push的操作,保证了写入数据时的安全性与准确性,以及,通过判断消息队列已空时,禁止执行出队pop的操作,保证了读取数据时的安全性与准确性,从而保证多线程访问成功,解决了线程间通信时阻塞的问题,从而提高服务器吞吐量。
本发明通过迭代增加可读计数参数CanReadCount,保证了线程执行读操作时可读原子数目的准确性,以及,通过迭代增加可写计数参数CanWriteCount,保证了线程执行写操作时可写原子数目的准确性,从而保证了线程间通信成功,减少资源消耗,充分利用系统资源,提高处理速度,从而提高服务器吞吐量。
本发明通过获得所述共享内存的映射文件,所述映射文件包括文件头,从所述文件头中读取写偏移指针pWrite并快照到临时变量中,记录了当前写偏移指针pWrite的位置,从而保证了在执行当前读操作的内存不会随写偏移指针pWrite的变化而被修改,以及,通过获得所述共享内存的映射文件,所述映射文件包括文件头,从所述文件头中读取读偏移指针pRead并快照到临时变量中,记录了当前读偏移指针pRead的位置,从而保证了在执行当前写操作的内存不会随读偏移指针pRead的变化而被修改,即读操作和写操作可以同时进行,并且,保证了读偏移指针pRead不会与写偏移指针pWrite产生冲突,因此能够充分利用系统资源,解决进程间通信时阻塞的问题,减少资源消耗,从而提高服务器吞吐量。
本发明通过采用内存拷贝memcpy的方式读出所述数据的方式,能够快速地将数据从共享内存中读出,以及,通过采用内存拷贝memcpy的方式写入所述数据的方式,能够快速地将数据写入共享内存中,从而提高处理速度,提高服务器吞吐量。
上述说明仅是本发明技术方案的概述,为了能够更清楚了解本发明的技术手段,而可依照说明书的内容予以实施,并且为了让本发明的上述和其它目的、特征和优点能够更明显易懂,以下特举本发明的具体实施方式。
具体实施方式
下面将参照附图更详细地描述本公开的示例性实施例。虽然附图中显示了本公开的示例性实施例,然而应当理解,可以以各种形式实现本公开而不应被这里阐述的实施例所限制。相反,提供这些实施例是为了能够更透彻地理解本公开,并且能够将本公开的范围完整的传达给本领域的技术人员。
为使本领域技术人员更好地理解本发明,以下对本发明所涉及的相关技术进行简单说明。
消息队列是在消息的传输过程中保存消息的容器,所谓消息是进行传送的数据单位。消息可以非常简单,例如只包含文本字符串,也可以更复杂,可能包含嵌入对象。消息队列在将消息从它的源中继到它的目标时充当中间人。消息队列的主要目的是提供路由并保证消息的传递;如果发送消息时接收者不可用,消息队列会保留消息,直到可以成功地传递它。消息队列是Microsoft的消息处理技术,它在任何安装了Microsoft Windows的计算机组合中,为任何应用程序提供消息处理和消息队列功能,无论这些计算机是否在同一个网络上或者是否同时联机。
共享内存指基于环形缓冲区的共享内存,顾名思义环形缓冲区是环形的,所谓环形,就是用一个指针去访问该缓冲区的最后一个内存位置的后一位置时回到环形缓冲区的起点。环形缓冲区通常有一个读指针和一个写指针,读指针指向环形缓冲区中可读的缓冲区,写指针指向环形缓冲区中可写的缓冲区。通过移动读指针和写指针就可以实现缓冲区的数据读取和写入。在通常情况下,环形缓冲区的读操作仅仅会影响读指针,而写操作仅仅会影响写指针。
消息队列和共享内存都可以单独的用于线程间的通信,当消息队列或共享内存单独地用于多线程写入和多线程读取时,由于线程可以执行进程的任何代码段,且线程的运行是由系统调度自动完成的,具有一定的不确定性,因此就有可能出现两个线程同时对磁盘驱动器进行操作,从而出现操作错误,因此要解决线程间对资源的并发争用安全性的问题,通常采用加锁的方式以解决上述问题,然而加锁会阻塞其他线程,以保证在任一时刻只能有一个线程访问该对象,从而造成程序效率大幅度的降低,资源消耗的增加,处理速度的降低,无法充分利用系统资源,服务器吞吐量大幅度的降低。
正是本专利发明人发现这一问题的严重性,创造性地提出本发明实施例的核心构思之一在于,提出一种通信机制,可以实现采用消息队列执行多线程进队push以及单线程出队pop的操作,和,采用消息队列执行单线程进队push以及多线程出队pop的操作,以及,单线程读写的共享内存,从而实现在对消息队列和共享内存不加锁的情况下,同时执行多线程进队push和多线程出队pop操作,安全地完成线程间通信,并且,线程间没有阻塞,从而能够充分利用系统资源,提高服务器吞吐量。长期以来,本领域技术人员对于多线程并发争用安全性的技术问题,普遍采用消息队列或共享内存在写入数据和读取数据时加锁的方式完成线程间的通信。本专利发明人反其道而行之,采用本领域技术人员由于技术偏见而舍弃的技术手段,通过不加锁的消息队列采用原子操作,以及不加锁的共享内存采用单线程读写,因此,多线程写入和多线程读取之间的通信访问操作不碰撞,从而解决多线程并发争用安全性的技术问题。
参照图1,示出了根据本发明一个实施例的一种基于消息队列的共享内存写入方法实施例1的步骤流程图,所述消息队列包括第一消息队列,具体可以包括如下步骤:
步骤101,采用所述消息队列执行多线程进队push以及单线程出队pop的操作;
参照图2,示出了根据本发明一个实施例的一种采用一个第一消息队列通信的示意图。如图2所示,多个线程写入数据至第一消息队列,并通过第一消息队列写入共享内存,从共享内存中读出数据到第二消息队列,多个线程从第二消息队列读取数据。
在具体应用中,消息队列是可以在消息的传输过程中保存消息的容器,在多个不同的应用之间实现相互通信的一种异步传输模式,将数据写入消息队列是通过进队push的操作,多线程进队push的操作是指同时执行多个线程进队push的操作,可以采用原子操作的方式,所谓原子操作就是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会切换到另一个线程,可以保证多线程进队push的操作不碰撞,从而将数据写入第一消息队列;从消息队列中读取数据是通过出队pop的操作,单线程出队pop的操作是指在执行多个线程进队push的操作的同时执行单个线程出队pop操作。
在本发明的一种优选实施例中,所述步骤101具体可以包括如下子步骤:
子步骤S11,判断所述消息队列是否已满;
在实际应用中,当消息队列为已满时,将禁止在消息队列中写入数据;当消息队列未满时,将可以在消息队列中写入数据。
在本发明的一种优选实施例中,所述子步骤S11具体可以包括如下子步骤:
子步骤A101,读取可写计数参数CanWriteCount的值;
子步骤A102,递减所述CanWriteCount的值;
子步骤A103,若获得递减后的CanWriteCount的值为0,则判定所述消息队列为已满,否则,判定所述消息队列为未满。
在具体应用中,多线程进队push操作时,每一个线程分别读取对应的可写计数参数CanWriteCount的值,采用原子操作递减CanWriteCount的值,若获得递减后的CanWriteCount的值为0,则判定所述消息队列为已满,否则,判定所述消息队列为未满。若所述消息队列已满,则禁止执行进队push的操作。
通过判断消息队列已满时,禁止执行进队push的操作,保证了写入数据时的安全性与准确性,从而保证多线程访问成功,解决了线程间通信时阻塞的问题,从而提高服务器吞吐量。
当然,上述判断消息队列是否为已满的处理方法只是作为示例,在实施本发明实施例时,可以根据实际情况设置其他判断消息队列是否为已满的处理方法,本发明实施例对此不加以限制。另外,除了上述判断消息队列是否为已满的处理方法外,本领域技术人员还可以根据实际需要采用其它判断消息队列是否为已满的处理方法,本发明实施例对此也不加以限制。
子步骤S12,若否,则分别计算n个线程进队push的偏移量;所述n为大于或等于1的正整数;
在实际应用中,一个双核心的CPU可以拥有4个线程,也就是说,线程的数量是CPU核数的2倍,服务器通常是8核CPU,具有16个线程。n的取值取决于任务数量,一个任务分配一个线程,偏移量是指存储单元的实际地址与其所在段的段地址之间的距离,n个线程进队push操作时,每个线程都是采用原子操作递加的方式,计算出来n个线程进队push的偏移量各不相同。
在本发明的一种优选实施例中,所述子步骤S12具体可以包括如下子步骤:
子步骤A201,读取进队push的偏移量Pushpos的值;
子步骤A202,针对所述n个线程迭代增加所述Pushpos的值,分别获得所述n个线程进队push的偏移量。
在具体实现中,一个线程读取进队push的偏移量Pushpos的值,采用当前偏移量Pushpos的值执行迭代增加操作,获得该线程进队push的偏移量,下一个线程读取迭代增加操作后的进队push的偏移量Pushpos的值,执行迭代增加操作,获得此线程进队push的偏移量,按上述方法依次针对所述n个线程迭代增加所述Pushpos的值,分别获得所述n个线程进队push的偏移量。
当然,上述计算n个线程进队push的偏移量的处理方法只是作为示例,在实施本发明实施例时,可以根据实际情况设置其他计算n个线程进队push的偏移量的处理方法,本发明实施例对此不加以限制。另外,除了上述计算n个线程进队push的偏移量的处理方法外,本领域技术人员还可以根据实际需要采用其它计算n个线程进队push的偏移量的处理方法,本发明实施例对此也不加以限制。
子步骤S13,依据所述n个线程进队push的偏移量,分别计算所述n个线程进队push的实际位置Pos;
在具体实现中,为了保证写入数据不超出消息队列的范围,可以分别计算所述n个线程进队push的实际位置。
在本发明的一种优选实施例中,所述子步骤S13具体可以包括如下子步骤:
子步骤A301,读取所述消息队列大小参数Size的值;
子步骤A302,采用所述Size的值对所述Pushpos的值取模,获得对应的n个线程进队push的实际位置Pos。
在实际应用中,Pos=Pushpos%Size,n个线程进队push的偏移量各不相同,因此,n个线程进队push的实际位置Pos也各不相同。这个时候实际位置Pos只有当前线程独自占有。
当然,上述计算n个线程进队push的实际位置Pos的处理方法只是作为示例,在实施本发明实施例时,可以根据实际情况设置其他计算n个线程进队push的实际位置Pos的处理方法,本发明实施例对此不加以限制。另外,除了上述计算n个线程进队push的实际位置Pos的处理方法外,本领域技术人员还可以根据实际需要采用其它计算n个线程进队push的实际位置Pos的处理方法,本发明实施例对此也不加以限制。
子步骤S14,所述n个线程分别在其进队push的实际位置Pos执行进队push操作;
在具体应用中,计算出了n个线程进队push的实际位置Pos,就可以在其进队push的实际位置Pos执行进队push操作。
子步骤S15,执行单线程出队pop的操作;
在具体实现中,单线程出队pop的操作可以有序地将数据读取出来。
在本发明的一种优选实施例中,所述子步骤S15具体可以包括如下子步骤:
子步骤A401,单个线程依次在所述消息队列中执行出队pop操作。
在实际应用中,出队pop操作与进队push操作可以同时进行,单个线程有序的读取消息队列中的数据。
通过采用消息队列执行多线程进队push以及单线程出队pop的操作,利用原子操作计算多线程进队push的偏移量,避免了多线程进队push对应的偏移量互相重复,从而计算出多线程进队push不同的实际位置,保证了多线程访问操作不碰撞,利用单个线程依次有序执行出队pop操作,解决了线程间通信时阻塞的问题,减少了资源消耗,充分利用了系统资源,提高了处理速度,从而提高了服务器吞吐量。
为便于本领域技术人员更好地理解本发明,以下通过一个具体示例简单说明多线程进队push的方法。
参照图3,示出了根据本发明一个实施例的一种多线程进队push的示意图。如图3所示,Thread1、Thread2、Thread3、Thread4分别是线程1、线程2、线程3、线程4,图示中消息队列的各个方格表示实际位置。
在具体应用中,线程1、线程2、线程3、线程4分别执行进队push操作,线程1读取可写计数参数CanWriteCount的值,采用原子操作递减CanWriteCount的值,获得递减后的CanWriteCount的值不为0,然后,读取进队push的偏移量Pushpos的值,采用偏移量Pushpos的值执行迭代增加操作,获得该线程进队push的偏移量,之后,读取消息队列大小参数Size的值,采用Size的值对Pushpos的值取模,得到实际位置,如图3所示的消息队列中第5个方格,此时,第5个方格只有线程1独自占有,线程1在第5个方格执行进队push操作。线程3读取线程1递减后的可写计数参数CanWriteCount的值,在其基础之上执行递减CanWriteCount的值的操作,获得递减后的CanWriteCount的值也不为0,然后,读取线程1进队push的偏移量,在其基础之上执行迭代增加Pushpos的值的操作,采用Size的值对Pushpos的值取模,得到实际位置,如图3所示的消息队列中第6个方格,此时,第6个方格只有线程3独自占有,线程3在第6个方格执行进队push操作。线程4、线程2也按上述方法分别在如图3所示的消息队列中第7个方格、第8个方格执行进队push操作。
步骤102,将所述单线程出队pop的数据写入共享内存;
需要说明的是,在本发明实施例中,共享内存指基于环形缓冲区的共享内存,顾名思义这个缓冲区是环形的,所谓环形,就是用一个指针去访问该缓冲区的最后一个内存位置的后一位置时回到环形缓冲区的起点。环形缓冲区通常有一个读指针和一个写指针,读指针指向环形缓冲区中可读的缓冲区,写指针指向环形缓冲区中可写的缓冲区。通过移动读指针和写指针就可以实现缓冲区的数据读取和写入。在通常情况下,环形缓冲区的读操作仅仅会影响读指针,而写操作仅仅会影响写指针。
在实际应用中,将所述单线程出队pop的数据写入共享内存中可以不加锁地实现,共享内存可以支持同时执行写入操作和读取操作。
在本发明的一种优选实施例中,所述步骤102具体可以包括如下子步骤:
子步骤S201,获得所述单线程出队pop的数据及其长度;
需要说明的是,在本发明实施例中,所述数据即为数据,需要将数据以及数据长度写入共享内存。
子步骤S202,检查所述数据的长度是否超出共享内存的长度界限;
在具体实现中,共享内存的长度是有限的,长度超过共享内存最大长度的数据是不合法的,将不能被写入共享内存中。
子步骤S203,若否,则获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
在实际应用中,当数据的长度未超出共享内存的长度界限,判定数据合法,可以写入共享内存中,获取所述共享内存的读偏移指针pRead和写偏移指针pWrite。更具体地,当数据的长度超共享内存的最大长度时,判定数据不合法,禁止写入。
在本发明的一种优选实施例中,所述子步骤S203具体可以包括如下子步骤:
子步骤B101,获得所述共享内存的映射文件,所述映射文件包括文件头;
子步骤B102,从所述文件头中读取写偏移指针pWrite;
子步骤B103,从所述文件头中读取读偏移指针pRead并快照到临时变量中。
在具体应用中,采用内存映射的方式,打开控制内存文件。内存文件数据结构可以包括:文件头、文件size、Read指针、Write指针、文件头结束、实际数据,如图4所示,示出了根据本发明一个实施例的一种内存文件数据结构的示意图。读取内存文件数据结构的Read指针和Write指针即可以获取所述共享内存的读偏移指针pRead和写偏移指针pWrite。并将读偏移指针pRead快照到临时变量中,记录当前读偏移指针pRead的位置。
上述获取读偏移指针pRead和写偏移指针pWrite的读写方法只是作为示例,在实施本发明实施例时,可以根据实际情况设置其他获取读偏移指针pRead和写偏移指针pWrite的读写方法,本发明实施例对此不加以限制。另外,除了上述获取读偏移指针pRead和写偏移指针pWrite的读写方法外,本领域技术人员还可以根据实际需要采用其它获取读偏移指针pRead和写偏移指针pWrite的读写方法,本发明实施例对此也不加以限制。
本发明通过获得所述共享内存的映射文件,所述映射文件包括文件头,从所述文件头中读取读偏移指针pRead并快照到临时变量中,记录了当前读偏移指针pRead的位置,从而保证了在执行当前写操作的内存不会随读偏移指针pRead的变化而被修改,即读操作和写操作可以同时进行,并且,保证了写偏移指针pWrite不会与读偏移指针pRead产生冲突,因此能够充分利用系统资源,解决进程间通信时阻塞的问题,减少资源消耗,从而提高服务器吞吐量。
子步骤S204,依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写;
在具体实现中,数据在共享内存中的写入位置可以由写偏移指针pWrite决定。数据的长度在由读偏移指针pRead和写偏移指针pWrite组成的可写数据的长度范围之内时,数据可写;数据的长度在由读偏移指针pRead和写偏移指针pWrite组成的可写数据的长度范围之外时,数据不可写。
在本发明的一种优选实施例中,所述子步骤S204具体可以包括如下子步骤:
子步骤B201,依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
子步骤B202,当所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,判定所述数据可写。
在具体应用中,数据从写偏移指针pWrite位置开始执行写操作,数据在共享内存中的写入位置由写偏移指针pWrite确定。由于数据是合法的,因此,把环状的数据变成文件顺序的数据,通过边缘控制模拟环形运动,则可以用pRead==pWrite表示读偏移指针pRead和写偏移指针pWrite处于同一位置时,即共享内存为空,数据的长度未超出共享内存的长度界限,判定所述数据可写。
在本发明的另一种优选实施例中,所述子步骤S204具体可以包括如下子步骤:
子步骤B301,依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
子步骤B302,当所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,设置可写数据的长度小于或等于allsize-pRead+pWrite-head,其中allsize为共享内存的长度,所述head为文件头的长度;
子步骤B303,判断所述数据的长度是否小于或等于所述可写数据的长度;
子步骤B304,若是,则判定所述数据可写;
子步骤B305,若否,则判定所述数据不可写。
在实际应用中,把环状的数据变成文件顺序的数据,通过边缘控制模拟环形运动,则可以用pRead<pWrite表示所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置,数据在共享内存中的写入位置可以为从写偏移指针pWrite到环形缓冲区终点的位置,还可以有另一部分为从文件头结束的位置到读偏移指针pRead,因此,设置可写数据的长度小于或等于allsize-pRead+pWrite-head,分别读取内存文件数据结构的文件头和文件size可以获得所述head和所述allsize。当所述数据的长度小于或等于所述可写数据的长度时,判定所述数据可写;当所述数据的长度大于所述可写数据的长度时,判定所述数据不可写。
在本发明的另一种优选实施例中,所述子步骤S204具体可以包括如下子步骤:
子步骤B401,依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
子步骤B402,当所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,设置可写数据的长度小于或等于pRead-pWrite;
子步骤B403,判断所述数据的长度是否小于或等于所述可写数据的长度;
子步骤B404,若是,则判定所述数据可写;
子步骤B405,若否,则判定所述数据不可写。
在具体应用中,把环状的数据变成文件顺序的数据,通过边缘控制模拟环形运动,则可以用pRead>pWrite表示所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置,可写数据的长度小于或等于pRead-pWrite,当所述数据的长度小于或等于所述可写数据的长度时,判定所述数据可读;当所述数据的长度大于所述可写数据的长度时,判定所述数据不可写。
子步骤S205,若是,则在所述写入位置写入所述数据。
在实际应用中,每一个数据所在共享内存的位置不一定都相同,需要根据数据所在共享内存不同的位置开始写入数据。
在本发明的一种优选实施例中,所述子步骤S205具体可以包括如下子步骤:
子步骤B501,当所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,或,当所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,则从当前写偏移指针pWrite位置开始写入所述数据;
子步骤B502,当写入到所述共享内存尾部的位置时,判断所述数据是否已全部写入;
子步骤B503,若否,则从所述共享内存中文件头结束的位置开始继续写入所述数据,直至在所述读偏移指针pRead位置之前写入全部的数据。
在具体实现中,当所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,或,当所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,即pRead==pWrite或pRead<pWrite时,数据所在共享内存中的写入位置可以为从写偏移指针pWrite到环形缓冲区终点的位置,还可以有另一部分为从文件头结束的位置到读偏移指针pRead,因此,数据所在共享内存的位置为allsize-pRead+pWrite-head的范围内。从当前写偏移指针pWrite位置开始写入所述数据,当写入到所述共享内存尾部的位置时,若数据已全部写入,则完成当前写操作;若数据未全部写入,从所述共享内存中文件头结束的位置开始继续写入所述数据,可以在所述读偏移指针pRead位置之前写入全部的数据。更具体而言,采用内存拷贝memcpy的方式写入所述数据。
在本发明的另一种优选实施例中,所述子步骤S205具体可以包括如下子步骤:
子步骤B601,当所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,则从当前写偏移指针pWrite位置开始写入所述数据;
子步骤B602,在所述读偏移指针pRead位置之前写入全部的数据。
在具体实现中,当所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,即pRead>pWrite,数据所在共享内存的位置即为pRead-pWrite的范围内,从当前写偏移指针pWrite位置开始写入所述数据,可以在不超过所述读偏移指针pRead位置读出全部的数据。更具体而言,采用内存拷贝memcpy的方式写入所述数据。
本发明通过采用内存拷贝memcpy的方式写入所述数据的方式,能够快速地将数据写入共享内存中,从而提高处理速度,提高服务器吞吐量。
本发明通过获得数据及其长度,在写入数据的长度不超出共享内存的长度界限的情况下获取所述共享内存的读偏移指针pRead和写偏移指针pWrite,可以不加锁的控制写入数据,避免了加锁造成的阻塞的问题,从而减少资源消耗,充分利用系统资源,提高处理速度,提高服务器吞吐量。
当然,上述写入所述数据的处理方法只是作为示例,在实施本发明实施例时,可以根据实际情况设置其他写入所述数据的处理方法,本发明实施例对此不加以限制。另外,除了上述写入所述数据的处理方法外,本领域技术人员还可以根据实际需要采用其它写入所述数据的处理方法,本发明实施例对此也不加以限制。
参照图5,示出了根据本发明一个实施例的一种基于消息队列的共享内存读取方法实施例的步骤流程图,所述消息队列包括第二消息队列,具体可以包括如下步骤:
步骤201,从共享内存中读取数据;
在实际应用中,从共享内存中读取数据可以不加锁地实现,并且,在共享内存中执行读取操作的同时可以执行写入操作。
在本发明的一种优选实施例中,所述步骤201具体可以包括如下子步骤:
子步骤S301,定位数据所在共享内存的位置;
在实际应用中,每个数据在内存上都有其映射地址,定位数据的映射地址可以定位出数据所在共享内存的位置。
子步骤S302,获得所述数据的长度;
需要说明的是,在本发明实施例中,每一条数据的协议可以包括协议头、协议版本、数据的长度(数据size)、循环冗余校验码(Cyclic Redundancy Check,CRC)、包名称(包id)、其他扩展以及实际写入的数据,具体可以参考如图6所示的根据本发明一个实施例的一种数据的协议的示意图。通过读取图6中的数据size即可以获得数据的长度。
当然,上述获得所述数据的长度的处理方法只是作为示例,在实施本发明实施例时,可以根据实际情况设置其他获得所述数据的长度的处理方法,本发明实施例对此不加以限制。另外,除了上述获得所述数据的长度的处理方法外,本领域技术人员还可以根据实际需要采用其它获得所述数据的长度的处理方法,本发明实施例对此也不加以限制。
在本发明的一种优选实施例中,所述步骤201还可以包括如下步骤:
若所述数据的长度超出共享内存的长度界限,则禁止写入。
在实际应用中,当数据的长度超共享内存的最大长度时,判定数据不合法,禁止写入。
子步骤S303,获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
需要说明的是,在本发明实施例中,可以把共享内存的读偏移指针pRead和写偏移指针pWrite想象成是两个人在体育场跑道上追逐,读偏移指针pRead追写偏移指针pWrite,则读偏移指针pRead和写偏移指针pWrite的使用可以包括以下原则:
1、只在pWrite追上pRead时候,pRead和pWrite重叠。不能是pRead追上pWrite。
2、pWrite不能从pRead后面追过去,追过去就覆盖了之前未读取的数据,此时数据用内存队列等待。
3、pRead不能追上pWrite,用一个字节隔离。pRead永远不会从后面追上pWrite。
在本发明的一种优选实施例中,所述子步骤S303具体可以包括如下子步骤:
子步骤C101,获得所述共享内存的映射文件,所述映射文件包括文件头;
子步骤C102,从所述文件头中读取读偏移指针pRead;
子步骤C103,从所述文件头中读取写偏移指针pWrite并快照到临时变量中。
在具体应用中,采用内存映射的方式,打开控制内存文件。内存文件数据结构可以包括:文件头、文件size、Read指针、Write指针、文件头结束、实际数据,具体可以参考如图4所示的本发明一种内存文件数据结构的示意图。通过读取图4中的Read指针和Write指针即可以获取所述共享内存的读偏移指针pRead和写偏移指针pWrite。并将写偏移指针pWrite快照到临时变量中,记录当前写偏移指针pWrite的位置。
上述获取读偏移指针pRead和写偏移指针pWrite的处理方法只是作为示例,在实施本发明实施例时,可以根据实际情况设置其他获取读偏移指针pRead和写偏移指针pWrite的处理方法,本发明实施例对此不加以限制。另外,除了上述获取读偏移指针pRead和写偏移指针pWrite的处理方法外,本领域技术人员还可以根据实际需要采用其它获取读偏移指针pRead和写偏移指针pWrite的处理方法,本发明实施例对此也不加以限制。
本发明通过获得所述共享内存的映射文件,所述映射文件包括文件头,从所述文件头中读取写偏移指针pWrite并快照到临时变量中,记录了当前写偏移指针pWrite的位置,从而保证了在执行当前读操作的内存不会随写偏移指针pWrite的变化而被修改,即读操作和写操作可以同时进行,并且,保证了读偏移指针pRead不会与写偏移指针pWrite产生冲突,因此能够充分利用系统资源,解决进程间通信时阻塞的问题,减少资源消耗,从而提高服务器吞吐量。
子步骤S304,依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,判断所述数据是否可读;
在具体实现中,数据的长度在由读偏移指针pRead和写偏移指针pWrite组成的可读数据的长度范围之内时,数据可读;数据的长度在由读偏移指针pRead和写偏移指针pWrite组成的可读数据的长度范围之外时,数据不可读。
在本发明的一种优选实施例中,所述子步骤S304具体可以包括如下子步骤:
子步骤C201,当所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,设置可读数据的长度小于或等于pWrite-pRead;
子步骤C202,判断所述数据的长度是否小于或等于所述可读数据的长度;
子步骤C203,若是,则判定所述数据可读;
子步骤C204,若否,则判定所述数据不可读。
需要说明的是,在本发明实施例中,由于共享内存具有环形的特性,即一个指针去访问该缓冲区的最后一个内存位置的后一位置时回到环形缓冲区的起点,可以想像共享内存为环形缓冲区的起点和终点首尾相接的环,以环形缓冲区的起点作为参考,假设写偏移指针pWrite和读偏移指针pRead按照顺时针方向移动,当写偏移指针pWrite相对于环形缓冲区的起点的偏移量大于读偏移指针pRead相对于环形缓冲区的起点的偏移量时,则读偏移指针pRead处于所述写偏移指针pWrite后面的位置;当写偏移指针pWrite相对于环形缓冲区的起点的偏移量小于读偏移指针pRead相对于环形缓冲区的起点的偏移量时,则读偏移指针pRead处于所述写偏移指针pWrite前面的位置。
在具体应用中,把环状的数据变成文件顺序的数据,通过边缘控制模拟环形运动,则可以用pRead<pWrite表示所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置,可读数据的长度小于或等于pWrite-pRead,当所述数据的长度小于或等于所述可读数据的长度时,判定所述数据可读;当所述数据的长度大于所述可读数据的长度时,判定所述数据不可读。
在本发明的另一种优选实施例中,所述子步骤S304具体可以包括如下子步骤:
子步骤C301,当所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,设置可读数据的长度小于或等于allsize-pRead+pWrite-head,其中,所述allsize为共享内存的长度,所述head为文件头的长度;
子步骤C302,判断所述数据的长度是否小于或等于所述可读数据的长度;
子步骤C303,若是,则判断所述数据可读;
子步骤C304,若否,则判定所述数据不可读。
在具体实现中,把环状的数据变成文件顺序的数据,通过边缘控制模拟环形运动,则可以用pRead>pWrite表示所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置,数据所在共享内存的位置可以为从读偏移指针pRead到环形缓冲区终点的位置,还可以有另一部分为从文件头结束的位置到写偏移指针pWrite,因此,设置可读数据的长度小于或等于allsize-pRead+pWrite-head,分别读取内存文件数据结构的文件头和文件size可以获得所述head和所述allsize。当所述数据的长度小于或等于所述可读数据的长度时,判定所述数据可读;当所述数据的长度大于所述可读数据的长度时,判定所述数据不可读。
在本发明的另一种优选实施例中,所述子步骤S304具体可以包括如下子步骤:
子步骤C401,当所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,则判定所述数据不可读。
在具体应用中,把环状的数据变成文件顺序的数据,通过边缘控制模拟环形运动,则可以用pRead==pWrite表示所述读偏移指针pRead和写偏移指针pWrite处于同一位置,判定此时数据不可读,返回数据为空。
当然,上述判断所述数据是否可读的处理方法只是作为示例,在实施本发明实施例时,可以根据实际情况设置其他判断所述数据是否可读的处理方法,本发明实施例对此不加以限制。另外,除了上述判断所述数据是否可读的处理方法外,本领域技术人员还可以根据实际需要采用其它判断所述数据是否可读的处理方法,本发明实施例对此也不加以限制。
子步骤S305,若是,则从所述数据所在共享内存的位置,读出所述数据。
在实际应用中,每一个数据所在共享内存的位置不一定都相同,需要根据数据所在共享内存不同的位置开始读出数据。
在本发明的一种优选实施例中,所述子步骤S305具体可以包括如下子步骤:
子步骤C501,当所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,则从当前读偏移指针pRead位置开始读出所述数据;
子步骤C502,在不超过所述写偏移指针pWrite位置读出全部的数据。
在具体实现中,当所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,即pRead<pWrite,数据所在共享内存的位置即为pWrite-pRead的范围内,从当前读偏移指针pRead位置开始读出所述数据,可以在不超过所述写偏移指针pWrite位置读出全部的数据。更具体而言,采用内存拷贝memcpy的方式读出所述数据。
在本发明的另一种优选实施例中,所述子步骤S305具体可以包括如下子步骤:
子步骤C601,当所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,则从当前读偏移指针pRead位置开始读出所述数据;
子步骤C602,当读取至所述共享内存尾部的位置时,判断所述数据是否已全部读出;
子步骤C603,若否,则从所述共享内存中文件头结束的位置开始继续读出所述数据,直至在不超过所述写偏移指针pWrite位置读出全部的数据。
在具体实现中,当所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,即pRead>pWrite,数据所在共享内存的位置可以为从读偏移指针pRead到环形缓冲区终点的位置,还可以有另一部分为从文件头结束的位置到写偏移指针pWrite,因此,数据所在共享内存的位置为allsize-pRead+pWrite-head的范围内。从当前读偏移指针pRead位置开始读出所述数据,当读取至所述共享内存尾部的位置时,若数据已全部读出,则完成当前读操作;若数据未全部读出,则从所述共享内存中文件头结束的位置开始继续读出所述数据,可以在不超过所述写偏移指针pWrite位置读出全部的数据。更具体而言,采用内存拷贝memcpy的方式读出所述数据。
本发明通过采用内存拷贝memcpy的方式读出所述数据的方式,能够快速地将数据从共享内存中读出,从而提高处理速度,提高服务器吞吐量。
本发明通过定位数据所在共享内存的位置,获取数据的长度,以及,共享内存的读偏移指针pRead和写偏移指针pWrite,可以不加锁的控制读出数据,避免了加锁造成的阻塞的问题,从而减少资源消耗,充分利用系统资源,提高处理速度,提高服务器吞吐量。
当然,上述读出所述数据的处理方法只是作为示例,在实施本发明实施例时,可以根据实际情况设置其他读出所述数据的处理方法,本发明实施例对此不加以限制。另外,除了上述读出所述数据的处理方法外,本领域技术人员还可以根据实际需要采用其它读出所述数据的处理方法,本发明实施例对此也不加以限制。
在本发明的一种优选实施例中,所述步骤201还可以包括如下子步骤:
子步骤S306,若所述数据不可读,则返回数据为空。
在具体应用中,若数据大于可读数据的长度,即超过由读偏移指针pRead和写偏移指针pWrite组成的可读数据的长度的范围,则返回数据为空。
步骤202,将读出的数据通过单线程进队push的操作压入所述第二消息队列,同时,采用所述第二消息队列执行多线程出队pop的操作;
在实际应用中,单线程进队push的操作是指采用原子操作执行单个线程进队push的操作,多线程出队pop的操作是指采用原子操作执行多个线程出队pop的操作,单线程进队push和多线程出队pop的操作可以同时进行。
在本发明的一种优选实施例中,所述步骤202具体可以包括如下子步骤:
子步骤S401,执行单线程进队push的操作;
在实际应用中,单线程进队push的操作可以有序地将数据写入第二消息队列。
在本发明的一种优选实施例中,所述子步骤S401具体可以包括如下子步骤:
子步骤D101,单个线程依次在所述消息队列中执行进队push操作;
在实际应用中,出队pop操作与进队push操作可以同时进行,单个线程有序的写入数据到消息队列中。
子步骤S402,判断所述消息队列是否已空;
在具体实现中,当消息队列为已空时,将禁止在消息队列中读取数据。
在本发明的一种优选实施例中,所述子步骤S402具体可以包括如下子步骤:
子步骤D201,读取可读计数参数CanReadCount的值;
子步骤D202,递减所述CanReadCount的值;
子步骤D203,若获得递减后的CanReadCount的值为0,则判定所述消息队列为已空,否则,判定所述消息队列为未空。
在具体应用中,多线程进队pop操作时,每一个线程分别读取对应的可读计数参数CanReadCount的值,采用原子操作递减CanReadCount的值,若获得递减后的CanReadCount的值为0,则判定所述消息队列为已空,否则,判定所述消息队列为未空。若所述消息队列已空,则禁止执行出队pop的操作。
通过判断消息队列已空时,禁止执行出队pop的操作,保证了读取数据时的安全性与准确性,从而保证多线程访问成功,解决了线程间通信时阻塞的问题,从而提高服务器吞吐量。
当然,上述判断消息队列是否为已空的处理方法只是作为示例,在实施本发明实施例时,可以根据实际情况设置其他判断消息队列是否为已空的处理方法,本发明实施例对此不加以限制。另外,除了上述判断消息队列是否为已空的处理方法外,本领域技术人员还可以根据实际需要采用其它判断消息队列是否为已空的处理方法,本发明实施例对此也不加以限制。
子步骤S403,若否,则分别计算n个线程出队pop的偏移量;所述n为大于或等于1的正整数;
在实际应用中,n个线程出队pop操作时,每个线程都是采用原子操作递加的方式,计算出来n个线程出队pop的偏移量各不相同。
在本发明的一种优选实施例中,所述子步骤S403具体可以包括如下子步骤:
子步骤D301,读取出队pop的偏移量Poppos的值;
子步骤D302,针对所述n个线程迭代增加所述Poppos的值,分别获得所述n个线程出队pop的偏移量。
在具体实现中,一个线程读取出队pop的偏移量Poppos的值,采用当前偏移量Poppos的值执行迭代增加操作,获得该线程出队pop的偏移量,下一个线程读取迭代增加操作后的出队pop的偏移量Poppos的值,执行迭代增加操作,获得此线程出队pop的偏移量,按上述方法依次针对所述n个线程迭代增加所述Poppos的值,分别获得所述n个线程出队pop的偏移量。
当然,上述计算n个线程出队pop的偏移量的处理方法只是作为示例,在实施本发明实施例时,可以根据实际情况设置其他计算n个线程出队pop的偏移量的处理方法,本发明实施例对此不加以限制。另外,除了上述计算n个线程出队pop的偏移量的处理方法外,本领域技术人员还可以根据实际需要采用其它计算n个线程出队pop的偏移量的处理方法,本发明实施例对此也不加以限制。
子步骤S404,依据所述n个线程出队pop的偏移量,分别计算所述n个线程出队pop的实际位置Pos;
在具体实现中,为了保证读取数据不超出消息队列的范围,可以分别计算所述n个线程出队pop的实际位置。
在本发明的一种优选实施例中,所述子步骤S404具体可以包括如下子步骤:
子步骤D401,读取所述消息队列大小参数Size的值;
子步骤D402,采用所述Size的值对所述Poppos的值取模,获得对应的n个线程进队pop的实际位置Pos。
在实际应用中,Pos=Poppos%Size,n个线程出队pop的偏移量各不相同,因此,n个线程出队pop的实际位置Pos也各不相同。这个时候实际位置Pos只有当前线程独自占有。
当然,上述计算n个线程出队pop的实际位置Pos的处理方法只是作为示例,在实施本发明实施例时,可以根据实际情况设置其他计算n个线程出队pop的实际位置Pos的处理方法,本发明实施例对此不加以限制。另外,除了上述计算n个线程出队pop的实际位置Pos的处理方法外,本领域技术人员还可以根据实际需要采用其它计算n个线程出队pop的实际位置Pos的处理方法,本发明实施例对此也不加以限制。
子步骤S405,所述n个线程分别在其出队pop的实际位置执行出队pop操作。
在具体应用中,计算出了n个线程出队pop的实际位置Pos,就可以在其出队pop的实际位置Pos执行出队pop操作。
为便于本领域技术人员更好地理解本发明,以下通过一个具体示例简单说明多线程出队pop的方法。
参照图7,示出了本发明一种多线程出队pop的示意图。如图7所示,Thread1、Thread2、Thread3分别是线程1、线程2、线程3,图示中消息队列的各个方格表示实际位置。
在具体应用中,线程1、线程2、线程3分别执行出队pop操作,线程2读取可读计数参数CanReadCount的值,采用原子操作递减CanReadCount的值,获得递减后的CanReadCount的值不为0,然后,读取出队pop的偏移量Poppos的值,采用偏移量Poppos的值执行迭代增加操作,获得该线程出队pop的偏移量,之后,读取消息队列大小参数Size的值,采用Size的值对Poppos的值取模,得到实际位置,如图7所示的消息队列中第1个方格,此时,第1个方格只有线程2独自占有,线程2在第1个方格执行出队pop操作。线程1读取线程2递减后的可读计数参数CanReadCount的值,在其基础之上执行递减CanReadCount的值的操作,获得递减后的CanReadCount的值也不为0,然后,读取线程2出队pop的偏移量,在其基础之上执行迭代增加Poppos的值的操作,采用Size的值对Poppos的值取模,得到实际位置,如图7所示的消息队列中第2个方格,此时,第2个方格只有线程1独自占有,线程1在第2个方格执行出队pop操作。线程3也按上述方法在如图7所示的消息队列中第3个方格执行出队pop操作。
通过采用消息队列执行单线程进队push以及多线程出队pop的操作,利用原子操作计算多线程出队pop的偏移量,避免了多线程出队pop对应的偏移量互相重复,从而计算出多线程出队pop不同的实际位置,保证了多线程访问操作不碰撞,利用单个线程依次有序执行进队push操作,解决了线程间通信时阻塞的问题,减少了资源消耗,充分利用了系统资源,提高了处理速度,从而提高了服务器吞吐量。
参照图8,示出了根据本发明一个实施例的一种基于消息队列的共享内存读写方法实施例的步骤流程图,所述消息队列包括第一消息队列和第二消息队列,具体可以包括如下步骤:
步骤301,采用第一消息队列执行多线程进队push以及单线程出队pop的操作;
在具体实现中,通过一个第一消息队列执行多线程进队push以及单线程出队pop的操作,数据就可以被写入共享内存。
在本发明的一种优选实施例中,所述步骤301具体可以包括如下子步骤:
子步骤S501,读取可写计数参数CanWriteCount的值;
子步骤S502,递减所述CanWriteCount的值;
子步骤S503,若获得递减后的CanWriteCount的值不为0,则判定所述第一消息队列为未满;
子步骤S504,在所述第一消息队列未满时,分别计算n个线程进队push的偏移量;所述n为大于或等于1的正整数;
子步骤S505,依据所述n个线程进队push的偏移量,分别计算所述n个线程进队push的实际位置;
子步骤S506,所述n个线程分别在其进队push的实际位置执行进队push操作;
子步骤S507,读取可读计数参数CanReadCount的值;
子步骤S508,按照所述n个线程进队push的操作,迭代增加所述CanReadCount的值。
在具体实施中,可以采用可写计数参数CanWriteCount的值判断消息队列是否已满,可写计数参数CanWriteCount的值为0,则消息队列已满,否则为未满。n的取值取决于任务数量,一个任务分配一个线程,偏移量是指存储单元的实际地址与其所在段的段地址之间的距离,n个线程进队push操作时,每个线程都是采用原子操作递加的方式,计算出来n个线程进队push的偏移量各不相同。为了保证写入数据不超出消息队列的范围,可以采用n个线程进队push的偏移量分别计算所述n个线程进队push的实际位置Pos。计算出了n个线程进队push的实际位置Pos,就可以在其进队push的实际位置Pos执行进队push操作。可读计数参数CanReadCount是判断消息队列是否已空的依据,可读计数参数CanReadCount的值为0时,消息队列已空,否则消息队列未空。
具体地,执行多线程进队push操作时,每一个线程分别读取对应的可写计数参数CanWriteCount的值,采用原子操作递减CanWriteCount的值,若获得递减后的CanWriteCount的值为0,则判定所述第一消息队列为已满,否则,判定所述第一消息队列为未满。若所述第一消息队列已满,则禁止执行进队push的操作。一个线程读取进队push的偏移量Pushpos的值,采用当前偏移量Pushpos的值执行迭代增加操作,获得该线程进队push的偏移量,下一个线程读取迭代增加操作后的进队push的偏移量Pushpos的值,执行迭代增加操作,获得此线程进队push的偏移量,按上述方法依次针对所述n个线程迭代增加所述Pushpos的值,分别获得所述n个线程进队push的偏移量。n个线程进队push的实际位置Pos=Pushpos%Size,由于n个线程进队push的偏移量各不相同,因此,n个线程进队push的实际位置Pos也各不相同。这个时候实际位置Pos只有当前线程独自占有。当前线程在独自占有的实际位置Pos执行进队push的操作,同时,读取可读计数参数CanReadCount的值,迭代增加所述CanReadCount的值。
当然,上述执行多线程进队push的操作将数据写入第一消息队列的处理方法只是作为示例,在实施本发明实施例时,可以根据实际情况设置其他执行多线程进队push的操作将数据写入第一消息队列的处理方法,本发明实施例对此不加以限制。另外,除了上述执行多线程进队push的操作将数据写入第一消息队列的处理方法外,本领域技术人员还可以根据实际需要采用其它执行多线程进队push的操作将数据写入第一消息队列的处理方法,本发明实施例对此也不加以限制。
步骤302,将所述单线程出队pop的数据写入共享内存;
在具体应用中,所述单线程出队pop的数据可以不加锁的写入共享内存。
在本发明的一种优选实施例中,所述步骤302具体可以包括如下子步骤:
子步骤S601,获得所述单线程出队pop的数据及其长度;
子步骤S602,检查所述数据的长度是否超出共享内存的长度界限;
子步骤S603,若否,则获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
子步骤S604,依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写;
子步骤S605,若是,则在所述写入位置写入所述数据;
在具体实施中,当完成了单线程出队pop的操作后,可以获得单线程出队pop的数据及其长度,该数据的长度不能超过共享内存的最大长度,当该数据的长度在共享内存的长度界限内时,可以获得共享内存的映射文件,映射文件可以包括文件头,可以获得文件头中包括的写偏移指针pWrite和读偏移指针pRead,并将读偏移指针pRead快照到临时变量中,这样在进行写操作的时候与临时变量中的读偏移指针pRead不会发生变化,写操作中写偏移指针pWrite的位置不可以超过临时变量中的读偏移指针pRead的位置,依据读偏移指针pRead和写偏移指针pWrite的相对位置决定写入数据所在共享内存中的位置,结合数据的长度确定开始和结束写入数据时的位置。
步骤303,从所述共享内存中读取数据;
在具体应用中,从所述共享内存中读取数据可以不加锁的实现。读取数据和写入数据的操作可以同时进行,当次写入的数据可以在后一次读取数据的操作中读取。
在本发明的一种优选实施例中,所述步骤303具体可以包括如下子步骤:
子步骤S701,定位待读取数据所在共享内存的位置;
子步骤S702,获得所述待读取数据的长度;
子步骤S703,获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
子步骤S704,依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述待读取数据的长度,判断所述待读取数据是否可读;
子步骤S705,若是,则从所述待读取数据所在共享内存的位置,读出所述待读取数据;
在具体实施中,可以定位数据所在共享内存的位置,并获得数据的长度,读取共享内存的映射文件的文件头,可以获取读偏移指针pRead和写偏移指针pWrite,并把写偏移指针pWrite快照到临时变量中,这样执行写操作而移动写偏移指针pWrite的位置时,读操作的内存由于把写偏移指针pWrite快照到临时变量中可以不发生改变,因而读操作和写操作可以同时进行。根据读偏移指针pRead和写偏移指针pWrite的相对位置决定数据所在共享内存中的位置,并结合数据的长度决定开始和结束读取数据的位置。
步骤304,将读出的数据通过单线程进队push的操作压入所述第二消息队列,同时,采用所述第二消息队列执行多线程出队pop的操作;
在具体应用中,数据最终是由多线程读取,采用执行多线程出队pop的操作从所述第二消息队列中读取所述数据可以不加锁的实现,并且进队push和出队pop操作可以同时进行。
在本发明的一种优选实施例中,所述步骤304具体可以包括如下子步骤:
子步骤S801,读取可读计数参数CanReadCount的值;
子步骤S802,递减所述CanReadCount的值;
子步骤S803,若获得递减后的CanReadCount的值不为0,则判定所述第二消息队列为未空;
子步骤S804,在所述消息队列未空时,分别计算n个线程出队pop的偏移量;所述n为大于或等于1的正整数;
子步骤S805,依据所述n个线程出队pop的偏移量,分别计算所述n个线程出队pop的实际位置;
子步骤S806,所述n个线程分别在其出队pop的实际位置执行出队pop操作;
子步骤S807,读取可写计数参数CanWriteCount的值;
子步骤S808,按照所述n个线程出队pop的操作,迭代增加所述CanWriteCount的值。
在具体实施中,可以采用读取可读计数参数CanReadCount的值判断消息队列是否已空,读取可读计数参数CanReadCount的值为0,则消息队列已空,否则为未空。n个线程出队pop操作时,每个线程都是采用原子操作递加的方式,计算出来n个线程出队pop的偏移量各不相同。为了保证读取数据不超出消息队列的范围,可以分别计算所述n个线程出队pop的实际位置。计算出了n个线程出队pop的实际位置Pos,就可以在其出队pop的实际位置Pos执行出队pop操作。可写计数参数CanWriteCount是判断消息队列是否已满的依据,可写计数参数CanWriteCount的值为0时,消息队列已满,否则消息队列为未满。
具体而言,多线程进队pop操作时,每一个线程分别读取对应的可读计数参数CanReadCount的值,采用原子操作递减CanReadCount的值,若获得递减后的CanReadCount的值为0,则判定所述消息队列为已空,否则,判定所述消息队列为未空。若所述消息队列已空,则禁止执行出队pop的操作。一个线程读取出队pop的偏移量Poppos的值,采用当前偏移量Poppos的值执行迭代增加操作,获得该线程出队pop的偏移量,下一个线程读取迭代增加操作后的出队pop的偏移量Poppos的值,执行迭代增加操作,获得此线程出队pop的偏移量,按上述方法依次针对所述n个线程迭代增加所述Poppos的值,分别获得所述n个线程出队pop的偏移量。Pos=Poppos%Size,n个线程出队pop的偏移量各不相同,因此,n个线程出队pop的实际位置Pos也各不相同。这个时候实际位置Pos只有当前线程独自占有。当前线程在独自占有的实际位置Pos执行出队pop的操作,同时,读取可写计数参数CanWriteCount的值,迭代增加所述CanWriteCount的值。
本发明通过第一消息队列、第二消息队列以及共享内存的组合进行通信,数据的处理速度相当于内存拷贝数据的速度,突破了传输的瓶颈,从而提高服务器吞吐量。
本发明通过采用第一消息队列执行多线程进队push以及单线程出队pop的操作,和,采用第二消息队列执行单线程进队push以及多线程出队pop的操作,可以保证多线程访问操作不碰撞,避免使用互斥锁来解决多线程并发争用安全性的问题,并且,多线程进队push和单线程出队pop的操作可以同时进行,解决了线程间通信时阻塞的问题,减少了资源消耗,充分利用了系统资源,提高了处理速度,从而提高了服务器吞吐量。
本发明通过将所述数据写入共享内存,可以不加锁的控制写入数据,避免了加锁造成的阻塞的问题,从而减少资源消耗,充分利用系统资源,提高处理速度,提高服务器吞吐量。
本发明通过从所述共享内存中读取所述数据,可以不加锁的控制读出数据,避免了加锁造成的阻塞的问题,从而减少资源消耗,充分利用系统资源,提高处理速度,提高服务器吞吐量。
参照图9,示出了根据本发明一个实施例的一种基于消息队列的共享内存写入方法实施例2的步骤流程图,所述消息队列包括第一消息队列,具体可以包括如下步骤:
步骤401,在存在多个消息队列时,选定用于当前通信的第一消息队列;
在实际应用中,当采用多个消息队列进行通信时,数据可以分段发送,所有分段数据可以自由选择消息队列进行通信,可能会出现某一消息队列上负载的分段数据远远超过其他消息队列,会影响处理速度,造成各个CPU使用率不均衡,因此,需要选定用于当前通信的第一消息队列以均衡多个消息队列的负载。
在本发明的一种优选实施例中,所述步骤401具体可以包括如下子步骤:
子步骤S901,读取所述数据的协议中的上下文参数intnId;
子步骤S902,采用所述上下文参数intnId对所述多个消息队列的个数取模;
子步骤S903,提取所述取模的值对应的消息队列为用于当前通信的第一消息队列。
在具体应用中,数据的协议中设置上下文参数intnId,每一段数据分配一个上下文参数intnId,后一段数据的上下文参数intnId通过前一段数据的上下文参数intnId执行原子操作加得到,然后每一段数据选择缓冲通道时,采用该段数据对应的上下文参数intnId对缓冲通道的个数进行取模操作,采用取模操作后得到的值确定为数据发送时采用的对应序号的缓冲通道,以及,关联为同一段数据返回时采用的关联序号的缓冲通道。
新增一段数据,上下文参数intnId就执行一次原子操作加,这样取模得到的数目就均衡了,每一个缓冲通道都均衡地有任务可以执行。而且保证同一段数据发送和返回使用的缓冲通道相互关联。
步骤402,采用所述消息队列执行多线程进队push以及单线程出队pop的操作;
步骤403,将所述单线程出队pop的数据写入共享内存;
本实施例与上述写入方法实施例1的区别之处在于,本实施例增加了在存在多个消息队列时,选定用于当前通信的第一消息队列。选定第一消息队列是为了均衡各个消息队列上的负载,提高处理速度,有效避免出现某个消息队列负载远远大于其他消息队列的负载的情况,从而减少各个CPU之间使用率的差值,提高服务器吞吐量。
为便于本领域技术人员更好地理解本发明步骤401,以下以多消息队列为例,简单说明在存在多个消息队列时,选定用于当前通信的第一消息队列的方法。
参照图10,示出了根据本发明一个实施例的一种采用多个消息队列通信的示意图。如图10所示,从上至下一共有5个第一消息队列、5个共享内存和5个第二消息队列,每一个共享内存和对应的一个第一消息队列以及对应的一个第二消息队列的组合都可以执行多线程写入数据和多线程读取数据。
具体而言,当有数据需要多个消息队列进行通信时,读取数据协议中的上下文参数intnId,每一个上下文参数intnId对应一段数据,采用上下文参数intnId对多个消息队列的个数取模,依据所述取模的值,确定所述上下文参数intnId对应的数据采用的消息队列。当同一段数据需要返回时,该段数据对应的上下文参数intnId在确定发送数据时采用的消息队列的同时,会关联返回消息队列中同一个序号的消息队列供返回数据时使用。即采用每一个上下文参数intnId除以缓冲通道的个数5,得到一个余数,依据这个余数,确定每一个上下文参数intnId对应的数据采用的消息队列,定义如图10所示的5个第一消息队列从上至下的序号分别为0、1、2、3、4,则取模得到的余数可以对应相同序号的消息队列,采用相同序号的消息队列进行通信。若上下文参数intnId取模得到的余数为0,则采用序号0的消息队列发送数据,当此上下文参数intnId对应的同一段数据需要返回时,则余数为0的上下文参数intnId采用关联序号0的返回消息队列返回数据,以保证发送和返回数据采用同一个序号的消息队列,从而保证采用相同的线程进行通信。
当然,上述均衡所述多个缓冲通道的负载的处理方法只是作为示例,在实施本发明实施例时,可以根据实际情况设置其他均衡所述多个缓冲通道的负载的处理方法,本发明实施例对此不加以限制。另外,除了上述均衡所述多个缓冲通道的负载的处理方法外,本领域技术人员还可以根据实际需要采用其它均衡所述多个缓冲通道的负载的处理方法,本发明实施例对此也不加以限制。
对于方法实施例,为了简单描述,故将其都表述为一系列的动作组合,但是本领域技术人员应该知悉,本发明实施例并不受所描述的动作顺序的限制,因为依据本发明实施例,某些步骤可以采用其他顺序或者同时进行。其次,本领域技术人员也应该知悉,说明书中所描述的实施例均属于优选实施例,所涉及的动作并不一定是本发明实施例所必须的。
参照图11,示出了根据本发明一个实施例的一种基于消息队列的共享内存写入系统实施例的结构框图,所述消息队列包括第一消息队列,具体可以包括如下模块:
多线程进队push模块501及单线程出队pop模块502,用于采用所述消息队列执行多线程进队push以及单线程出队pop的操作;
数据写入模块503,用于将所述单线程出队pop的数据写入共享内存;
其中,所述多线程进队push模块501包括:
第一判断子模块,用于判断所述消息队列是否已满;
进队push偏移量计算子模块,用于在消息队列未满时,分别计算n个线程进队push的偏移量;所述n为大于或等于1的正整数;
进队push的实际位置Pos计算子模块,用于依据所述n个线程进队push的偏移量,分别计算所述n个线程进队push的实际位置Pos;
操作进队push子模块,用于所述n个线程分别在其进队push的实际位置Pos执行进队push操作;
其中,数据写入模块503包括:
数据及其长度获得子模块,用于获得所述单线程出队pop的数据及其长度;
界限检查子模块,用于检查所述数据的长度是否超出共享内存的长度界限;
第一指针获取子模块,用于在所述数据的长度未超出共享内存的长度界限时,获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
可写判断子模块,用于依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写;
写入子模块,用于在数据可写时,在所述写入位置写入所述数据。
在本发明的一种优选实施例中,所述系统还包括:
第一消息队列选定模块,用于在存在多个消息队列时,选定用于当前通信的第一消息队列。
在本发明的一种优选实施例中,所述第一消息队列选定模块包括:
上下文参数读取子模块,用于读取所述数据的协议中的上下文参数intnId;
取模子模块,用于采用所述上下文参数intnId对所述多个消息队列的个数取模;
提取子模块,用于提取所述取模的值对应的消息队列为用于当前通信的第一消息队列。
在本发明的一种优选实施例中,所述第一判断子模块包括:
可写计数参数读取子模块,用于读取可写计数参数CanWriteCount的值;
可写计数参数递减子模块,用于递减所述CanWriteCount的值;
第一判断子模块,用于在获得递减后的CanWriteCount的值为0,则判定所述消息队列为已满,否则,判定所述消息队列为未满。
在本发明的一种优选实施例中,所述进队push偏移量计算子模块包括:
偏移量Pushpos读取子模块,用于读取进队push的偏移量Pushpos的值;
偏移量Pushpos获得子模块,用于针对所述n个线程迭代增加所述Pushpos的值,分别获得所述n个线程进队push的偏移量。
在本发明的一种优选实施例中,所述进队push的实际位置Pos计算子模块包括:
第一大小参数Size读取子模块,用于读取所述消息队列大小参数Size的值;
进队push的实际位置Pos获得子模块,用于获得对应的n个线程进队push的实际位置Pos。
在本发明的一种优选实施例中,所述多线程进队push子模块还包括:
可读计数参数读取子模块,读取可读计数参数CanReadCount的值;
可读计数参数读迭代增加子模块,按照所述n个线程进队push的操作,迭代增加所述CanReadCount的值。
在本发明的一种优选实施例中,所述单线程出队pop模块包括:
出队pop子模块,用于单个线程依次在所述消息队列中执行出队pop操作。
在本发明的一种优选实施例中,所述多线程进队push模块还包括:
进队push的操作禁止子模块,用于在所述消息队列已满时,禁止执行进队push的操作。
在本发明的一种优选实施例中,所述数据写入模块还包括:
禁止写入子模块,用于在所述数据的长度超出共享内存的长度界限,则禁止写入。
在本发明的一种优选实施例中,所述可写判断子模块包括:
第一写入位置确定子模块,用于依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
第一可写判定子模块,用于当所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,判定所述数据可写。
在本发明的一种优选实施例中,所述可写判断子模块还包括:
第二写入位置确定子模块,用于依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
第一可写数据长度设置子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,设置可写数据的长度小于或等于allsize-pWrite+pRead-head,其中allsize为共享内存的长度,所述head为文件头的长度;
第三判断子模块,用于判断所述数据的长度是否小于或等于所述可写数据的长度;
第二可写判定子模块,用于所述数据的长度小于或等于所述可写数据的长度时,判定所述数据可写;
第一不可写判定子模块,用于所述数据的长度大于所述可写数据的长度时,判定所述数据不可写。
在本发明的一种优选实施例中,所述可写判断子模块还包括:
第三写入位置确定子模块,用于依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
第二可写数据长度设置子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,设置可写数据的长度小于或等于pRead-pWrite;
第四判断子模块,用于判断所述数据的长度是否小于或等于所述可写数据的长度;
第三可写判定子模块,用于所述数据的长度小于或等于所述可写数据的长度时,判定所述数据可写;
第二不可写判定子模块,用于所述数据的长度大于所述可写数据的长度时,判定所述数据不可写。
在本发明的一种优选实施例中,所述第一指针获取子模块包括:
第一映射文件获得子模块,用于获得所述共享内存的映射文件,所述映射文件包括文件头;
第一写偏移指针pWrite读取子模块,用于从所述文件头中读取写偏移指针pWrite;
第一读偏移指针pRead读取子模块,用于从所述文件头中读取读偏移指针pRead并快照到临时变量中。
在本发明的一种优选实施例中,所述写入子模块包括:
第一开始写入子模块,用于在所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,或,在所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,则从当前写偏移指针pWrite位置开始写入所述数据;
尾部写入判断子模块,用于在写入到所述共享内存尾部的位置时,判断所述数据是否已全部写入;
第一全部写入子模块,用于所述数据未全部写入时,从所述共享内存中文件头结束的位置开始继续写入所述数据,直至在所述读偏移指针pRead位置之前写入全部的数据。
在本发明的一种优选实施例中,所述写入子模块包括:
第二开始写入子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,则从当前写偏移指针pWrite位置开始写入所述数据;
第二全部写入子模块,用于在所述读偏移指针pRead位置之前写入全部的数据。
在本发明的一种优选实施例中,采用内存拷贝memcpy的方式写入所述数据
对于图11所示的系统实施例而言,由于其与图1所示的方法实施例基本相似,所以描述的比较简单,相关之处参见方法实施例的部分说明即可。
参照图12,示出了根据本发明一个实施例的一种基于消息队列的共享内存读取系统实施例的结构框图,所述消息队列包括第二消息队列,具体可以包括如下模块:
数据读取模块601,用于从共享内存中读取数据;
单线程进队push模块602及多线程出队pop模块603,用于将读出的数据通过单线程进队push的操作压入所述第二消息队列,同时,采用所述第二消息队列执行多线程出队pop的操作;
其中,所述数据读取模块601包括:
定位子模块,用于定位数据所在共享内存的位置;
数据长度获得子模块,用于获得所述数据的长度;
第二指针获取子模块,用于获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
可读判断子模块,用于依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,判断所述数据是否可读;
读取子模块,用于在所述数据可读时,从所述数据所在共享内存的位置,读出所述数据。
其中,所述多线程出队pop模块603包括:
第二判断子模块,用于判断所述消息队列是否已空;
出队pop的偏移量计算子模块,用于在消息队列未空时,分别计算n个线程出队pop的偏移量;所述n为大于或等于1的正整数;
出队pop的实际位置Pos计算子模块,用于依据所述n个线程出队pop的偏移量,分别计算所述n个线程出队pop的实际位置Pos;
操作出队pop子模块,用于所述n个线程分别在其出队pop的实际位置执行出队pop操作。
在本发明的一种优选实施例中,所述数据读取模块还包括:
返回子模块,用于在所述数据不可读时,返回数据为空。
在本发明的一种优选实施例中,所述可读判断子模块包括:
第一可读数据长度设置子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,设置可读数据的长度小于或等于pWrite-pRead;
第一判断子模块,用于判断所述数据的长度是否小于或等于所述可读数据的长度;
第一可读判定子模块,用于所述数据的长度小于或等于所述可读数据的长度时,判定所述数据可读;
第一不可读判定子模块,用于所述数据的长度大于所述可读数据的长度时,判定所述数据不可读。
在本发明的一种优选实施例中,所述可读判断子模块还包括:
第二可读数据长度设置子模块,用于当所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,设置可读数据的长度小于或等于allsize-pRead+pWrite-head,其中,所述allsize为共享内存的长度,所述head为文件头的长度;
第二判断子模块,用于判断所述数据的长度是否小于或等于所述可读数据的长度;
第二可读判定子模块,用于所述数据的长度小于或等于所述可读数据的长度时,判定所述数据可读;
第二不可读判定子模块,用于所述数据的长度大于所述可读数据的长度时,判定所述数据不可读。
在本发明的一种优选实施例中,所述可读判断子模块还包括:
第三不可读判定子模块,用于在所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,判定所述数据不可读。
在本发明的一种优选实施例中,所述第二指针获取子模块包括:
第二映射文件获得子模块,用于获得所述共享内存的映射文件,所述映射文件包括文件头;
第二读偏移指针pRead读取子模块,用于从所述文件头中读取读偏移指针pRead;
第二写偏移指针pWrite读取子模块,用于从所述文件头中读取写偏移指针pWrite并快照到临时变量中。
在本发明的一种优选实施例中,所述读取子模块包括:
第一开始读取子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,从当前读偏移指针pRead位置开始读出所述数据;
第一全部读取子模块,用于在不超过所述写偏移指针pWrite位置读出全部的数据。
在本发明的一种优选实施例中,所述读取模块包括:
第二开始读取子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,从当前读偏移指针pRead位置开始读出所述数据;
尾部读取判断子模块,用于在读取至所述共享内存尾部的位置时,判断所述数据是否已全部读出;
第二全部读取子模块,用于在所述数据未全部读出时,从所述共享内存中文件头结束的位置开始继续读出所述数据,直至在不超过所述写偏移指针pWrite位置读出全部的数据。
在本发明的一种优选实施例中,采用内存拷贝memcpy的方式读出所述数据。
在本发明的一种优选实施例中,所述第二判断子模块包括:
可读计数参数读取子模块,用于读取可读计数参数CanReadCount的值;
可读计数参数递减子模块,用于递减所述CanReadCount的值;
第二判断子模块,用于在获得递减后的CanReadCount的值为0,则判定所述消息队列为已空,否则,判定所述消息队列为未空。
在本发明的一种优选实施例中,所述出队pop的偏移量计算子模块还包括:
偏移量Poppos读取子模块,用于读取出队pop的偏移量Poppos的值;
偏移量Poppos获得子模块,用于针对所述n个线程迭代增加所述Poppos的值,分别获得所述n个线程出队pop的偏移量。
在本发明的一种优选实施例中,所述出队pop的实际位置Pos计算子模块包括:
第二大小参数读取子模块,用于读取所述消息队列大小参数Size的值;
出队pop的实际位置Pos计算子模块,用于采用所述Size的值对所述Poppos的值取模,获得对应的n个线程出队pop的实际位置Pos。
在本发明的一种优选实施例中,所述多线程出队pop模块还包括:
可写计数参数读取子模块,用于读取可写计数参数CanWriteCount的值;
可写计数参数迭代增加子模块,用于按照所述n个线程出队pop的操作,迭代增加所述CanWriteCount的值。
在本发明的一种优选实施例中,所述单线程进队push模块包括:
进队push子模块,用于单个线程依次在所述消息队列中执行进队push操作。
在本发明的一种优选实施例中,所述多线程出队pop模块还包括:
出队pop的操作禁止子模块,用于在所述消息队列已空时,则禁止执行出队pop的操作。
对于图12所示的系统实施例而言,由于其与图5所示的方法实施例基本相似,所以描述的比较简单,相关之处参见方法实施例的部分说明即可。
参照图13,示出了根据本发明一个实施例的一种基于消息队列的共享内存读写系统实施例的结构框图,所述消息队列包括第一消息队列和第二消息队列,具体可以包括如下模块:
第一进队push模块701和第一出队pop模块702,用于采用第一消息队列执行多线程进队push以及单线程出队pop的操作;
共享内存写入模块703,用于将所述单线程出队pop的数据写入共享内存;
共享内存读取模块704,用于从所述共享内存中读取数据;
第二进队push模块705和第二出队pop模块706,用于将所述数据采用第二消息队列执行单线程进队push以及多线程出队pop的操作;
其中,所述第一进队push模块701包括:
CanWriteCount参数读取子模块,用于读取可写计数参数CanWriteCount的值;
CanWriteCount参数递减子模块,用于递减所述CanWriteCount的值;
第三判断子模块,用于在获得递减后的CanWriteCount的值不为0,则判定所述消息队列为未满;
push的偏移量计算子模块,用于在所述消息队列未满时,分别计算n个线程进队push的偏移量;所述n为大于或等于1的正整数;
push的实际位置计算子模块,用于依据所述n个线程进队push的偏移量,分别计算所述n个线程进队push的实际位置;
push操作执行子模块,用于所述n个线程分别在其进队push的实际位置执行进队push操作;
CanReadCount参数读取子模块,用于读取可读计数参数CanReadCount的值;
CanReadCount参数迭加子模块,用于按照所述n个线程进队push的操作,迭代增加所述CanReadCount的值;
其中,所述第二出队pop模块706包括:
CanReadCount参数读取子模块,用于读取可读计数参数CanReadCount的值;
CanReadCount参数递减子模块,用于递减所述CanReadCount的值;
第四判断子模块,用于在获得递减后的CanReadCount的值不为0,则判定所述消息队列为未空;
pop的偏移量计算子模块,用于在所述消息队列未空时,分别计算n个线程出队pop的偏移量;所述n为大于或等于1的正整数;
pop的实际位置计算子模块,用于依据所述n个线程出队pop的偏移量,分别计算所述n个线程出队pop的实际位置;
pop操作执行子模块,用于所述n个线程分别在其出队pop的实际位置执行出队pop操作;
CanWriteCount参数读取子模块,用于读取可写计数参数CanWriteCount的值;
CanWriteCount参数迭加子模块,用于按照所述n个线程出队pop的操作,迭代增加所述CanWriteCount的值。
其中,共享内存写入模块703包括:
数据获得子模块,用于获得所述单线程出队pop的数据及其长度;
检查子模块,用于检查所述数据的长度是否超出共享内存的长度界限;
第三指针获取子模块,用于在所述数据的长度未超出共享内存的长度界限时,获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
数据可写判断子模块,用于依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写;
写入数据子模块,用于在数据可写时,在所述写入位置写入所述数据;
其中,所述共享内存读取模块704包括:
数据定位子模块,用于定位待读取数据所在共享内存的位置;
长度获得子模块,用于获得所述待读取数据的长度;
第四指针获取子模块,用于获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
数据可读判断子模块,用于依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,判断所述待读取数据是否可读;
读取数据子模块,用于在所述数据可读时,从所述数据所在共享内存的位置,读出所述待读取数据;
对于图13所示的系统实施例而言,由于其与图8所示的方法实施例基本相似,所以描述的比较简单,相关之处参见方法实施例的部分说明即可。
在此提供的算法和显示不与任何特定计算机、虚拟系统或者其它设备固有相关。各种通用系统也可以与基于在此的示教一起使用。根据上面的描述,构造这类系统所要求的结构是显而易见的。此外,本发明也不针对任何特定编程语言。应当明白,可以利用各种编程语言实现在此描述的本发明的内容,并且上面对特定语言所做的描述是为了披露本发明的最佳实施方式。
在此处所提供的说明书中,说明了大量具体细节。然而,能够理解,本发明的实施例可以在没有这些具体细节的情况下实践。在一些实例中,并未详细示出公知的方法、结构和技术,以便不模糊对本说明书的理解。
类似地,应当理解,为了精简本公开并帮助理解各个发明方面中的一个或多个,在上面对本发明的示例性实施例的描述中,本发明的各个特征有时被一起分组到单个实施例、图、或者对其的描述中。然而,并不应将该公开的方法解释成反映如下意图:即所要求保护的本发明要求比在每个权利要求中所明确记载的特征更多的特征。更确切地说,如下面的权利要求书所反映的那样,发明方面在于少于前面公开的单个实施例的所有特征。因此,遵循具体实施方式的权利要求书由此明确地并入该具体实施方式,其中每个权利要求本身都作为本发明的单独实施例。
本领域那些技术人员可以理解,可以对实施例中的设备中的模块进行自适应性地改变并且把它们设置在与该实施例不同的一个或多个设备中。可以把实施例中的模块或单元或组件组合成一个模块或单元或组件,以及此外可以把它们分成多个子模块或子单元或子组件。除了这样的特征和/或过程或者单元中的至少一些是相互排斥之外,可以采用任何组合对本说明书(包括伴随的权利要求、摘要和附图)中公开的所有特征以及如此公开的任何方法或者设备的所有过程或单元进行组合。除非另外明确陈述,本说明书(包括伴随的权利要求、摘要和附图)中公开的每个特征可以由提供相同、等同或相似目的的替代特征来代替。
此外,本领域的技术人员能够理解,尽管在此所述的一些实施例包括其它实施例中所包括的某些特征而不是其它特征,但是不同实施例的特征的组合意味着处于本发明的范围之内并且形成不同的实施例。例如,在下面的权利要求书中,所要求保护的实施例的任意之一都可以以任意的组合方式来使用。
本发明的各个部件实施例可以以硬件实现,或者以在一个或者多个处理器上运行的软件模块实现,或者以它们的组合实现。本领域的技术人员应当理解,可以在实践中使用微处理器或者数字信号处理器(DSP)来实现根据本发明实施例的基于消息队列的共享内存写入、读取、读写方法和系统设备中的一些或者全部部件的一些或者全部功能。本发明还可以实现为用于执行这里所描述的方法的一部分或者全部的设备或者装置程序(例如,计算机程序和计算机程序产品)。这样的实现本发明的程序可以存储在计算机可读介质上,或者可以具有一个或者多个信号的形式。这样的信号可以从因特网网站上下载得到,或者在载体信号上提供,或者以任何其他形式提供。
应该注意的是上述实施例对本发明进行说明而不是对本发明进行限制,并且本领域技术人员在不脱离所附权利要求的范围的情况下可设计出替换实施例。在权利要求中,不应将位于括号之间的任何参考符号构造成对权利要求的限制。单词“包含”不排除存在未列在权利要求中的元件或步骤。位于元件之前的单词“一”或“一个”不排除存在多个这样的元件。本发明可以借助于包括有若干不同元件的硬件以及借助于适当编程的计算机来实现。在列举了若干装置的单元权利要求中,这些装置中的若干个可以是通过同一个硬件项来具体体现。单词第一、第二、以及第三等的使用不表示任何顺序。可将这些单词解释为名称。
本发明公开了A1、一种基于消息队列的共享内存写入方法,所述消息队列包括第一消息队列,所述方法包括:
采用所述消息队列执行多线程进队push以及单线程出队pop的操作;
将所述单线程出队pop的数据写入共享内存;
其中,所述多线程进队push的操作包括:
判断所述消息队列是否已满;
若否,则分别计算n个线程进队push的偏移量;所述n为大于或等于1的正整数;
依据所述n个线程进队push的偏移量,分别计算所述n个线程进队push的实际位置Pos;
所述n个线程分别在其进队push的实际位置Pos执行进队push操作;
其中,所述将所述单线程出队pop的数据写入共享内存的步骤包括:
获得所述单线程出队pop的数据及其长度;
检查所述数据的长度是否超出共享内存的长度界限;
若否,则获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写;
若是,则在所述写入位置写入所述数据。
A2、根据权利要求A1所述的方法,其特征在于,在采用所述消息队列执行多线程进队push以及单线程出队pop的操作的步骤之前还包括:
在存在多个消息队列时,选定用于当前通信的第一消息队列。
A3、根据权利要求A2所述的方法,其特征在于,所述选定用于当前通信的第一消息队列的步骤包括:
读取所述数据的协议中的上下文参数intnId;
采用所述上下文参数intnId对所述多个消息队列的个数取模;
提取所述取模的值对应的消息队列为用于当前通信的第一消息队列。
A4、根据权利要求A1所述的方法,其特征在于,所述判断消息队列是否已满的子步骤进一步包括:
读取可写计数参数CanWriteCount的值;
递减所述CanWriteCount的值;
若获得递减后的CanWriteCount的值为0,则判定所述消息队列为已满,否则,判定所述消息队列为未满。
A5、根据权利要求A1所述的方法,其特征在于,所述分别计算n个线程进队push的偏移量的子步骤进一步包括:
读取进队push的偏移量Pushpos的值;
针对所述n个线程迭代增加所述Pushpos的值,分别获得所述n个线程进队push的偏移量。
A6、根据权利要求A1所述的方法,其特征在于,所述分别计算所述n个线程进队push的实际位置Pos的子步骤进一步包括:
读取所述消息队列大小参数Size的值;
采用所述Size的值对所述Pushpos的值取模,获得对应的n个线程进队push的实际位置Pos。
A7、根据权利要求A1或A4或A5或A6所述的方法,其特征在于,在所述n个线程分别在其进队push的实际位置执行进队push操作的子步骤之后,所述多线程进队push的操作还包括:
读取可读计数参数CanReadCount的值;
按照所述n个线程进队push的操作,迭代增加所述CanReadCount的值。
A8、根据权利要求A1所述的方法,其特征在于,所述单线程出队pop的操作的子步骤为:
单个线程依次在所述消息队列中执行出队pop操作。
A9、根据权利要求A1所述的方法,其特征在于,所述多线程进队push的操作还包括:
若所述消息队列已满,则禁止执行进队push的操作。
A10、根据权利要求A1所述的方法,其特征在于,所述将所述单线程出队pop的数据写入共享内存的步骤还包括:
若所述数据的长度超出共享内存的长度界限,则禁止写入。
A11、根据权利要求A1所述的方法,其特征在于,所述依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写的子步骤进一步包括:
依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
当所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,判定所述数据可写。
A12、根据权利要求A11所述的方法,其特征在于,所述依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写的子步骤还进一步包括:
依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
当所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,设置可写数据的长度小于或等于allsize-pRead+pWrite-head,其中allsize为共享内存的长度,所述head为文件头的长度;
判断所述数据的长度是否小于或等于所述可写数据的长度;
若是,则判定所述数据可写;
若否,则判定所述数据不可写。
A13、根据权利要求A12所述的方法,其特征在于,所述依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写的子步骤还进一步包括:
依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
当所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,设置可写数据的长度小于或等于pRead-pWrite;
判断所述数据的长度是否小于或等于所述可写数据的长度;
若是,则判定所述数据可写;
若否,则判定所述数据不可写。
A14、根据权利要求A1所述的方法,其特征在于,所述获取所述共享内存的读偏移指针pRead和写偏移指针pWrite的子步骤进一步包括:
获得所述共享内存的映射文件,所述映射文件包括文件头;
从所述文件头中读取写偏移指针pWrite;
从所述文件头中读取读偏移指针pRead并快照到临时变量中。
A15、根据权利要求A1所述的方法,其特征在于,所述在所述数据所在共享内存的位置写入所述数据的子步骤进一步包括:
当所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,或,当所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,则从当前写偏移指针pWrite位置开始写入所述数据;
当写入到所述共享内存尾部的位置时,判断所述数据是否已全部写入;
若否,则从所述共享内存中文件头结束的位置开始继续写入所述数据,直至在所述读偏移指针pRead位置之前写入全部的数据。
A16、根据权利要求A1所述的方法,其特征在于,所述在所述数据所在共享内存的位置写入所述数据子步骤进一步包括:
当所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,则从当前写偏移指针pWrite位置开始写入所述数据;
在所述读偏移指针pRead位置之前写入全部的数据。
A17、根据权利要求A13所述的方法,其特征在于,采用内存拷贝memcpy的方式写入所述数据。
本发明还公开了B18、一种基于消息队列的共享内存读取方法,所述消息队列包括第二消息队列,所述方法包括:
从共享内存中读取数据;
将读出的数据通过单线程进队push的操作压入所述第二消息队列,同时,采用所述第二消息队列执行多线程出队pop的操作;
其中,所述从共享内存中读取数据的步骤包括:
定位待读取数据所在共享内存的位置;
获得所述待读取数据的长度;
获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述待读取数据的长度,判断所述待读取数据是否可读;
若是,则从所述待读取数据所在共享内存的位置,读出所述待读取数据;
其中,所述多线程出队pop的操作包括:
判断所述消息队列是否已空;
若否,则分别计算n个线程出队pop的偏移量;所述n为大于或等于1的正整数;
依据所述n个线程出队pop的偏移量,分别计算所述n个线程出队pop的实际位置Pos;
所述n个线程分别在其出队pop的实际位置执行出队pop操作。
B19、根据权利要求B18所述的方法,其特征在于,所述从共享内存中读取数据的步骤还包括:
若所述数据不可读,则返回数据为空。
B20、根据权利要求B18或B19所述的方法,其特征在于,所述依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,判断所述数据是否可读的子步骤进一步包括:
当所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,设置可读数据的长度小于或等于pWrite-pRead;
判断所述数据的长度是否小于或等于所述可读数据的长度;
若是,则判定所述数据可读;
若否,则判定所述数据不可读。
B21、根据权利要求B20所述的方法,其特征在于,所述依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,判断所述数据是否可读的子步骤还进一步包括:
当所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,设置可读数据的长度小于或等于allsize-pRead+pWrite-head,其中,所述allsize为共享内存的长度,所述head为文件头的长度;
判断所述数据的长度是否小于或等于所述可读数据的长度;
若是,则判定所述数据可读;
若否,则判定所述数据不可读。
B22、根据权利要求B21所述的方法,其特征在于,所述依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,判断所述数据是否可读的子步骤还进一步包括:
当所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,则判定所述数据不可读。
B23、根据权利要求B18所述的方法,其特征在于,所述获取所述共享内存的读偏移指针pRead和写偏移指针pWrite的子步骤进一步包括:
获得所述共享内存的映射文件,所述映射文件包括文件头;
从所述文件头中读取读偏移指针pRead;
从所述文件头中读取写偏移指针pWrite并快照到临时变量中。
B24、根据权利要求B20所述的方法,其特征在于,所述从所述数据所在共享内存的位置,读出所述数据的子步骤进一步包括:
当所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,则从当前读偏移指针pRead位置开始读出所述数据;
在不超过所述写偏移指针pWrite位置读出全部的数据。
B25、根据权利要求B21所述的方法,其特征在于,所述从所述数据所在共享内存的位置,读出所述数据的子步骤进一步包括:
当所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,则从当前读偏移指针pRead位置开始读出所述数据;
当读取至所述共享内存尾部的位置时,判断所述数据是否已全部读出;
若否,则从所述共享内存中文件头结束的位置开始继续读出所述数据,直至在不超过所述写偏移指针pWrite位置读出全部的数据。
B26、根据权利要求B25所述的方法,其特征在于,采用内存拷贝memcpy的方式读出所述数据。
B27、根据权利要求B18所述的方法,其特征在于,所述判断消息队列是否已空的子步骤进一步包括:
读取可读计数参数CanReadCount的值;
递减所述CanReadCount的值;
若获得递减后的CanReadCount的值为0,则判定所述消息队列为已空,否则,判定所述消息队列为未空。
B28、根据权利要求B18所述的方法,其特征在于,所述分别计算n个线程出队pop的偏移量的子步骤进一步包括:
读取出队pop的偏移量Poppos的值;
针对所述n个线程迭代增加所述Poppos的值,分别获得所述n个线程出队pop的偏移量。
B29、根据权利要求B18所述的方法,其特征在于,所述分别计算所述n个线程出队pop的实际位置Pos的子步骤还进一步包括:
读取所述消息队列大小参数Size的值;
采用所述Size的值对所述Poppos的值取模,获得对应的n个线程出队pop的实际位置Pos。
B30、根据权利要求B18或B27或B28或B29所述的方法,其特征在于,在所述n个线程分别在其出队pop的实际位置执行出队pop操作的步骤之后,还包括:
读取可写计数参数CanWriteCount的值;
按照所述n个线程出队pop的操作,迭代增加所述CanWriteCount的值。
B31、根据权利要求B18所述的方法,其特征在于,所述单线程进队push的操作进一步包括:
单个线程依次在所述消息队列中执行进队push操作。
B32、根据权利要求B18所述的方法,其特征在于,所述多线程出队pop的操作还进一步包括:
若所述消息队列已空,则禁止执行出队pop的操作。
本发明还公开了C33、一种基于消息队列的共享内存处理的方法,所述消息队列包括第一消息队列和第二消息队列,所述方法包括:
采用第一消息队列执行多线程进队push以及单线程出队pop的操作;
将所述单线程出队pop的数据写入共享内存;
从所述共享内存中读取数据;
将读出的数据通过单线程进队push的操作压入所述第二消息队列,同时,采用所述第二消息队列执行多线程出队pop的操作;
其中,所述多线程进队push的操作包括:
读取可写计数参数CanWriteCount的值;
递减所述CanWriteCount的值;
若获得递减后的CanWriteCount的值不为0,则判定所述消息队列为未满;
在所述消息队列未满时,分别计算n个线程进队push的偏移量;所述n为大于或等于1的正整数;
依据所述n个线程进队push的偏移量,分别计算所述n个线程进队push的实际位置;
所述n个线程分别在其进队push的实际位置执行进队push操作;
读取可读计数参数CanReadCount的值;
按照所述n个线程进队push的操作,迭代增加所述CanReadCount的值;
其中,所述多线程出队pop的操作包括:
读取可读计数参数CanReadCount的值;
递减所述CanReadCount的值;
若获得递减后的CanReadCount的值不为0,则判定所述消息队列为未空;
在所述消息队列未空时,分别计算n个线程出队pop的偏移量;所述n为大于或等于1的正整数;
依据所述n个线程出队pop的偏移量,分别计算所述n个线程出队pop的实际位置;
所述n个线程分别在其出队pop的实际位置执行出队pop操作;
读取可写计数参数CanWriteCount的值;
按照所述n个线程出队pop的操作,迭代增加所述CanWriteCount的值。
其中,将所述单线程出队pop的数据写入共享内存的步骤包括:
获得所述单线程出队pop的数据及其长度;
检查所述数据的长度是否超出共享内存的长度界限;
若否,则获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写;
若是,则在所述写入位置写入所述数据;
其中,所述从共享内存中读取数据的步骤包括:
定位待读取数据所在共享内存的位置;
获得所述待读取数据的长度;
获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述待读取数据的长度,判断所述待读取数据是否可读;
若是,则从所述待读取数据所在共享内存的位置,读出所述待读取数据。
本发明还公开了D34、一种基于消息队列的共享内存写入系统,所述消息队列包括第一消息队列,所述系统包括:
多线程进队push模块及单线程出队pop模块,用于采用所述消息队列执行多线程进队push以及单线程出队pop的操作;
数据写入模块,用于将所述单线程出队pop的数据写入共享内存;
其中,所述多线程进队push模块包括:
第一判断子模块,用于判断所述消息队列是否已满;
进队push偏移量计算子模块,用于在消息队列未满时,分别计算n个线程进队push的偏移量;所述n为大于或等于1的正整数;
进队push的实际位置Pos计算子模块,用于依据所述n个线程进队push的偏移量,分别计算所述n个线程进队push的实际位置Pos;
操作进队push子模块,用于所述n个线程分别在其进队push的实际位置Pos执行进队push操作;
其中,所述数据写入模块包括:
数据及其长度获得子模块,用于获得所述单线程出队pop的数据及其长度;
界限检查模块,用于检查所述数据的长度是否超出共享内存的长度界限;
第一指针获取子模块,用于在所述数据的长度未超出共享内存的长度界限时,获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
可写判断子模块,用于依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写;
写入子模块,用于在数据可写时,在所述写入位置写入所述数据。
D35、根据权利要求D34所述的系统,其特征在于,还包括:
第一消息队列选定模块,用于在存在多个消息队列时,选定用于当前通信的第一消息队列。
D36、根据权利要求D35所述的系统,其特征在于,所述第一消息队列选定模块包括:
上下文参数读取子模块,用于读取所述数据的协议中的上下文参数intnId;
取模子模块,用于采用所述上下文参数intnId对所述多个消息队列的个数取模;
提取子模块,用于提取所述取模的值对应的消息队列为用于当前通信的第一消息队列。
D37、根据权利要求D34所述的系统,其特征在于,所述第一判断子模块进一步包括:
可写计数参数读取子模块,用于读取可写计数参数CanWriteCount的值;
可写计数参数递减子模块,用于递减所述CanWriteCount的值;
第一判断子模块,用于在获得递减后的CanWriteCount的值为0,则判定所述消息队列为已满,否则,判定所述消息队列为未满。
D38、根据权利要求D34所述的系统,其特征在于,所述进队push偏移量计算子模块进一步包括:
偏移量Pushpos读取子模块,用于读取进队push的偏移量Pushpos的值;
偏移量Pushpos获得子模块,用于针对所述n个线程迭代增加所述Pushpos的值,分别获得所述n个线程进队push的偏移量。
D39、根据权利要求D34所述的系统,其特征在于,所述进队push的实际位置Pos计算子模块进一步包括:
第一大小参数Size读取子模块,用于读取所述消息队列大小参数Size的值;
进队push的实际位置Pos获得子模块,用于获得对应的n个线程进队push的实际位置Pos。
D40、根据权利要求D34或D37或D38或D39所述的系统,所述多线程进队push子模块还进一步包括:
可读计数参数读取子模块,读取可读计数参数CanReadCount的值;
可读计数参数读迭代增加子模块,按照所述n个线程进队push的操作,迭代增加所述CanReadCount的值。
D41、根据权利要求D34所述的系统,其特征在于,所述单线程出队pop模块进一步包括:
出队pop子模块,用于单个线程依次在所述消息队列中执行出队pop操作。
D42、根据权利要求D34所述的系统,其特征在于,所述多线程进队push模块还进一步包括:
进队push的操作禁止子模块,用于在所述消息队列已满时,禁止执行进队push的操作。
D43、根据权利要求D34所述的系统,其特征在于,所述数据写入模块还进一步包括:
禁止写入子模块,用于在所述数据的长度超出共享内存的长度界限,则禁止写入。
D44、根据权利要求D34或D43所述的系统,其特征在于,所述可写判断子模块进一步包括:
第一写入位置确定子模块,用于依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
第一可写判定子模块,用于当所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,判定所述数据可写。
D45、根据权利要求D44所述的系统,其特征在于,所述可写判断子模块还进一步包括:
第二写入位置确定子模块,用于依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
第一可写数据长度设置子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,设置可写数据的长度小于或等于allsize-pWrite+pRead-head,其中allsize为共享内存的长度,所述head为文件头的长度;
第三判断子模块,用于判断所述数据的长度是否小于或等于所述可写数据的长度;
第二可写判定子模块,用于所述数据的长度小于或等于所述可写数据的长度时,判定所述数据可写;
第一不可写判定子模块,用于所述数据的长度大于所述可写数据的长度时,判定所述数据不可写。
D46、根据权利要求D45所述的系统,其特征在于,所述可写判断子模块还进一步包括:
第三写入位置确定子模块,用于依据所述写偏移指针pWrite确定所述数据在共享内存中的写入位置;
第二可写数据长度设置子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,设置可写数据的长度小于或等于pRead-pWrite;
第四判断子模块,用于判断所述数据的长度是否小于或等于所述可写数据的长度;
第三可写判定子模块,用于所述数据的长度小于或等于所述可写数据的长度时,判定所述数据可写;
第二不可写判定子模块,用于所述数据的长度大于所述可写数据的长度时,判定所述数据不可写。
D47、根据权利要求D34或D44或D45或D46所述的系统,其特征在于,所述第一指针获取子模块进一步包括:
第一映射文件获得子模块,用于获得所述共享内存的映射文件,所述映射文件包括文件头;
第一写偏移指针pWrite读取子模块,用于从所述文件头中读取写偏移指针pWrite;
第一读偏移指针pRead读取子模块,用于从所述文件头中读取读偏移指针pRead并快照到临时变量中。
D48、根据权利要求D44或D45所述的系统,其特征在于,所述写入子模块进一步包括:
第一开始写入子模块,用于在所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,或,在所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,则从当前写偏移指针pWrite位置开始写入所述数据;
尾部写入判断子模块,用于在写入到所述共享内存尾部的位置时,判断所述数据是否已全部写入;
第一全部写入子模块,用于所述数据未全部写入时,从所述共享内存中文件头结束的位置开始继续写入所述数据,直至在所述读偏移指针pRead位置之前写入全部的数据。
D49、根据权利要求D46所述的系统,其特征在于,所述写入子模块进一步包括:
第二开始写入子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,则从当前写偏移指针pWrite位置开始写入所述数据;
第二全部写入子模块,用于在所述读偏移指针pRead位置之前写入全部的数据。
D50、根据权利要求D34所述的系统,其特征在于,采用内存拷贝memcpy的方式写入所述数据
本发明还公开了E51、一种基于消息队列的共享内存读取系统,所述消息队列包括第二消息队列,所述系统包括:
数据读取模块,用于从共享内存中读取数据;
单线程进队push模块及多线程出队pop模块,用于将读出的数据通过单线程进队push的操作压入所述第二消息队列,同时,采用所述第二消息队列执行多线程出队pop的操作;
其中,所述数据读取模块包括:
定位子模块,用于定位待读取数据所在共享内存的位置;
数据长度获得子模块,用于获得所述待读取数据的长度;
第二指针获取子模块,用于获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
可读判断子模块,用于依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,判断所述待读取数据是否可读;
读取子模块,用于在所述数据可读时,从所述数据所在共享内存的位置,读出所述待读取数据。
其中,所述多线程出队pop模块包括:
第二判断子模块,用于判断所述消息队列是否已空;
出队pop的偏移量计算子模块,用于在消息队列未空时,分别计算n个线程出队pop的偏移量;所述n为大于或等于1的正整数;
出队pop的实际位置Pos计算子模块,用于依据所述n个线程出队pop的偏移量,分别计算所述n个线程出队pop的实际位置Pos;
操作出队pop子模块,用于所述n个线程分别在其出队pop的实际位置执行出队pop操作。
E52、根据权利要求E51所述的系统,其特征在于,所述数据读取模块还进一步包括:
返回子模块,用于在所述数据不可读时,返回数据为空。
E53、根据权利要求E51或E52所述的系统,其特征在于,所述可读判断子模块进一步包括:
第一可读数据长度设置子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,设置可读数据的长度小于或等于pWrite-pRead;
第一判断子模块,用于判断所述数据的长度是否小于或等于所述可读数据的长度;
第一可读判定子模块,用于所述数据的长度小于或等于所述可读数据的长度时,判定所述数据可读;
第一不可读判定子模块,用于所述数据的长度大于所述可读数据的长度时,判定所述数据不可读。
E54、根据权利要求E53所述的系统,其特征在于,所述可读判断子模块还进一步包括:
第二可读数据长度设置子模块,用于当所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,设置可读数据的长度小于或等于allsize-pRead+pWrite-head,其中,所述allsize为共享内存的长度,所述head为文件头的长度;
第二判断子模块,用于判断所述数据的长度是否小于或等于所述可读数据的长度;
第二可读判定子模块,用于所述数据的长度小于或等于所述可读数据的长度时,判定所述数据可读;
第二不可读判定子模块,用于所述数据的长度大于所述可读数据的长度时,判定所述数据不可读。
E55、根据权利要求E53所述的系统,其特征在于,所述可读判断子模块还进一步包括:
第三不可读判定子模块,用于在所述读偏移指针pRead和写偏移指针pWrite处于同一位置时,判定所述数据不可读。
E56、根据权利要求E51或E53或E54或E55所述的系统,其特征在于,所述第二指针获取子模块进一步包括:
第二映射文件获得子模块,用于获得所述共享内存的映射文件,所述映射文件包括文件头;
第二读偏移指针pRead读取子模块,用于从所述文件头中读取读偏移指针pRead;
第二写偏移指针pWrite读取子模块,用于从所述文件头中读取写偏移指针pWrite并快照到临时变量中。
E57、根据权利要求E53所述的系统,其特征在于,所述读取子模块进一步包括:
第一开始读取子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite后面的位置时,从当前读偏移指针pRead位置开始读出所述数据;
第一全部读取子模块,用于在不超过所述写偏移指针pWrite位置读出全部的数据。
E58、根据权利要求E54所述的方法,其特征在于,所述读取模块进一步包括:
第二开始读取子模块,用于在所述读偏移指针pRead处于所述写偏移指针pWrite前面的位置时,从当前读偏移指针pRead位置开始读出所述数据;
尾部读取判断子模块,用于在读取至所述共享内存尾部的位置时,判断所述数据是否已全部读出;
第二全部读取子模块,用于在所述数据未全部读出时,从所述共享内存中文件头结束的位置开始继续读出所述数据,直至在不超过所述写偏移指针pWrite位置读出全部的数据。
E59、根据权利要求E51所述的系统,其特征在于,采用内存拷贝memcpy的方式读出所述数据。
E60、根据权利要求E51所述的系统,其特征在于,所述第二判断子模块进一步包括:
可读计数参数读取子模块,用于读取可读计数参数CanReadCount的值;
可读计数参数递减子模块,用于递减所述CanReadCount的值;
第二判断子模块,用于在获得递减后的CanReadCount的值为0,则判定所述消息队列为已空,否则,判定所述消息队列为未空。
E61、根据权利要求E51所述的系统,其特征在于,所述出队pop的偏移量计算子模块还进一步包括:
偏移量Poppos读取子模块,用于读取出队pop的偏移量Poppos的值;
偏移量Poppos获得子模块,用于针对所述n个线程迭代增加所述Poppos的值,分别获得所述n个线程出队pop的偏移量。
E62、根据权利要求E51所述的系统,其特征在于,所述出队pop的实际位置Pos计算子模块进一步包括:
第二大小参数读取子模块,用于读取所述消息队列大小参数Size的值;
出队pop的实际位置Pos计算子模块,用于采用所述Size的值对所述Poppos的值取模,获得对应的n个线程出队pop的实际位置Pos。
E63、根据权利要求E51或E60或E61或E62所述的系统,所述多线程出队pop模块还进一步包括:
可写计数参数读取子模块,用于读取可写计数参数CanWriteCount的值;
可写计数参数迭代增加子模块,用于按照所述n个线程出队pop的操作,迭代增加所述CanWriteCount的值。
E64、根据权利要求E51所述的系统,其特征在于,所述单线程进队push模块进一步包括:
进队push子模块,用于单个线程依次在所述消息队列中执行进队push操作。
E65、根据权利要求E51所述的系统,其特征在于,所述多线程出队pop模块还进一步包括:
出队pop的操作禁止子模块,用于在所述消息队列已空时,则禁止执行出队pop的操作。
本发明还公开了F66、一种基于消息队列的共享内存处理的系统,所述消息队列包括第一消息队列和第二消息队列,所述方法包括:
第一进队push模块和第一出队pop模块,用于采用第一消息队列执行多线程进队push以及单线程出队pop的操作;
共享内存写入模块,用于将所述单线程出队pop的数据写入共享内存;
共享内存读取模块,用于从所述共享内存中读取数据;
第二进队push模块和第二出队pop模块,用于将所述数据采用第二消息队列执行单线程进队push以及多线程出队pop的操作;
其中,所述第一进队push模块包括:
CanWriteCount参数读取子模块,用于读取可写计数参数CanWriteCount的值;
CanWriteCount参数递减子模块,用于递减所述CanWriteCount的值;
第三判断子模块,用于在获得递减后的CanWriteCount的值不为0,则判定所述消息队列为未满;
push的偏移量计算子模块,用于在所述消息队列未满时,分别计算n个线程进队push的偏移量;所述n为大于或等于1的正整数;
push的实际位置计算子模块,用于依据所述n个线程进队push的偏移量,分别计算所述n个线程进队push的实际位置;
push操作执行子模块,用于所述n个线程分别在其进队push的实际位置执行进队push操作;
CanReadCount参数读取子模块,用于读取可读计数参数CanReadCount的值;
CanReadCount参数迭加子模块,用于按照所述n个线程进队push的操作,迭代增加所述CanReadCount的值;
其中,所述第二出队pop模块包括:
CanReadCount参数读取子模块,用于读取可读计数参数CanReadCount的值;
CanReadCount参数递减子模块,用于递减所述CanReadCount的值;
第四判断子模块,用于在获得递减后的CanReadCount的值不为0,则判定所述消息队列为未空;
pop的偏移量计算子模块,用于在所述消息队列未空时,分别计算n个线程出队pop的偏移量;所述n为大于或等于1的正整数;
pop的实际位置计算子模块,用于依据所述n个线程出队pop的偏移量,分别计算所述n个线程出队pop的实际位置;
pop操作执行子模块,用于所述n个线程分别在其出队pop的实际位置执行出队pop操作;
CanWriteCount参数读取子模块,用于读取可写计数参数CanWriteCount的值;
CanWriteCount参数迭加子模块,用于按照所述n个线程出队pop的操作,迭代增加所述CanWriteCount的值;
其中,共享内存写入模块包括:
数据获得子模块,用于获得所述单线程出队pop的数据及其长度;
检查子模块,用于检查所述数据的长度是否超出共享内存的长度界限;
第三指针获取子模块,用于在所述数据的长度未超出共享内存的长度界限时,获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
数据可写判断子模块,用于依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,确定所述数据在共享内存中的写入位置,并判断所述数据是否可写;
写入数据子模块,用于在数据可写时,在所述写入位置写入所述数据;
其中,所述共享内存读取模块包括:
数据定位子模块,用于定位待读取数据所在共享内存的位置;
长度获得子模块,用于获得所述待读取数据的长度;
第四指针获取子模块,用于获取所述共享内存的读偏移指针pRead和写偏移指针pWrite;
数据可读判断子模块,用于依据所述读偏移指针pRead和写偏移指针pWrite,以及,所述数据的长度,判断所述待读取数据是否可读;
读取数据子模块,用于在所述数据可读时,从所述数据所在共享内存的位置,读出所述待读取数据。