Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
206 views
in Technique[技术] by (71.8m points)

python - Python写入映射文件-奇怪的行为(Python writing into a mapped file - strange behaviour)

I have a Python script that can successfully write binary data to a file:

(我有一个可以成功将二进制数据写入文件的Python脚本:)

iterable_array = [i + 32 for i in range(50)]
file_handle = open("a.bin", "wb")
bytes_to_write = bytearray(iterable_array)
file_handle.write(bytes_to_write)
file_handle.close()

However, I get the following error:

(但是,出现以下错误:)

Traceback (most recent call last):
File "python_100_chars.py", line 20, in <module>
file_handle = open("a.bin", "wb")
OSError: [Errno 22] Invalid argument: 'a.bin'

when I try to write while executing the following program (source originally from Microsoft docs) that creates a file mapping and reads the data after a keypress:

(当我尝试在执行以下程序(最初来自Microsoft docs)时编写时,该程序创建文件映射并在按键后读取数据:)

HANDLE hFile = CreateFileA( "a.bin",
                            GENERIC_READ | GENERIC_WRITE,
                            FILE_SHARE_WRITE | FILE_SHARE_READ,
                            NULL,
                            CREATE_ALWAYS,
                            FILE_ATTRIBUTE_NORMAL,
                            NULL);
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = CreateFileMapping(
             hFile,    // use paging file
             NULL,                    // default security
             PAGE_EXECUTE_READWRITE,          // read/write access
             0,                       // maximum object size (high-order DWORD)
             BUF_SIZE,                // maximum object size (low-order DWORD)
             szName);                 // name of mapping object

if (hMapFile == NULL)
{
   _tprintf(TEXT("Could not create file mapping object (%d).
"),
          GetLastError());
   return 1;
}
pBuf = (LPTSTR) MapViewOfFile(hMapFile,   // handle to map object
                     FILE_MAP_ALL_ACCESS, // read/write permission
                     0,
                     0,
                     BUF_SIZE);
if (pBuf == NULL)
{
   _tprintf(TEXT("Could not map view of file (%d).
"),
          GetLastError());

    CloseHandle(hMapFile);

   return 1;
}


 _getch(); 

 printf("string inside file:%s",(char *)((void *)pBuf));
UnmapViewOfFile(pBuf);

CloseHandle(hMapFile);

I've already tested that I can write into the memory-mapped file (and see the results) with basic I/O in the following way:

(我已经测试过可以通过以下方式使用基本I / O写入内存映射文件(并查看结果):)

HANDLE hFile =  CreateFileA(         "a.bin",
                               GENERIC_WRITE,
          FILE_SHARE_WRITE | FILE_SHARE_READ,
                                        NULL,
                               OPEN_EXISTING,
                      FILE_ATTRIBUTE_NORMAL ,
                                        NULL);
char *p = "bonjour";
DWORD bw;
WriteFile(   hFile,
                 p,
                 8,
               &bw,
               NULL);
  • What is the python script doing that prevents it from writing?

    (python脚本在做什么阻止它编写?)

Thank you for any feedback!

(感谢您的任何反馈!)

  ask by thehorseisbrown translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I do not have Windows so I cannot quite test the behaviour, but I believe this happens because Windows does not quite follow the POSIX semantics and open(name, 'wb') will, instead of truncating the existing file, open it with CREATE_ALWAYS which would conflict with the file being mapped in another process.

(我没有Windows,所以我无法完全测试其性能,但是我相信会发生这种情况,因为Windows不太遵循POSIX语义,并且open(name, 'wb')将使用CREATE_ALWAYS打开它,而不是截断现有文件,将与另一个进程中正在映射的文件冲突。)

The ab mode could work too, but... as the Python documentation says

(ab模式也可以工作,但是...正如Python文档所述)

'a' for appending (which on some Unix systems, means that all writes append to the end of the file regardless of the current seek position).

(用于附加的'a' (在某些Unix系统上,意味着所有写操作均附加至文件末尾,而不管当前查找位置如何)。)

Unfortunately the open function uses C semantics for the flag, and hence it is not possible to specify the desired mode as "open the file for random access writing only without truncating the file", so the best you can do is "open it for both reading and writing without truncating the file", which would be r+b .

(不幸的是, open函数对标志使用C语义,因此无法将所需的模式指定为“仅在不截断文件的情况下打开文件以进行随机访问写入”,因此,您最好的做法是“为两个文件同时打开”读取和写入而不截断文件”,这将是r+b 。)


As user Eryk Sun pointed out, the problem is that Windows does not support file truncation at all if there are any existing memory mappings:

(正如用户Eryk Sun指出的那样,问题在于,如果存在任何现有的内存映射,Windows根本不支持文件截断 :)

If CreateFileMapping is called to create a file mapping object for hFile, UnmapViewOfFile must be called first to unmap all views and call CloseHandle to close the file mapping object before you can call SetEndOfFile .

(如果调用CreateFileMapping为hFile创建文件映射对象,则必须首先调用UnmapViewOfFile以取消所有视图的映射,并调用CloseHandle关闭文件映射对象,然后才能调用SetEndOfFile 。)

Likewise there is no mapping of space larger than the existing file - if the mapping is longer than the file size, the file is extended instead...

(同样,不存在比现有文件大的空间映射-如果该映射的长度大于文件大小,则会扩展文件...)


On POSIXly correct platforms, a program like

(在POSIXly正确平台上,类似)

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


int main(int argc, char const *argv[])
{
    struct stat s;
    int fd = open("a.bin", O_RDWR);
    fstat(fd, &s);
    unsigned char *d = mmap(0, s.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    getchar();

    for (int i = 0; i < s.st_size; i++) {
        putchar(d[i]);
    }

    putchar('
');
    fflush(stdout);
    getchar();
}

will not interfere with running the said Python program.

(不会干扰运行所述Python程序。)

However if this C program accesses the file within the within the window while it has been truncated to 0, SIGBUS signal will be raised in the C process.

(但是,如果该C程序在被截断为0时访问了窗口内的文件,则在C进程中将发出SIGBUS信号。)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...