我发现了几个问题,但是,我不确定它们是否可以解决您的问题。
name
对shm_open
应开始/
携带使用。- 在
read
和publish
演员一定不能丢弃volatile
。例如:const uint64_t newVal = *(uint64_t volatile*)_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 %lun", v); usleep(100); } }}void reader() { SHM shm; uint64_t magic = 0; uint64_t t = 0; while (true) { if (shm.read(magic, t)) { printf("%lu, %lun", magic, t); } }}int main(int ac, char**) { if(ac > 1) reader(); else sender();}有了
std::atomic您,您可以拥有更多控制权。例如:
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. }


