在Python 3中从POSIX共享内存中读取C结构

时间:2018-02-09 21:09:59

标签: python c++ linux shared-memory

存在一个包含C struct的共享内存块,它本身包含struct个数组。我所追求的是那个阵列中更深层次的东西。源代码中的布局大致如下所示:

(tl;博士 - 你会怎么做?)

struct proc_data
{
  pid_t proc_id;
  bool initialized;
  bool suppress;
  bool only;
  bool halt;

  pthread_mutex_t mutex_a;
  int64_t total_a;
  bool total_a_flag;

  pthread_mutex_t mutex_b;
  int64_t total_b;
  int64_t long_b;
  bool total_b_flag;

  pthread_mutex_t mutex_c;
  int64_t total_c;
  bool total_c_flag;

  pthread_mutex_t mutex_d;
  int64_t total_d;
  bool total_d_flag;

  std::atomic<int> garbage;
  std::atomic<bool> garbage2;
};

struct gloabl_data
{
  bool initialized;
  bool global_suppress;
  bool global_only;
  bool global_halt;

  uint p_proc_data[50];   //offsets for the following array
  struct proc_data proc_data_arr[50];
};

请原谅匿名命名约定,但你知道它是怎么回事。

我已成功使用sysv_ipc读取此共享内存块,甚至可以将每个程序的PID读取为每个数组元素的第一个成员。整齐。以下代码对我有用:

segment = SharedMemory(ftok(shm_keyfile, ord("r"), silence_warning = True))

offsets = list()

for i in range(0,50): #the hardcoded limit
    offsets.append(int.from_bytes(segment.read(byte_count=4, offset=4+4*i), byteorder='little'))

for offset in offsets:
    pid = int.from_bytes(segment.read(byte_count=4, offset=offset), byteorder='little')
    if(pid == 0): continue

    proc = Process(pid)
    print(str(pid)+" "+str(proc.cmdline()))

但是,一旦我到达pthread_mutex_t,它们似乎都会分崩离析。 sizeof(pthread_mutex_t)在我的平台(x86_64)上是40个字节,但当然可能会有一些填充。

以下代码在for offset in offsets循环中继续:

intra_offset = offset + 4

initialized = int.from_bytes(segment.read(byte_count=1, offset=intra_offset), byteorder='little')))
intra_offset += 1
suppress = int.from_bytes(segment.read(byte_count=1, offset=intra_offset), byteorder='little')))
intra_offset += 1
only = int.from_bytes(segment.read(byte_count=1, offset=intra_offset), byteorder='little')))
intra_offset += 1
halt = int.from_bytes(segment.read(byte_count=1, offset=intra_offset), byteorder='little'))+"\n")
intra_offset += 1

intra_offset += sizeof_pthread_mutex_t # mutex_a
total_a = int.from_bytes(segment.read(byte_count=8, offset=intra_offset), byteorder='little')))
intra_offset += 8
total_a_flag = int.from_bytes(segment.read(byte_count=1, offset=intra_offset), byteorder='little')))
intra_offset += 1

intra_offset += sizeof_pthread_mutex_t # mutex_b
total_b = int.from_bytes(segment.read(byte_count=8, offset=intra_offset), byteorder='little')))
intra_offset += 8
long_b = int.from_bytes(segment.read(byte_count=8, offset=intra_offset), byteorder='little')))
intra_offset += 8
total_b_flag = int.from_bytes(segment.read(byte_count=1, offset=intra_offset), byteorder='little')))
intra_offset += 1

intra_offset += sizeof_pthread_mutex_t # mutex_c
total_c = int.from_bytes(segment.read(byte_count=8, offset=intra_offset), byteorder='little')))
intra_offset += 8
c_flag = int.from_bytes(segment.read(byte_count=1, offset=intra_offset), byteorder='little')))
intra_offset += 1

intra_offset += sizeof_pthread_mutex_t # open pnl mutex
total_d = int.from_bytes(segment.read(byte_count=8, offset=intra_offset), byteorder='little')))
intra_offset += 8
total_d_flag = int.from_bytes(segment.read(byte_count=1, offset=intra_offset), byteorder='little')))
intra_offset += 1

当然,我从中得到的值只是在第一个互斥锁之后的垃圾。我调整了我假定的互斥量大小,并在这里和那里添加了一些填充,但似乎无法获得良好,合理的输出。

我的实际问题是 - 有更简单的方法吗?我还没有通过Python ctypes找到合适的方法来做到这一点,尽管我喜欢走那条路。

欢迎提出任何反馈意见。 =)

0 个答案:

没有答案