【问题标题】:How can I write a I/O bound C program?如何编写 I/O 绑定的 C 程序?
【发布时间】:2016-10-17 23:10:25
【问题描述】:

我必须编写 I/O Bound 的程序,这将使我的 I/O 调度程序以前所未有的方式工作,以完成操作系统作业,但我不知道该怎么做。我尝试编写一个简单的 C 程序来计算大文本文件的行数,但它执行得太快,我无法用它来衡量我的调度程序的有效性。这占我成绩的 25%,任何帮助将不胜感激。

【问题讨论】:

  • 使用更大的文件?
  • I/O bound是指硬盘I/O,还是可以接受其他类型的I/O?跨度>
  • @user3386109 其他类型的I/O都可以接受,我只是假设硬盘I/O更贵,我这里需要的东西很贵
  • 网络 I/O 的优势在于它只是推动电子,不会损坏您的硬盘。 Here's a starting point for network I/O。在该示例中,客户端和服务器在 4 条消息后停止,但没有什么可以阻止您永远发送/接收。
  • 使用网络IO的好处是可以故意让另一端真的很慢。

标签: c linux io operating-system scheduler


【解决方案1】:

从我的测试来看,上一个答案似乎比 i/o 更多的 CPU 限制。

我建议使用低级非缓存 C 例程打开许多文件并在每个文件中疯狂地寻找。以下是执行搜索的 C 代码:

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char **argv) {

    if (argc != 2) {
        fprintf(stderr, "specify a file to read!\n");
        return EXIT_FAILURE;
    }

    int fd = open(argv[1], O_DIRECT);
    if (fd < 0) {
        perror("open error");
        return EXIT_FAILURE;
    }

    off_t size = lseek(fd, 0, SEEK_END);

    for (int i = 0; i < 1000000; i++)                                                                                
        lseek(fd, rand() % size, SEEK_SET);

    close(fd);

    return EXIT_SUCCESS;
}

然后,在 shell 中,通过 find 对文件系统中的每个文件运行它:

find / -exec ./io_bound {} \; 2>/dev/null

在我的系统上运行良好,可以发现 rcu_sched 任务:

top - 20:44:48 up 57 min,  1 user,  load average: 0.84, 0.76, 0.59
Tasks: 266 total,   2 running, 264 sleeping,   0 stopped,   0 zombie
%Cpu0  : 10.0 us, 11.3 sy,  0.0 ni, 78.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu1  : 10.3 us,  8.3 sy,  0.0 ni, 81.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu2  : 15.3 us, 15.9 sy,  0.0 ni, 68.4 id,  0.3 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu3  : 16.4 us, 14.7 sy,  0.0 ni, 68.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 16314192 total,  9431208 free,  3312716 used,  3570268 buff/cache
KiB Swap: 15624188 total, 15624188 free,        0 used. 12630464 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND     
13087 gluckf    20   0    4224    784    708 R   3.3  0.0   0:00.10 io_bound    
    7 root      20   0       0      0      0 S   0.3  0.0   0:03.54 rcu_sched   
 1586 root      20   0  455832  74824  62736 S   0.3  0.5   0:41.49 Xorg        
 2160 gluckf    20   0 1389916 137096  52548 S   0.3  0.8   0:41.27 cinnamon    
 2285 gluckf    20   0  498388  46752  28632 S   0.3  0.3   0:14.15 gnome-term+ 

【讨论】:

  • 你是对的,谢谢。我本来打算在每个随机位置读取几个扇区(以避免缓存)但完全忘记了!我不确定如何在这里插入代码。
  • 只需使用 pread() 从随机偏移量读取 512 字节缓冲区 - 不需要 lseek()。您可以使用~(0x1FF)(511 的补码)屏蔽随机偏移量,以获得 512 字节对齐的偏移量,并希望抓取单个随机磁盘块(假设为 512 字节磁盘块)。要真正成为 IO 绑定,请使用多个线程。
  • 好的@AndrewHenle,那么这个程序真的是IO绑定的吗?我在你和 flg 的谈话中迷路了,不知道该怎么办
  • @Fagundes 应该是 - 除非 rand() 调用花费太多时间阻塞,等待更多熵。而rand() 可能无法产生足够的范围——它仅限于RAND_MAX,这可能太小了。如果是这样,you can use lrand48().
【解决方案2】:

试试这个:

find / | head -n 1000000 | xargs -P 10 wc >/dev/null 2>&1

应该很糟糕。 xargs -P 选项使其并行运行。您可以调整选项以获得合适的负载。 wc 除了消耗每个文件之外并没有做太多事情,所以认为它应该主要是 IO 绑定的。当然还有磁盘缓存。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-21
    • 2013-12-18
    • 1970-01-01
    • 2015-05-24
    • 1970-01-01
    • 2011-09-04
    • 2014-10-28
    • 1970-01-01
    相关资源
    最近更新 更多