已解决:C和Python:通过mmap填充一个文件为空

Resolved: C and Python: fill a file empty through mmap

我想在 C(创建映射文件并且只从中读取)和 python(写入和填充映射文件)之间创建一个共享映射文件。我有这个 C 代码:

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

int main(void)
{
    char *shared;
    int fd = -1;
    fd = open("hello.txt", O_RDWR, 0);
    if (fd == -1) {
        printf("unable to open");
        return 0;
    }

    shared = (char *)mmap(NULL, 1, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    system("python /home/giuseppe/Documents/test_mmap/mappalo.py");
    printf("C CODE: %c\n",shared[0]);

}

这是一个 python 代码:

import sys
import os
import mmap

with open( "hello.txt", "wb" ) as fd:
    fd.write("1")
with open( "hello.txt", "r+b" ) as fd:
    mm = mmap.mmap(fd.fileno(), 0, flags=mmap.MAP_SHARED, access=mmap.ACCESS_WRITE, offset=0)
    print("content read from file")
    print(mm.readline())
    mm[0] = "01"
    mm.close()
    fd.close()

当我执行 C 代码时,出现此错误:

content read from file
1
Traceback (most recent call last):
  File "/home/giuseppe/Documents/test_mmap/mappalo.py", line 11, in <module>
    mm[0] = "01"
IndexError: mmap assignment must be single-character string
C CODE: 1

如何从 python 代码中写入映射文件中的长字符串,然后从 C 代码中读取它?

非常感谢您的宝贵时间

更新 我想写两个字符串,所以我写了这段代码:

arr = bytes("Hello123;", 'utf-8')
arr1 = bytes("Hello412;", 'utf-8')
size = sys.getsizeof(arr) + sys.getsizeof(arr1)

with buf:
    buf[:size] = struct.pack('ss', arr1, arr)

但是我有以下错误:

IndexError: mmap slice assignment is wrong size

更新 2 感谢 Sam Mason 让我解决问题。这是代码:

C代码:

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

int main(void)
{
  int fd = open("hello.txt", O_RDWR | O_CREAT, 0666);
  if (fd == -1) {
      perror("unable to open");
      return 1;
  }

  if (ftruncate(fd, 4096) < 0) {
    perror("unable to set length");
    return 1;
  }

  int *shared = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  //system("python3.7 mappalo.py");
  printf("C CODE: %s\n", shared);
  return 0;
}

Python代码:

import mmap
import struct

with open('hello.txt', 'r+b') as fd:
    buf = mmap.mmap(fd.fileno(), 4096, access=mmap.ACCESS_DEFAULT)

arr = bytes("Hello123;", 'utf-8')
arr1 = bytes("Hello412;", 'utf-8')
size = len(arr) + len(arr1)
types = str(len(arr))+'s' + str(len(arr1))+'s'

with buf:
    buf[:size] = struct.pack(types, arr1, arr)

您在 C 代码和 Python 代码中都做了各种奇怪的事情。我将从 "works":

的一些代码开始

首先,C代码:

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

int main(void)
{
  int fd = open("hello.txt", O_RDWR | O_CREAT, 0666);
  if (fd == -1) {
      perror("unable to open");
      return 1;
  }

  if (ftruncate(fd, 1024) < 0) {
    perror("unable to set length");
    return 1;
  }

  int *shared = mmap(NULL, 1024, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  system("python mmap-test.py");
  printf("C CODE: %i %i\n", shared[0], shared[1]);
  return 0;
}

我对 headers 进行了一些修改,并确保文件中包含一些数据(在这种情况下,内核将用零延迟填充)。我也将其视为 int 的数组,因为单个字节传输毫无意义。此外,通常建议您不要从 void* 转换为另一种类型。我还将权限掩码设置为合理的值,零会在以后破坏。

下一个Python代码:

import mmap
import struct

with open('hello.txt', 'r+b') as fd:
    buf = mmap.mmap(fd.fileno(), 1024, access=mmap.ACCESS_DEFAULT)

with buf:
    buf[:8] = struct.pack('ii', 123, 7901)

我就打开一次,把数据映射进去,把两个Pythonint编码成两个C-int的字节数组。 with 语句的 non-nesting 是为了表明 mmap 使文件自行打开,但您可能希望将它们嵌套在您自己的代码中。 Python 中的两个 open 还创建了第二个文件(同名,替换了 C 文件),这可能令人困惑。此外,您没有将正确的 sized/typed 数据写入 mmaped space