C++ IPC超过共享内存段-memcpy可见性

C++ IPC超过共享内存段-memcpy可见性,c++,ipc,shared-memory,volatile,memcpy,C++,Ipc,Shared Memory,Volatile,Memcpy,我用C语言编写了共享内存通信 以下结构位于分配段的最开头 typedef struct { int closedCount; int shmId; int semId; int size; volatile bool closed; volatile unsigned int readCount; volatile unsigned int writeCount; volatile bool readBlocked; vol

我用C语言编写了共享内存通信

以下结构位于分配段的最开头

typedef struct {
    int closedCount;
    int shmId;
    int semId;
    int size;
    volatile bool closed;
    volatile unsigned int readCount;
    volatile unsigned int writeCount;
    volatile bool readBlocked;
    volatile bool writeBlocked;
} T_IpcData;
我使用了2个信号量——1个用于reader,1个用于writer

Writer将数据放入共享内存,更新writeCount并通知读取器信号量。如果writeCount-readCount==size,则writer等待writer信号量

读卡器尝试使用memcpy从共享内存中读取writeCount-readCount字节,更新readCount并通知写卡器信号量。若readCount==writeCount,则读取器等待读取器信号量

问题:有时我的应用程序中很少出现错误,这是由于读取的数据与写入的数据不一致造成的

我在单CPU 8核和双CPU 16核机器上运行测试。操作系统-Ubuntu。这一问题很少在这两个网站上重现

问题:memcpy为变更可见性提供了哪些保证?我怎样才能确保读者正确地看到writer线程中所做的所有修改

谢谢

更新代码

template <class T>
    jlong Java_org_gridgain_grid_util_ipc_shmem_GridIpcSharedMemoryUtils_ReadShMem(
        JNIEnv *env, jclass, jlong shMemPtr, T dest, jlong dOffset, jlong len, jlong timeout) {
    T_IpcData *ipcData = (T_IpcData*) (((char *) shMemPtr) - BUF_OFFSET);

    int unreadCnt = GetUnreadCount(ipcData);

    while (unreadCnt == 0) {
        if (unreadCnt == 0 && ipcData->closed) {
            return -1;
        }

        // signal the other party, if it's blocked
        if (ipcData->writeBlocked) {
            if (__DEBUG) {
                cerr << "Before write semaphore notification 1 [semId=" << ipcData->semId << "]\n" << flush;
            }

            SemNotify(env, ipcData->semId, SEM_WRITE, ipcData);
        }

        if (__DEBUG) {
            cerr << "Before read semaphore wait [semId=" << ipcData->semId << "]\n" << flush;
        }

        ipcData->readBlocked = 1;
        SemWait(env, ipcData->semId, SEM_READ, timeout, ipcData);
        ipcData->readBlocked = 0;

        unreadCnt = GetUnreadCount(ipcData);
    }

    int bytesRead = 0;

    while (unreadCnt > 0 && bytesRead < len) {
        int pos = ipcData->readCount % ipcData->size;
        int len0 =  (ipcData->size - pos < unreadCnt)? ipcData->size - pos: unreadCnt;

        if (len0 > len - bytesRead) {
            len0 = len - bytesRead;
        }

        RW::FromShMem(env, dest, dOffset + bytesRead , len0, (void*) (shMemPtr + pos));
        ipcData->readCount += len0;
        bytesRead += len0;

        if (__DEBUG) {
            cerr << "Before write semaphore notification 2 [semId=" << ipcData->semId << "]\n" << flush;
        }

        SemNotify(env, ipcData->semId, SEM_WRITE, ipcData);
        unreadCnt = GetUnreadCount(ipcData);
    }

    return bytesRead;
}

template <class T>
jlong Java_org_gridgain_grid_util_ipc_shmem_GridIpcSharedMemoryUtils_WriteShMem(
    JNIEnv *env, jclass clsName, jlong shMemPtr, T src, jlong sOffset, jlong len, jlong timeout) {
    T_IpcData *ipcData = (T_IpcData*) (((char *) shMemPtr) - BUF_OFFSET);

    int bytesWritten = 0;

    while(bytesWritten < len) {
        // Wait for reader.
        int unreadCnt = GetUnreadCount(ipcData);
        int pos = ipcData->writeCount % ipcData->size;

        while (unreadCnt == ipcData->size) {
            if (ipcData->closed) {
                env->ThrowNew(env->FindClass(GRID_EXCEPTION), "Shared memory segment has been closed.");
                return -1;
            }

            // signal the other party, if it's blocked
            if (ipcData->readBlocked) {
                SemNotify(env, ipcData->semId, SEM_READ, ipcData);
            }

            ipcData->writeBlocked = 1;
            SemWait(env, ipcData->semId, SEM_WRITE, timeout, ipcData);
            ipcData->writeBlocked = 0;

            unreadCnt = GetUnreadCount(ipcData);
        }

        int len0 = ipcData->size - ((pos >  unreadCnt)?  pos :  unreadCnt);

        if (len0 > len - bytesWritten) {
            len0 = len - bytesWritten;
        }

        if (ipcData->closed) {
            env->ThrowNew(env->FindClass(GRID_EXCEPTION), "Shared memory segment has been closed");
            return -1;
        }

        RW::ToShMem(env, src, sOffset + bytesWritten, len0, (void*) (shMemPtr + pos));
        ipcData->writeCount += len0;
        bytesWritten += len0;
        SemNotify(env, ipcData->semId, SEM_READ, ipcData);
    }

    return GetUnreadCount(ipcData);
}

SemWait调用semop,SemNotify调用semctl。

请发布处理信号量的确切代码,访问readCount和writeCount。那里可能有比赛条件,谢尔盖,代码上传了。我已经多次检查它的比赛条件。请看一下,也许我错过了什么。我建议你把这个重新标记到C++,让C++的人检查。完成了,但是CPP没有什么特别的。只有与我观察到的问题无关的模板。