带有 Mappedbus 的 Java IPC - 在 EOF 上重置文件

Posted

技术标签:

【中文标题】带有 Mappedbus 的 Java IPC - 在 EOF 上重置文件【英文标题】:Java IPC with Mappedbus - reset file on EOF 【发布时间】:2016-12-21 13:34:18 【问题描述】:

我在两个 JVM(oracle jdk 1.8、linux arm)之间使用 Mappedbus 进行 IPC; 我希望看到 IPC“永远”工作,但由于内存映射(或共享内存)文件是有限的,因此在编写器之前或之后会收到 EOFException。

所以我尝试重置写入器(和读取器),但在关闭并重新打开写入器后,读取器无法读取新记录。

所以,问题是,如何使以下测试用例工作,即在编写者和阅读器工作的情况下永远持续下去?

 // intentionally low, for this test case
 final long FILE_SIZE = 2000L;

 private final String fileName = "/dev/shm/ipc-message";

 @Test
 public void hello() throws IOException 

    MappedBusReader reader;

    MappedBusWriter writer;
    writer = new MappedBusWriter(fileName, FILE_SIZE, 128, false);

    writer.open();  

    reader = new MappedBusReader(fileName, FILE_SIZE, 128);

    reader.open();        

    int writeCounter = 0;
    int readCounter = 0;

    while (true) 

        IpcMessage message = new IpcMessage();

        message.source = 1; 

        message.value = 1;
        message.destination = 2;

        message.body = new byte [32];

        try 

            writer.write(message);       

         catch (EOFException ex) 
            System.out.println("write EXCEPTION");

            writer.close();

            writer = new MappedBusWriter(fileName, FILE_SIZE, 128, false);

            writer.open();  
        

        System.out.println("write: " + writeCounter++);

        try 
            if (reader.next()) 

                    boolean recovered = reader.hasRecovered();
                    int type = reader.readType();

                    System.out.println("read: " + readCounter++);

                    reader.readMessage(message);   

            
          catch (EOFException ex) 

            System.out.println("read EXCEPTION");

            reader.close();

            reader = new MappedBusReader(fileName, FILE_SIZE, 128);

            reader.open(); 

        

    



 

IpcMessage 在哪里:

public class IpcMessage implements MappedBusMessage, Serializable 

    public static final int TYPE = 0;

    public int messageType;
    public int value;

    public int source;
    public int destination;


    @Override
    public void write(MemoryMappedFile mem, long pos) 

        mem.putInt(pos, messageType); 
        mem.putInt(pos + 4, value); 

        mem.putInt(pos + 8, source);
        mem.putInt(pos + 12, destination);
    

    @Override
    public void read(MemoryMappedFile mem, long pos) 

        messageType = mem.getInt(pos);
        value = mem.getInt(pos + 4);

        source = mem.getInt(pos + 8);
        destination = mem.getInt(pos + 12); 

    

    @Override
    public int type() 
        return TYPE;
    




我从这个测试用例得到的输出是:

write: 0
read: 0
write: 1
read: 1
write: 2
read: 2
...
write: 8
read: 8
write: 9
read: 9
write: 10
read: 10
write: 11
read: 11
write: 12
read: 12
write: 13
read: 13
write EXCEPTION
write: 14
write: 15
write: 16
write: 17
write: 18
write: 19
write: 20
write: 21
write: 22
write: 23

【问题讨论】:

我会冒险猜测你会从套接字获得更好的性能,因为你似乎在做线性 IO,尽管这当然取决于用例。 参见例如this answer 类似的问题。 FWIW,SHM不是内存映射的文件,磁盘 IO 会消耗大量性能并增加管理 EOF 等复杂性。 @LukeBriggs:实际上我在不同的 JVM 中有三个进程在它们之间进行通信,所以像 Jgroups 这样的多播套接字解决方案可能是解决方案。 【参考方案1】:

我收到了来自 Mappedbus 开发者的电子邮件对我的问题的回答,我认为这很有趣,所以我在这里复制它:

这里简要回答了这个问题: https://github.com/caplogic/Mappedbus/issues/1

简而言之,mappedbus 适用于需要存储所有 消息。如果你不需要这样做,它可能不是正确的 解决方案。

如果您确实需要存储它们,只需使文件足够大即可 能够包含系统生命周期中的所有消息 (例如一天)。然后有一段时间你停止一切 组件,重命名文件并重新启动它们。

【讨论】:

以上是关于带有 Mappedbus 的 Java IPC - 在 EOF 上重置文件的主要内容,如果未能解决你的问题,请参考以下文章

带有 IPC_EXCL 的 shmget

IPC_RMID 不适用于带有 C++ 的 linux

带有用于 IPC 的 WndProc 覆盖的本机 SendMessage 不起作用

带有命名管道的 C 中的 IPC

带有 IPC::Run 的 Perl 命令执行器

带有 QSharedMemory 的 IPC 和如果进程之一挂起的风险