【问题标题】:C: Writing data to memory mapped file shows junkC:将数据写入内存映射文件显示垃圾
【发布时间】:2023-04-02 08:58:01
【问题描述】:

我正在尝试将数据写入内存映射文件并且它显示垃圾。不知道我做错了什么。我正在创建一个内存映射文件并将 int 写入它。我看到垃圾输出。

我以读/写方式打开的文件,理想情况下我希望其他进程读取写入其中的数据

代码如下

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

#define FILEPATH "test"
#define NUMINTS  (1000)
#define FILESIZE (NUMINTS * sizeof(int))

int main(int argc, char *argv[])
{
    int i;
    int fd;
    int result;
    int *map;  /* mmapped array of int's */

    /* Open a file for writing.
     *  - Creating the file if it doesn't exist.
     *  - Truncating it to 0 size if it already exists. (not really needed)
     *
     * Note: "O_WRONLY" mode is not sufficient when mmaping.
     */
    fd = open(FILEPATH, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
    if (fd == -1) {
    perror("Error opening file for writing");
    exit(EXIT_FAILURE);
    }

    /* Stretch the file size to the size of the (mmapped) array of ints
     */
    result = lseek(fd, FILESIZE-1, SEEK_SET);
    if (result == -1) {
    close(fd);
    perror("Error calling lseek() to 'stretch' the file");
    exit(EXIT_FAILURE);
    }

    /* Something needs to be written at the end of the file to
     * have the file actually have the new size.
     * Just writing an empty string at the current file position will do.
     *
     * Note:
     *  - The current position in the file is at the end of the stretched
     *    file due to the call to lseek().
     *  - An empty string is actually a single '\0' character, so a zero-byte
     *    will be written at the last byte of the file.
     */
    result = write(fd, "", 1);
    if (result != 1) {
    close(fd);
    perror("Error writing last byte of the file");
    exit(EXIT_FAILURE);
    }

    /* Now the file is ready to be mmapped.
     */
    map = mmap(0, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (map == MAP_FAILED) {
    close(fd);
    perror("Error mmapping the file");
    exit(EXIT_FAILURE);
    }

    /* Now write int's to the file as if it were memory (an array of ints).
     */
    for (i = 1; i <=10; ++i) {
        map[i] = i;
    }

    /* Don't forget to free the mmapped memory
     */
    if (munmap(map, FILESIZE) == -1) {
    perror("Error un-mmapping the file");
    /* Decide here whether to close(fd) and exit() or not. Depends... */
    }

    /* Un-mmaping doesn't close the file, so we still need to do that.
     */
    close(fd);
    return 0;
}

【问题讨论】:

  • 你能检查一下输出文件的十六进制转储吗?
  • 您如何验证您的结果?通过在 text 编辑器中打开文件? map[i] = i; 创建 二进制 数据。如果使用文本工具查看,它将看起来像垃圾。
  • 糟糕,我的错.. hexdump 显示正确的输出。如何编写文本数据而不是二进制数据?
  • 那就是printf() 然后...
  • @DevSolar 我认为您的意思是 snprintf,因为 OP 需要输出到缓冲区而不是 stdout

标签: c


【解决方案1】:

test 的内容与我预期的一样:

$ hexdump -C test
00000000  00 00 00 00 01 00 00 00  02 00 00 00 03 00 00 00  |................|
00000010  04 00 00 00 05 00 00 00  06 00 00 00 07 00 00 00  |................|
00000020  08 00 00 00 09 00 00 00  0a 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000fa0

有你的 10 个整数。

当然,在一个看起来像垃圾的文本编辑器中,因为它是整数的二进制值,而不是ASCII "1""2".. .

【讨论】:

  • www.asciitable.com 的停留可以帮助清理 :)
  • @DavidC.Rankin:由于我正在处理各种编码,并且必须定期检查 0x80-0xff 范围以找出确切的编码,我写了我自己的版本,encoding.rootdirectory.de
  • 这更有意义,很抱歉造成混乱。
猜你喜欢
  • 2022-08-18
  • 2010-10-18
  • 1970-01-01
  • 2016-01-08
  • 1970-01-01
  • 2016-02-23
  • 1970-01-01
  • 2011-09-21
  • 2021-10-27
相关资源
最近更新 更多