Shared-memory through shm_open and mmap: how do I avoid thread or process local caches when reading from my shared-memory?

huangapple go评论72阅读模式
英文:

Shared-memory through shm_open and mmap: how do I avoid thread or process local caches when reading from my shared-memory?

问题

我使用 shm_open + mmap 来编写一个通过共享内存交换数据的消费者和生产者。消费者在一个进程中,生产者在另一个进程中。一切正常,但我如何确保我的消费者不会继续读取缓存内存(线程/进程本地缓存),而是读取生产者写入的最新内容?

以下是我的消费者 C 代码:

#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define STORAGE_ID "/SHM_TEST"
#define STORAGE_SIZE 32

int main(int argc, char *argv[])
{
    int res;
    int fd;
    char data[STORAGE_SIZE];
    pid_t pid;
    void *addr;
    
    pid = getpid();
     
    // 获取共享内存文件描述符(不是文件)
    fd = shm_open(STORAGE_ID, O_RDONLY, S_IRUSR | S_IWUSR);
    if (fd == -1)
    {
        perror("open");
        return 10;
    }
     
    // 将共享内存映射到进程地址空间
    addr = mmap(NULL, STORAGE_SIZE, PROT_READ, MAP_SHARED, fd, 0);
    if (addr == MAP_FAILED)
    {
        perror("mmap");
        return 30;
    }
     
    // 将数据放入内存
    memcpy(data, addr, STORAGE_SIZE);
    
    printf("PID %d: 从共享内存中读取:\"%s\"\n", pid, data);
     
    return 0;
}

希望这对你有帮助!

英文:

I'm using shm_open + mmap to write a consumer and a producer that exchange data through shared-memory. The consumer is in one process and the producer is in another process. All good, but how can I be sure that my consumer is not going to keep reading cached memory (thread/process local cache) instead of the latest contents written by the producer?

Below my consumer C code:

#include &lt;stdio.h&gt;
#include &lt;sys/mman.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;unistd.h&gt;
#include &lt;string.h&gt;

#define STORAGE_ID &quot;/SHM_TEST&quot;
#define STORAGE_SIZE 32

int main(int argc, char *argv[])
{
    int res;
    int fd;
    char data[STORAGE_SIZE];
    pid_t pid;
    void *addr;
    
    pid = getpid();
     
    // get shared memory file descriptor (NOT a file)
    fd = shm_open(STORAGE_ID, O_RDONLY, S_IRUSR | S_IWUSR);
    if (fd == -1)
    {
        perror(&quot;open&quot;);
        return 10;
    }
     
    // map shared memory to process address space
    addr = mmap(NULL, STORAGE_SIZE, PROT_READ, MAP_SHARED, fd, 0);
    if (addr == MAP_FAILED)
    {
        perror(&quot;mmap&quot;);
        return 30;
    }
     
    // place data into memory
    memcpy(data, addr, STORAGE_SIZE);
    
    printf(&quot;PID %d: Read from shared memory: \&quot;%s\&quot;\n&quot;, pid, data);
     
    return 0;
}

答案1

得分: 2

通过使用适当的同步对象(可能本身存储在共享内存中,虽然还有其他选项)来同步对共享内存的访问。@AndrewHenle 在评论中讨论了这个问题。进程共享的互斥锁是自然的选择,因为您很可能希望与之一起使用(进程共享的)条件变量,这将需要一个互斥锁。

您需要应用适当的同步来获得任何有用的程序语义,如果您确实应用了适当的同步,那么这也会解决任何缓存/内存排序的问题。因此,即使您在评论中所说的“一步一步地进行”,确保适当的同步和确保写入的可见性也不是分开的步骤。

英文:

> how can I be sure that my consumer is not going to keep reading cached memory (thread/process local cache) instead of the latest contents written by the producer?

By synchronizing access to the shared memory with an appropriate synchronization object (which might itself live in the shared memory, though there are other options). @AndrewHenle discussed this in comments. A process-shared mutex would be the natural choice, because you are very likely going to want to use a (process shared) condition variable along with it, which will require a mutex.

You need to apply appropriate synchronization to have any kind of useful program semantics, and if you do apply appropriate synchronization then that takes care of any caching / memory-ordering issues too. Thus, even if you're "doing one step at a time", as you put it in comments, ensuring proper synchronization and ensuring visibility of writes are not separate steps.

huangapple
  • 本文由 发表于 2023年6月9日 05:17:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76435747.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定