Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
yjsslab
V2EX  ›  Linux

/dev/null 的原理是什么?大量写入会影响系统性能吗?

  •  
  •   yjsslab · Apr 13, 2015 · 10048 views
    This topic created in 4082 days ago, the information mentioned may be changed or developed.
    Supplement 1  ·  Apr 14, 2015
    找到一个解释:https://bbs.archlinux.org/viewtopic.php?id=137861

    It's all implemented via file_operations (drivers/char/mem.c if you're curious to look yourself):

    ```
    static const struct file_operations null_fops = {
    .llseek = null_lseek,
    .read = read_null,
    .write = write_null,
    .splice_write = splice_write_null,
    };
    ```

    write_null is what's called when you write to /dev/null. It always returns the same number of bytes
    that you write to it:

    ```
    static ssize_t write_null(struct file *file, const char __user *buf,
    size_t count, loff_t *ppos)
    {
    return count;
    }
    ```

    That's it. The buffer is just ignored.


    写时竟然还 return 一个 size !
    29 replies    2015-04-15 10:02:14 +08:00
    bellchu
        1
    bellchu  
       Apr 13, 2015   ❤️ 9
    /dev/null类似一个黑洞,写入任何东西都会返回成功,但是实际写入数据随即被丢弃。

    /dev/null的io只是软件层面的,实际没有存储的io动作。但是既然是软件层面的,就会有userspace到kernel的system call,会耗费相当多的CPU和内存。

    因为传入/dev/null的数据几乎是在其被从软件传出的同时被丢弃的,所以传输的速度基本没有延迟,CPU占用率基本会迅速被占满。
    bellchu
        2
    bellchu  
       Apr 13, 2015   ❤️ 3
    rming
        3
    rming  
       Apr 13, 2015   ❤️ 1
    好像,貌似,记得,有人说过这个问题,在 C 的实现中,是直接使用的 return
    julyclyde
        4
    julyclyde  
       Apr 13, 2015   ❤️ 1
    @rming 这个不存在所谓在C的实现中的说法。虽说内核都是C写的,但这事和语言没关系
    tabris17
        5
    tabris17  
       Apr 13, 2015
    会有系统调用,所以开销也不算小
    rming
        6
    rming  
       Apr 13, 2015
    @bellchu 说的很对
    rrfeng
        7
    rrfeng  
       Apr 13, 2015   ❤️ 1
    @bellchu

    这个实验说明了 yes 能使 CPU 使用率增加到 100%。
    ryd994
        8
    ryd994  
       Apr 13, 2015
    @bellchu 这只是yes本身的开销而已吧……
    不能认为是/dev/null的
    loading
        10
    loading  
       Apr 13, 2015 via Android
    不是你写到哪,写这个动作就耗资源,只是io部分少很多。
    bellchu
        11
    bellchu  
       Apr 14, 2015
    @ryd994 对哦,那换一个往null写0的,更贴切点
    cat /dev/zero > /dev/null
    bellchu
        12
    bellchu  
       Apr 14, 2015
    @rrfeng 这个实验也说明了频繁写入/dev/null同样会消耗资源影响性能,而不会像很多人想象的输出到null的就不耗费任何资源,但实际上CPU的开销是一样的。

    如果纠结yes命令的话。就换cat /dev/zero > /dev/null,其实效果是一样的,只不过一个是不断输出y,一个是不断输出0.

    我的本意只想表达:把/dev/null当成一个0延迟的IO设备,当IO没有延迟的时候,CPU会成为最大的系统瓶颈,CPU会因为无法及时处理排队的数据而满负载。
    ryd994
        13
    ryd994  
       Apr 14, 2015 via Android   ❤️ 1
    @bellchu 那就变成cat的开销了……
    不过到null没开销这个肯定不可能,系统调用是少不了的。不过有多大开销就很难说了,如果只是百分之一/千分之一,认为可以忽略也没什么。
    bellchu
        14
    bellchu  
       Apr 14, 2015 via iPhone
    @ryd994 楼主和我说的都是写入null造成的开销,不能单纯说是一个进程的开销或者是null的开销

    这类似于讨论网络 A发送包给B 当A到B的延迟很高时会不会性能下降 当A到B基本无延迟时会不会有性能下降。还有性能下降的程度和速度。当量达到一定程度的时候,例如A有无数个副本同时发送数据给B的时候,一定量时B就瘫痪了,ddos成功。

    就像你所说百分之一千分之一的开销基本可忽略,所以很多人喜欢把null当成焚化炉,把垃圾输出全丢null,不占用存储,不消耗io。现代系统的大多数应用的性能瓶颈都是io。

    歪楼了...
    bellchu
        15
    bellchu  
       Apr 14, 2015 via iPhone
    @ryd994 或者换句话说,百分之一千分之一的量不能算是大量。大数据时代要机器所产生的数据很简单就能“大量”。

    可以参照keen.io
    ryd994
        16
    ryd994  
       Apr 14, 2015 via Android
    @bellchu 即使是yes这样的程序,生成这么多数据的开销也比null丢弃这么多的大。那么忽略null的开销就是合理的。
    这时候需要检讨的不是为什么输出到null,而是为什么平白无故生成这么多无用的数据。这么多数据,无论输出到哪里都是浪费。
    这就像listen lo和用socket的区别。用loopback固然比用sock开销大,不过实际上可以忽略。倒不如考虑一下怎么减少不必要的进程间数据交换。
    yjsslab
        17
    yjsslab  
    OP
       Apr 14, 2015
    所以,没有实际的 IO 发生,只是 return count 的开销。
    yjsslab
        18
    yjsslab  
    OP
       Apr 14, 2015
    谢谢楼上各位。
    wizardoz
        19
    wizardoz  
       Apr 14, 2015
    要是写的时候不返回size的话,应用程序岂不是认为没有写进去进而重复写同一个内容?
    bellchu
        20
    bellchu  
       Apr 14, 2015
    @ryd994 你说的都对,但是你没考虑到垃圾达到一定程度的时候的问题。

    http://devnull-as-a-service.com/
    Admstor
        21
    Admstor  
       Apr 14, 2015
    我有时候会把暂时不需要的日志指向null,需要的时候再指向别的地方...
    bellchu
        22
    bellchu  
       Apr 14, 2015
    bellchu
        23
    bellchu  
       Apr 14, 2015
    @wizardoz 有返回的,输出多少就返回多少
    static ssize_t write_null(struct file *file, const char __user *buf,
    size_t count, loff_t *ppos)
    {
    return count;
    }
    fxxkgw
        24
    fxxkgw  
       Apr 14, 2015
    这个一般都是在脚本里面用的吧,特别是一些crontab定时器中执行的脚本,大部分作用是把无用或出错信息不显示。
    如果考虑到使用的情况,将打印显示到界面的资源消耗量应远大于输入到/dev/null 所以个人感觉可以放心使用。
    vonnyfly
        25
    vonnyfly  
       Apr 14, 2015   ❤️ 1
    这个return size一定要,不要的话,用户态write会返回失败。以前写驱动的时候这里返回值写0,导致用户态write失败。
    ElmerZhang
        26
    ElmerZhang  
       Apr 14, 2015   ❤️ 2
    write系统调用消耗的CPU很少了
    ryd994
        27
    ryd994  
       Apr 14, 2015
    @bellchu 26楼
    bellchu
        28
    bellchu  
       Apr 15, 2015
    @ryd994 这不是正好证明我的理解是正确的么。无IO或无延迟,大量system call积聚造成CPU占用率飙升。

    BTW,昨天去楼下苹果店用这些命令给新Macbook烤机,开了四个线程的yes,CPU 100%,无风扇的机器居然不是很烫。。。。有点想买了,除了他那个纠结的键盘之外。
    bellchu
        29
    bellchu  
       Apr 15, 2015
    @bellchu 再BTW,yes是纯输出的命令,而/dev/null是write only的设备。所以用yes才能演示楼主所说的大量写入的情况。

    cat /dev/zero首先是从/dev/zero读取,然后写入/dev/null。所以system call的数量是read/write各占一半。

    /dev/zero /dev/random /dev/null都是上世纪创造的东西了,现在很多人都在想怎么改良它们。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3489 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 50ms · UTC 10:39 · PVG 18:39 · LAX 03:39 · JFK 06:39
    ♥ Do have faith in what you're doing.