如何在python和C / C ++中使用共享内存

时间:2018-03-05 04:57:21

标签: python c++ synchronization multiprocessing

我正在尝试修改python程序,以便能够使用共享内存与C ++程序进行通信。 python程序的主要职责是从位于共享内存中的输入队列中读取一些视频帧,对视频帧执行某些操作并将其写回共享内存中的输出队列。

我相信我需要做的事情很少,如果有人可以对它有所了解,那就太棒了:

  1. 共享内存:在C / C ++中,您可以使用shmgetshmat等函数来获取指向共享内存的指针。在python中处理这个问题的等效方法是什么,所以python和C ++程序都可以使用相同的共享内存?

  2. 同步:因为这涉及多处理,我们需要在C ++和python程序中为共享内存提供某种锁定机制。我怎么能在python中做到这一点?

  3. 非常感谢!

2 个答案:

答案 0 :(得分:1)

或许shmgetshmat不一定是您使用的最合适的界面。在我工作的项目中,我们使用内存映射文件通过C和Python API提供对守护程序的访问,这为我们提供了一种非常快速的数据访问方式

操作顺序有点像这样:

  • 客户端使door_call()告诉守护进程创建共享内存区域
  • 守护程序安全地创建一个临时文件
  • 守护程序open(),然后mmap()该文件
  • 守护程序通过door_return()
  • 将文件描述符传递回客户端
  • 客户端mmap()是文件描述符,并将具有该fd的结构中的连续放置的变量关联起来
  • 客户端在需要时对这些变量执行任何操作 -
  • 守护进程从共享区域读取并执行自己的更新(在我们的示例中,将该共享区域中的值写入日志文件)。

我们的客户使用库来处理上面的前5个步骤;该库附带了使用ctypes的Python包装器,以准确显示所需的函数和数据类型。

对于你的问题空间,如果它只是写入输出队列的python应用程序,那么你可以跟踪python应用程序中已处理的帧。如果你的python和c ++应用程序都写入输出队列,那么这会增加你的难度,也许重构整个应用程序架构将是一个很好的投资。

答案 1 :(得分:1)

Sorta,有点共享内存。因此,OP并非完全如此。

这可以使用内存映射文件进行。我不以任何方式要求高速或高效。这些只是为了展示它工作的示例。

hello_world

C ++端仅监视其所需的值。 Python端仅提供值。

注意:文件名“ pods.txt”在C ++和python代码中必须相同。

.rodata

python端:

 $ python --version
 Python 3.7.9

 $ g++ --version
 g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0

要在终端#1中运行它,

#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
 
int main(void)
  {
  // assume file exists
  int fd = -1;
  if ((fd = open("pods.txt", O_RDWR, 0)) == -1)
     {
     printf("unable to open pods.txt\n");
     return 0;
     }
  // open the file in shared memory
  char* shared = (char*) mmap(NULL, 8, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

  // periodically read the file contents
  while (true)
      {
      printf("0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n", shared[0], shared[1], shared[2], shared[3], shared[4], shared[5],           shared[6], shared[7]);
      sleep(1);
      }

   return 0;
   }

即由于C ++代码中的sleep(2),您应该看到0x01每隔几秒钟移动一次。

在2号航站楼:

import mmap
import os
import time
 
fname = './pods.txt'
if not os.path.isfile(fname):
    # create initial file
    with open(fname, "w+b") as fd:
         fd.write(b'\x01\x00\x00\x00\x00\x00\x00\x00')

# at this point, file exists, so memory map it
with open(fname, "r+b") as fd:
    mm = mmap.mmap(fd.fileno(), 8, access=mmap.ACCESS_WRITE, offset=0)

    # set one of the pods to true (== 0x01) all the rest to false
    posn = 0
    while True:
         print(f'writing posn:{posn}')

         # reset to the start of the file
         mm.seek(0)
 
         # write the true/false values, only one is true
         for count in range(8):
             curr = b'\x01' if count == posn else b'\x00'
             mm.write(curr)

         # admire the view
         time.sleep(2)

         # set up for the next position in the next loop
        posn = (posn + 1) % 8

    mm.close()
    fd.close()

即您应该会看到位置从0到7再次变回0。