gpt4 book ai didi

检查 mmap 的地址是否正确

转载 作者:太空狗 更新时间:2023-10-29 15:07:45 25 4
gpt4 key购买 nike

我正在编写一个应该在 FreeBSD 8.0 和 Linux 上运行的高负载守护进程。守护进程的主要目的是传递由其标识符请求的文件。标识符通过对数据库的请求转换为本地文件名/文件大小。然后我使用顺序 mmap() 调用通过 send() 传递文件 block 。

然而,有时数据库中的文件大小与文件系统中的文件大小不匹配(实际大小 < 数据库中的大小)。在这种情况下,我已经发送了所有真实的数据 block ,并且当下一个数据 block 被映射时——mmap 没有返回错误,只是通常的地址(我也检查了 errno 变量,它在 mmap 之后等于零)。当守护进程试图发送这个 block 时,它会出现段错误。 (此行为保证在 FreeBSD 8.0 amd64 上发布)

我在打开前使用安全检查来确保调用 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;
}

最佳答案

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

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

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

关于检查 mmap 的地址是否正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2519880/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com