Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 无法读取共享内存_C++_Linux_G++ - Fatal编程技术网

C++ 无法读取共享内存

C++ 无法读取共享内存,c++,linux,g++,C++,Linux,G++,我试图通过共享内存发布一些随机的东西;出于某种奇怪的原因,读者没有读到发件人写的东西 #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include <unistd.h> #include <sys/types.h> #include <cstdio> class SHM { volatile char* _ptr; public:

我试图通过共享内存发布一些随机的东西;出于某种奇怪的原因,读者没有读到发件人写的东西

#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/types.h>
#include <cstdio>

class SHM {
    volatile char* _ptr;
public:
    SHM() {
        const auto handle = shm_open("myTest", O_RDWR|O_CREAT, 0666);
        const auto size =  4 * 1024 * 1024;
        if (-1 == ftruncate(handle, size)) {
            throw;
        }
        _ptr = (volatile char*)mmap(0,size , PROT_READ | PROT_WRITE, MAP_SHARED, handle, 0);

        if(_ptr == MAP_FAILED){
            throw;
        }

                int rc = fchmod(handle, 0666);
                if (rc == -1) {
            throw;
                }
    }

    bool read(uint64_t& magic, uint64_t& time) {
        const uint64_t newVal = *(uint64_t*)_ptr;
        if (newVal != magic) {
            magic = newVal;
            printf("value changed!!!\n");
            time = *(uint64_t*)(_ptr + sizeof(magic));
            return true;
        }
        //printf("old value: %lu\n", newVal);
        return false;
    }

    void publish(const uint64_t time) {
        __sync_fetch_and_add((uint64_t*)_ptr, time);
        __sync_synchronize();
        *(uint64_t*)(_ptr + sizeof(uint64_t)) = time;
    }
};

