将 strcpy 用于 mmap 文件时出现总线错误(核心已转储)

Bus error (core dumped) when using strcpy to a mmap'ed file

我有一个简单的程序:

int main(void) {
   int fd;
   const char *text = "This is a test";

   fd = open("/tmp/msyncTest", (O_CREAT | O_TRUNC | O_RDWR), (S_IRWXU | S_IRWXG | S_IRWXO) );
   if ( fd < 0 ) {
           perror("open() error");
           return fd;
   }

    /* mmap the file. */
   void *address;
   off_t my_offset = 0;
   address = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED, fd, my_offset);

   if ( address == MAP_FAILED ) {
           perror("mmap error. " );
           return -1;
   }

    /* Move some data into the file using memory map. */
    strcpy( (char *)address, text);

    /* use msync to write changes to disk. */
    if ( msync( address, 4096 , MS_SYNC ) < 0 ) {
    perror("msync failed with error:");
        return -1;
    }
    else {
    printf("%s","msync completed successfully.");
}

    close(fd);
    unlink("/tmp/msyncTest");
}

我的代码有什么问题吗?我做了一些简单的测试,看来问题出在strcpy。但是根据定义,我看没有问题。

如果

fd = open("/tmp/msyncTest", (O_CREAT | O_TRUNC | O_RDWR), (S_IRWXU | S_IRWXG | S_IRWXO) );

成功,fd 将引用零长度文件 (O_TRUNC)。调用 mmap()

address = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED, fd, my_offset);

建立了内存映射,但是页面没有对应对象

http://pubs.opengroup.org/onlinepubs/7908799/xsh/mmap.html对于这种情况有如下说法:

The system always zero-fills any partial page at the end of an object. Further, the system never writes out any modified portions of the last page of an object that are beyond its end. References within the address range starting at pa and continuing for len bytes to whole pages following the end of an object result in delivery of a SIGBUS signal.

同样,man mmap 在 Linux 个笔记上

Use of a mapped region can result in these signals:
[...]
SIGBUS Attempted access to a portion of the buffer that does not correspond to the file (for example, beyond the end of the file, including the case where another process has truncated the file).

因此,您必须 ftruncate() 文件的非零长度 mmap() 之前 mmap()ing 它(除非您正在 mmap()ing匿名记忆)。