【发布时间】:2011-09-08 11:00:21
【问题描述】:
当缓冲区在堆栈上时,以下代码会失败,但在堆上分配时会成功。我在带有 Raid 驱动器的 RHEL 5.3 上对其进行了测试。是否可以将 O_DIRECT 与堆栈缓冲区一起使用?
#define _GNU_SOURCE
#include <stdio.h>
#include <assert.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <malloc.h>
#define K 1024
#define ALIGNMENT (4*K)
#define RDSIZE (16*K)
#define BLOCKSIZE (512*K)
int main()
{
int flags = O_RDONLY | O_LARGEFILE;
int n = 0;
int fd = 0;
char* buf = (char *) memalign(ALIGNMENT, BLOCKSIZE);
//char buf[BLOCKSIZE] __attribute__((__aligned__(ALIGNMENT)));
assert(((long)buf) % ALIGNMENT == 0);
fd = open("test", flags | O_DIRECT);
if (fd < 0) {
perror("file open");
return -1;
}
n = read(fd, buf, RDSIZE);
if (n < 0) {
perror("file read");
return -1;
}
printf("%d\n", n);
close(fd);
}
更新:使用 Intel CC 编译时相同的代码成功。
【问题讨论】:
-
+1 提出了一个很好的问题。我假设 assert() 成功而 open() 失败?什么是 perror() 打印?
-
旁注:
#define ALIGNMENT (4*K)等等。否则你会遇到麻烦,因为 C 预处理器是基于令牌的。见C FAQ 10.1。 -
很好地抓住了宏观问题,这是对问题的快速而肮脏的再现,所以请原谅我的不良风格
-
打开成功。使用带有错误打印无效参数的堆栈缓冲区时读取失败。
-
好的,这看起来确实像一个编译器错误。您的程序在 Ubuntu Natty (gcc 4.5.2)、CentOS 5.5 (gcc 4.1.2) 和 Suse 11 SP1 (gcc 4.3.4) 上运行良好。如果要调试编译器,请使用“-S”编译生成 foo.s,然后将其发布到某处...