unistd.h中的pwrite()在C++中不能将数据写入文件。

问题描述 投票:0回答:1

这是我的代码片段。

void
    DirectIO::writeFileUnix(const std::string &file_path,
                            unsigned long long int index,
                            size_t size,
                            std::string &bytes_data) {
        WRITE_COUNT++;

        const int file_descriptor = open(file_path.c_str(),
                                         O_WRONLY | O_DIRECT | O_SYNC | O_CREAT, S_IRUSR | S_IWUSR);
        if (file_descriptor == -1 || size % SECTOR_SIZE != 0) {
            throw std::exception();
        }

        char *buffer = &bytes_data[0];
        ssize_t number_of_bytes_written = pwrite(file_descriptor, buffer, size, index * size);

        if (number_of_bytes_written == -1 || number_of_bytes_written < size) {
            throw std::exception();
        }

        close(file_descriptor);
    }

这个函数在逻辑上似乎是正确的 但是 number_of_bytes_written 始终是-1.如果文件不存在,可能会被创建。如果文件不存在,可能会被创建。我不明白为什么它不工作。

更新1

好了,我知道问题所在了。char* buffer 是由空字符限制的。因此,这一行 char *buffer = &bytes_data[0]; 将指向字符串的一小部分。bytes_data.

当我知道这一点后,我把这部分代码更新为

void *buffer = bytes_data.data();
        ssize_t number_of_bytes_written = pwrite(file_descriptor, buffer, size, index * size);

        if (number_of_bytes_written == -1 || number_of_bytes_written < size) {
            throw std::exception();
        }

还有 data() 的功能 std::string 根据它的C++参考页和它的C++参考页,不关心空字符。这个职位

但还是不行。

如果有人想试一下代码,我把我的样本数据贴在这里试一下。

bytes_data - "\000\000\000\000\005\000\000\000\000\000\000\000\000\000\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\000....\000" (octal representation as supported by clion)
index = 0
size = 4096 (length of bytes_data)
file_path = "abc.binary"

更新2

我试着写了一个没有空字符的字符串,但它仍然抛出了一个错误。因此,问题不在于空字符。这似乎是一些内存对齐的问题,因为磁盘对齐已经处理好了(我可能错了,因为我的C++知识有限)。

c++ unix file-io unistd.h
1个回答
1
投票

由于,最后在问题中更新了,这个问题不是因为null字符。好吧,在某些时候是这样的,但上次编辑中修改的代码确保了null字符不会引起问题。

在@IanAbbott的帮助下,我发现问题出在(虚拟)内存对齐上。在此之前,我一直以为只有文件偏移量才需要对齐。但通过查看 扉页 open(),我发现虚拟内存地址空间也需要与SECTOR_SIZE对齐。

通过多看一些文章和文档,我发现 mmap 是为这个任务提供的。返回的地址是 mmap 储存空间 始终是对齐的。因此,最后,我使用mmap做任务,代码运行没有任何错误。

© www.soinside.com 2019 - 2024. All rights reserved.