我想说我要存储一个C数组(固定长度N
)的结构:
typedef struct {
type0 field0;
type1 field1;
} foo_struct;
foo_struct array[N];
在一个文件中,以便程序可以从文件中读取数组,对其进行操作并将其写回。
程序可以使用系统调用write
来编写typen
的每个实例。然后当我们调用程序读取时,如果我们假设sizeof(typen)
返回与之前相同的内容,我们可以在内存中分配数组,并使用read
来填充字段。我认为由于可移植性问题,没有办法可以立即可靠地填充整个结构,如果我错了,请纠正我。
但这对我来说太慢了。即使我立刻将所有内容读入大缓冲区,我也必须复制到字段中。发生的事情是我的数据大小是" yuuge",但操作是零星的。读取和复制将比实际数据访问花费更多时间。
所以我更喜欢使用mmap
而我假设mmap
按需工作 - 如果我错了,请再次纠正我。
现在,这可能会更快,但我在访问内存中的数据时会遇到一些麻烦。
从mmap
指定一个返回值本身是一个坏主意,该函数会为您返回缓冲区,但不保证对齐,即使它在sizeof(foo_struct)
的倍数上对齐,这仍然无法保证我可以访问带有指向结构和->
运算符的指针的字段。
所以我认为,我必须忘记识别结构,只需将我的数组视为一系列大小S0 = sizeof(field0)
S1 = sizeof(field1)
S = S0 + S1
,并按以下方式计算:通过使用指针算法来获取数据的位置:
buffer + M * S
buffer + M * S + S0
然后,即使该指针未对齐,所以如果我想读取或写入fieldn
,我必须将数据拆分为字节并逐字节地执行,这很慢。尽管这些访问并不多,但是,整个过程有很多次迭代,所以我仍然要尽可能快地完成它。
有没有办法使用mmap
(或其他一些方式让我不必阅读整个yuuge文件),但是,不必逐个字段和字节访问数据逐字节?
如果我写的一些内容违反Linux或普通体面,请分享,因为我不完全确定它没有。
答案 0 :(得分:1)
仅出于演示目的,标准从二进制文件中读取struct-array :
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
struct omg{
int num;
char buff[122];
double values[23];
};
#define NNN (3*1024*1024)
#define FILENAME "omg.dat"
#define COUNTOF(a) (sizeof a/sizeof a[0])
struct omg array[NNN];
int main(void)
{
int fd;
int ret, ii, jj;
fprintf(stderr, "Sizeof array[0] is %zu\n", sizeof array[0] );
/* initialise the array to nonsence */
for (ii=0; ii < COUNTOF(array); ii++) {
array[ii].num=ii;
sprintf(array[ii].buff, "Hello world %d", ii);
for (jj=0; jj < COUNTOF(array[0].values); jj++) {
array[ii].values[jj] = ii / (jj+1) ;
}
}
fd = open(FILENAME, O_RDWR|O_CREAT, 0660);
if (fd < 0) return 1;
ret = read(fd, array, sizeof array);
fprintf(stderr, "Read %d/ %zu\n", ret, sizeof array);
/* modify the nonsence */
for (ii=0; ii < COUNTOF(array); ii++) {
array[ii].num += 1;
sprintf(array[ii].buff, "Hello world %d", array[ii].num);
for (jj=0; jj < COUNTOF(array[0].values); jj++) {
array[ii].values[jj] = array[ii].num / (jj+1) ;
}
}
ret = lseek(fd, 0, SEEK_SET);
fprintf(stderr, "Seek = %d\n", ret);
ret = write(fd, array, sizeof array);
fprintf(stderr, "Wrote %d/ %zu\n", ret, sizeof array);
close(fd);
return 0;
}
结果:
plasser@pisbak$ vi readstruct.c
plasser@pisbak$ cc -Wall -O2 readstruct.c
plasser@pisbak$ time ./a.out
Sizeof array[0] is 312
Read 981467136/ 981467136
Wrote 981467136/ 981467136
real 0m3.972s
user 0m1.689s
sys 0m0.782s
现在,我不会在4秒慢中打电话给读书加900MB。
大多数用户CPU可能被sprintf()
调用消耗。