如何在没有 malloc 的情况下从 mmap 更改地址值?

How to change value at address from mmap without malloc?

有这个:

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

int main (void) {

    int fd = open("./sometext.txt", O_RDONLY);
    struct stat sb;

    if(fstat(fd,&sb)) perror("in function fstat"); 

    printf("file size is %ld bytes\n\n",sb.st_size);
    char* file_p = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);

    printf("printing file as an array of chars \n\n");
    for(int i =0; i<sb.st_size ; i++){
        if(file_p[i]=='a') //cannot do this
            file_p[i]='5'; //string/char is read-only, but then how?
        printf("%c",file_p[i]);
    }

    munmap(file_p, sb.st_size);
    close(fd);

    return 0;
}

正如我从其他问题中发现的那样,要更改默认为只读的字符串文字,我必须具有数组存储(char arr[] = "sometext_to_change_in_loop")或创建另一个指针,malloc 需要space然后从malloc中复制那个指针的字符串的首地址。但是如何在不执行其中任何一个的情况下更改字符串 "in-line" 呢?

编辑: 是的,主要问题是我没有对 mmap 调用中的 int prot 参数进行按位或运算。可是,怎么可能只有这样就够了?

1) - 我在 open 调用中 没有 更改 int flags,那么为什么 opened 与 O_RDONLY 而不是 O_RDWD ,这使得同一个文件也可写(我正在通过 file_p[i] = '5': 写作)。

2)在 mmap 中如何实际保存更改 我在参数 int flags MAP_PRIVATE 中有,但我想保存更改,所以我应该 MAP_SHARED?根据本教程:enter link description here 其中打开标志和 mmap 标志在我编写时都已更改。我也需要解释一下。

编辑2: 从教程。在不同的写入文件的情况下确实需要它:

for(int i =0; i<sb.st_size ; i++){
        file_p[i] = toupper(file_p[i]);
        printf("%c",file_p[i]);
    }

这将要求open 标志设置为 O_RDWR 并将 mmap 标志设置为 MAP_SHARED。但为什么?为什么对文件 file_p[i]='5' 的一个更改与另一个更改 file_p[i]=toupper(file_p[i]) 不同?为什么 一个更改需要设置两个标志(第一种情况),而另一个 需要它(第二种情况)?我现在很困惑。

尝试改变

char* file_p = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);

char* file_p = mmap(0, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);

您似乎问了两个完全不同的问题,一个是关于 mmap() 的,另一个是关于字符串文字的。先拿后者:

to change string literal, which is read-only by defaul, I have to either have array storage (char arr[] = "sometext_to_change_in_loop") or make another pointer, malloc need space and then copy the first address of the string that pointer from malloc. But how to change the string "in-line" without doing either of those?

回应我对这个问题的评论,没有定义的方法来修改字符串文字。任何这样做的尝试都会产生未定义的行为。但是,许多字符串不是文字,如果它们具有可修改类型的元素并存储在可写存储中,则可以通过各种字符串和 I/O 函数以及对它们所在的数组的普通访问来修改它们。特别是,可以将字符串文字的内容复制到这样的 space 中,然后修改生成的单独字符串。


至于 mmap() 个问题,首要问题似乎是如何映射文件以便可以通过映射修改内容。你的另一个答案已经解决了这个问题,它观察到允许的映射访问是由作为 mmap() 的第三个参数传递的位掩码控制的,如 by POSIX 所述。有单独的位用于读取、写入和执行对映射内容的访问。

您继续要求澄清:

1) - I do not change int flags in open call, so why does it work when opened with O_RDONLY and not with O_RDWD [sic] which makes the same file writeable as well

我能理解这种观察可能会让人感到惊讶。 mmap()建立的映射不通过提供的文件描述符访问底层对象,因此描述符的模式无关紧要。文件描述符仅用作要映射的数据的(部分)标识。通过映射访问的权限由 mmap() 的参数单独定义,如果进程对映射对象没有足够的权限以请求的模式访问它,mmap() 调用将失败。

How can be actually changes saved when in mmap I have in argument int flags MAP_PRIVATE, but I want to save changes, so I should have MAP_SHARED?

你把两个不同的东西混为一谈了。已经讨论过的访问模式决定了您是否可以写入映射。 MAP_PRIVATEMAP_SHARED 控制其他进程是否可以 查看 此类写入,无论是在它们自己的映射副本中还是在基础文件中。 POSIX 表示这是关于 disposition 写入映射。使用 MAP_SHARED,它们修改基础对象。使用 MAP_PRIVATE,它们不会修改底层对象,并且它们仅对执行写入的进程可见。

不完全清楚你在第二次编辑中问的是什么,但我认为它是关于通过文件描述符写入底层对象并试图通过映射观察变化。当然,如果要使用文件描述符写入文件,则需要以允许写入的模式打开文件描述符。此外,然而,要通过已建立的内存映射查看更改,该映射应配置为共享映射。

正如 POSIX 所说:"It is unspecified whether modifications to the underlying object done after the MAP_PRIVATE mapping is established are visible through the MAP_PRIVATE mapping." 这几乎是已经讨论过的 MAP_PRIVATE 语义的另一面:不仅对映射的写入没有反映在底层对象,但是通过映射也可能看不到对底层对象的修改。再次记住,由 mmap() 建立的映射不通过提供的文件描述符访问底层对象。