我需要在 Linux 中做一些非正统的操作。我有 2 个硬盘驱动器连接为 /dev/sda
和 /dev/sdb
。第一个是 1TB,第二个是 4TB。我需要逐字节比较 1TB 驱动器的内容是否与 4TB 驱动器的前 1TB 匹配(是的,我知道这很奇怪,但这是有原因的)。
现在,1TB 的数据量很大。由于这些是传统硬盘驱动器,平均读取速度将在 100MB/s 左右。以这种速度,读取 1TB 将需要 10,000 秒或大约 2 小时 45 分钟。最有可能接近 3 小时。
如果我采用天真的“阅读一个然后阅读另一个”的方法,总时间约为 6 小时。我想通过同时读取两个驱动器来做得更好。 :)
不幸的是,我对 Linux 相当陌生。我对 Windows 了如指掌,并且可以在午餐时间之前在那里编写这样的程序,但 Linux 是另一种野兽。谷歌搜索“Linux async io”给出了一些关于 AIO functions 的信息这是非常神秘的。
或者,我想我可以生成两个线程用于读取,第三个线程用于比较。 mmap()
可能也很有用,因为它是 64 位机器并且有足够的地址空间。
有没有更好的办法?
最佳答案
Googling for "Linux async io" gives something about AIO functions which are pretty cryptic.
这是一个例子。
// Link with '-lrt'.
#define _FILE_OFFSET_BITS 64
#define _GNU_SOURCE
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <aio.h>
#define BUFSIZE 0x100000 // 1 MiB
int xopen(const char *path)
{
int fd = open(path, O_RDONLY|O_DIRECT);
if (fd < 0) perror(path), exit(EXIT_FAILURE);
return fd;
}
void *xalloc()
{
void *mem = memalign(0x1000, BUFSIZE);
if (!mem) perror("memalign"), exit(EXIT_FAILURE);
return mem;
}
void xread(struct aiocb *cbp)
{
if (aio_read(cbp) < 0) perror("aio_read"), exit(EXIT_FAILURE);
}
size_t xwait(struct aiocb *cbp)
{
if (aio_suspend((const struct aiocb **)&cbp, 1, NULL) < 0)
perror("aio_suspend"), exit(EXIT_FAILURE);
if (aio_error(cbp)) perror("aio_error"), exit(EXIT_FAILURE);
ssize_t n = aio_return(cbp);
if (n < 0) perror("aio_return"), exit(EXIT_FAILURE);
cbp->aio_offset += n; // prepare for next read
return n;
}
size_t min(size_t a, size_t b) { return a < b ? a : b; }
main()
{
int lt = 0, gt = 0, eq = 0; // counters for chunks A less, greater, equal B
int fd[2] = { xopen("/dev/sda"), xopen("/dev/sdb") };
// 2 buffer pairs: one for reading data, other holding previously read data
char *buf[2][2] = { xalloc(), xalloc(), xalloc(), xalloc() };
_Bool flp = 0; // flag which buffer pair to use for reading data
struct aiocb cb[2] =
{ { .aio_fildes = fd[0], .aio_nbytes = BUFSIZE },
{ .aio_fildes = fd[1], .aio_nbytes = BUFSIZE }
};
size_t n = 0;
do
{
cb[0].aio_buf = buf[0][flp], cb[1].aio_buf = buf[1][flp], flp = !flp;
xread(&cb[0]), xread(&cb[1]);
if (n) // Do we have previously read data to work on?
{
int s = memcmp(buf[0][flp], buf[1][flp], n);
if (s < 0) ++lt; else if (s > 0) ++gt; else ++eq;
}
} while (n = min(xwait(&cb[0]), xwait(&cb[1])));
close(fd[0]), close(fd[1]);
if (eq) printf("%7d chunks of A equal to B\n", eq);
if (lt) printf("%7d chunks of A less than B\n", lt);
if (gt) printf("%7d chunks of A greater than B\n", gt);
return 0;
}
关于linux - 如何在linux中做异步IO?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23753054/