linux - 如何在linux中做异步IO?

标签 linux asynchronous io

我需要在 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/

相关文章:

linux - Ubuntu 终端打开文件后挂起

JQuery同步动画

javascript - 如何等待React Native Image Picker回调函数响应?

c# - 如何在没有额外线程的情况下执行具有等待的任务

linux - 更改目录中数十亿个文件的后缀和前缀

linux - 如何使用 systemd 将应用程序作为守护进程运行?

list - 类型声明中的方括号意味着什么?

java - Java读取文件错误

编译 vsftpd 3.0.0 失败

java - 将 MP3 播放列表保存到文件