【问题标题】:How to do asynschronous IO in linux?如何在linux中做异步IO?
【发布时间】:2014-07-08 07:36:23
【问题描述】:

我需要在 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 位机器并且有足够的地址空间。

有没有更好的办法?

【问题讨论】:

  • 你可以在 Linux 上通过 boost::asio 使用 boost 异步 I/O

标签: linux asynchronous io


【解决方案1】:

谷歌搜索“Linux async io”提供了一些关于 AIO 功能的信息 非常神秘。

这是一个例子。

// 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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-23
    • 2016-04-06
    • 1970-01-01
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    • 2018-01-13
    • 2010-10-10
    相关资源
    最近更新 更多