我发现了几个问题,但是,我不确定他们是否能解决您的问题

  • shm\u open的
    名称
    应以
    /
    开头,以便便携使用
  • read
    publish
    中,强制转换不能丢弃
    volatile
    。例如:
    const uint64\u t newVal=*(uint64\u t volatile*)\u ptr。更好的办法是,去掉volatile,使用std::atomic
  • 尽管涉及到不同的进程,但相同的对象仍然会被多个执行线程访问,并且这些线程中至少有一个会修改共享对象


    我做了上述改变。使用
    std::atomic
    修复了它:

    class SHM {
        void* _ptr;
    public:
        SHM() {
            const auto handle = shm_open("/myTest", O_RDWR|O_CREAT, 0666);
            const auto size =  4 * 1024 * 1024;
            if (-1 == ftruncate(handle, size))
                throw;
    
            _ptr = mmap(0,size , PROT_READ | PROT_WRITE, MAP_SHARED, handle, 0);
    
            if(_ptr == MAP_FAILED)
                throw;
        }
    
        bool read(uint64_t& magic, uint64_t& time) {
            auto p = static_cast<std::atomic<uint64_t>*>(_ptr);
            const uint64_t newVal = p[0];
            if (newVal != magic) {
                magic = newVal;
                printf("value changed!!!\n");
                time = p[1];
                return true;
            }
            return false;
        }
    
        void publish(const uint64_t time) {
            auto p = static_cast<std::atomic<uint64_t>*>(_ptr);
            p[0] += time;
            p[1] = time;
        }
    };
    
    void sender() {
        SHM shm;
        timespec t;
        for (auto i = 0; i < 10000; i++) {
            if (0 == clock_gettime(CLOCK_REALTIME, &t)) {
                const uint64_t v = t.tv_sec * 1000 * 1000 * 1000 + t.tv_nsec;
                shm.publish(v);
                printf("published %lu\n", v);
                usleep(100);
            }
        }
    }
    
    void reader() {
        SHM shm;
        uint64_t magic = 0;
        uint64_t t = 0;
        while (true) {
            if (shm.read(magic, t)) {
                printf("%lu, %lu\n", magic, t);
            }
        }
    }
    
    int main(int ac, char**) {
        if(ac > 1)
            reader();
        else
            sender();
    }
    

    #2确实是个问题——编译器可能优化了
    const uint64\u t newVal=*(uint64\u t*)\u ptr
    。我想知道在哪一点上我可以停止使用volatile限定符,因为我认为声明
    volatile char*\u ptr
    足以告诉编译器不要优化对
    \u ptr
    的访问,因为
    \u ptr
    有一个volatile限定符。希望你能分享一些光明。对于#1,为什么启动/可移植?谢谢@HCSF#1请参阅第二段。@HCSF#1:如果名称以字符开头,则使用相同名称值调用shm#u open()的进程引用相同的共享内存对象,只要该名称未被删除。@HCSF#2如果强制转换为
    (uint64#t volatile*)
    在访问的任何地方都保持一致
    \u ptr
    它也能按预期工作。但是
    std::atomic
    是正确的方法。感谢您提供了一个示例。如果ptr指向C结构(而不是uint64 t),该怎么办<代码>自动p=静态强制转换(ptr);自动v=p->load()然后访问字段v?如果S很大,load()可能会生成一个隐式锁,对吗?如果我坚持使用
    auto p=static\u cast(\u ptr),似乎不会生成隐式锁,对吗?只是想找到一个对延迟影响较小的解决方案。如果是,我是否也需要声明S volatile中的所有字段?当我访问ptr时,编译器似乎并不固有地尊重
    volatile
    。谢谢
    #include <iostream>
    #include "shm.h"
    
    int main() {
        SHM shm;
        uint64_t magic = 0;
        uint64_t t = 0;
        while (true) {
            if (shm.read(magic, t)) {
                printf("%lu, %lu\n", magic, t);
            }
        }
    }
    
    g++ (GCC) 7.2.1 20170829 (Red Hat 7.2.1-1)
    
    class SHM {
        void* _ptr;
    public:
        SHM() {
            const auto handle = shm_open("/myTest", O_RDWR|O_CREAT, 0666);
            const auto size =  4 * 1024 * 1024;
            if (-1 == ftruncate(handle, size))
                throw;
    
            _ptr = mmap(0,size , PROT_READ | PROT_WRITE, MAP_SHARED, handle, 0);
    
            if(_ptr == MAP_FAILED)
                throw;
        }
    
        bool read(uint64_t& magic, uint64_t& time) {
            auto p = static_cast<std::atomic<uint64_t>*>(_ptr);
            const uint64_t newVal = p[0];
            if (newVal != magic) {
                magic = newVal;
                printf("value changed!!!\n");
                time = p[1];
                return true;
            }
            return false;
        }
    
        void publish(const uint64_t time) {
            auto p = static_cast<std::atomic<uint64_t>*>(_ptr);
            p[0] += time;
            p[1] = time;
        }
    };
    
    void sender() {
        SHM shm;
        timespec t;
        for (auto i = 0; i < 10000; i++) {
            if (0 == clock_gettime(CLOCK_REALTIME, &t)) {
                const uint64_t v = t.tv_sec * 1000 * 1000 * 1000 + t.tv_nsec;
                shm.publish(v);
                printf("published %lu\n", v);
                usleep(100);
            }
        }
    }
    
    void reader() {
        SHM shm;
        uint64_t magic = 0;
        uint64_t t = 0;
        while (true) {
            if (shm.read(magic, t)) {
                printf("%lu, %lu\n", magic, t);
            }
        }
    }
    
    int main(int ac, char**) {
        if(ac > 1)
            reader();
        else
            sender();
    }
    
    struct Data {
        std::atomic<uint64_t> time;
        std::atomic<uint64_t> generation;
    };
    
    // ...
    
        bool read(uint64_t& generation, uint64_t& time) {
            auto data = static_cast<Data*>(_ptr);
    
            auto new_generation = data->generation.load(std::memory_order_acquire); // 1. Syncronizes with (2).
            if(generation == new_generation)
                return false;
    
            generation = new_generation;
            time = data->time.load(std::memory_order_relaxed);
            printf("value changed!!!\n");
            return true;
        }
    
        void publish(const uint64_t time) {
            auto data = static_cast<Data*>(_ptr);
    
            data->time.store(time, std::memory_order_relaxed);
            data->generation.fetch_add(time, std::memory_order_release);  // 2. (1) Synchronises with this store.
        }