red*_*dot 5 c high-load freebsd mmap segmentation-fault
我正在编写一个高负载的守护进程,它应该在FreeBSD 8.0和Linux上运行.守护程序的主要目的是传递其标识符请求的文件.通过对db的请求将标识符转换为本地文件名/文件大小.然后我使用顺序mmap()调用来传递文件块send().
但是有时文件系统中的db和filesize中的文件大小不匹配(realsize <db中的大小).在这种情况下,我发送了所有实际数据块,当下一个数据块被映射时 - mmap没有返回任何错误,只是通常的地址(我也检查过errno变量,它在mmap之后等于零).当守护进程尝试发送此块时,它会获得Segmentation Fault.(在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;
}
Run Code Online (Sandbox Code Playgroud)
当然,我无法从这里证明这一点,但我强烈怀疑您的代码中存在记账错误。如果您调用 mmap 并传入一个大小,并且成功,您不应该收到 SIGSEGV。
我建议您在调查中应用 valgrind。
在许多 Linux 系统上,/proc/PID/maps 将显示哪些区域映射了哪些访问权限。
| 归档时间: |
|
| 查看次数: |
1606 次 |
| 最近记录: |