【问题标题】:check whether mmap'ed address is correct检查mmap的地址是否正确
【发布时间】:2010-03-25 22:26:36
【问题描述】:

我正在编写一个高负载的守护进程,它应该可以在 FreeBSD 8.0 和 Linux 上运行。守护进程的主要目的是传递由其标识符请求的文件。标识符通过对 db 的请求转换为本地文件名/文件大小。然后我使用连续的mmap() 调用来传递带有send() 的文件块。

但是,有时 db 中的文件大小和文件系统上的文件大小不匹配(realsize

我在打开之前使用安全检查来确保stat() 调用的大小。然而,现实生活向我表明,在极少数情况下仍然可以引发段错误。

那么,我的问题是有没有办法在取消引用之前检查指针是否可以访问?当我在 gdb 中打开核心时,gdb 说给定地址超出范围。 可能有人可以提出另一种解决方案。

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

#define FILENAME        "./datafile"

int main()
{
    unsigned long i, j;

    srand(time(NULL));
    unsigned long pagesize = sysconf(_SC_PAGESIZE);

    unsigned long basesize = 4 * pagesize;
    unsigned long cropsize = 2 * pagesize;

    // create 4*pagesize sized file
    int f = creat(FILENAME, 0644);
    for (i = 0; i < basesize; i++) {
        unsigned char c = (unsigned char)rand();
        if (write(f, &c, 1) < 1) { perror("write"); break; }
    }
    close(f);

    f = open(FILENAME, O_RDONLY);

    // walk trough file
    unsigned char xor = 0;
    unsigned long offset = 0;
    for (j = 0; j < 4; j++) {
        // trunc file to 2*pagesize
        if (j == 2) truncate(FILENAME, cropsize);

        char *data = mmap(NULL, pagesize, PROT_READ, MAP_PRIVATE, f, offset);
        if (data == MAP_FAILED) { perror("mmap"); break; }
        printf("mmap: %lu@%lu for %i\n", pagesize, offset, f);

        for (i = 0; i < pagesize; i++) xor ^= data[i];

        offset += pagesize;
    }

    close(f);

    return 0;
}

【问题讨论】:

    标签: c segmentation-fault freebsd mmap high-load


    【解决方案1】:

    当然我无法从这里证明这一点,但我强烈怀疑您的代码中只是存在簿记错误。如果你调用 mmap 并传入一个大小,并且它成功了,你不应该得到 SIGSEGV。

    我建议您将 valgrind 应用于您的调查。

    在许多 linux 系统上,/proc/PID/maps 会显示哪些区域被映射到哪些访问权限。

    【讨论】:

    • 我已将说明问题的代码示例放在头帖中。此代码模拟文件的创建,然后在使用 mmap 进行时调整其大小。在 Linux 系统上第三步出现 Bus Error,在 FreeBSD 上出现 SegFault。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-25
    • 1970-01-01
    • 2013-02-26
    • 1970-01-01
    • 2012-12-15
    相关资源
    最近更新 更多