linux大量写数据到存储设备write线程偶尔出现卡顿的原因

版权声明:本文为博主原创文章,未经允许,不得转载。 https://blog.csdn.net/weixin_41944449/article/details/80616594

    之前有个项目,是做行车记录仪的,大家都知道,行车记录仪有多路视频数据需要保存到TF卡类的存储介质,但是芯片的IO速度却是有限的,尝试过将写卡线程的优先级提高,但是最后也还是发现,并没有什么改善,最终发现是,在调用驱动中的write函数之后,数据并没有在底层驱动缓冲区满之后回写存储介质。是什么原因导致没有会写的呢?这个需要了解linux的回写机制了,这个也是我们下面介绍的,分别是dirty_background_bytes、dirty_background_ratio、dirty_bytes以及dirty_ratio,它们共同决定Linux页的回写机制。

    先来看看Linux中对dirty_background_bytes、dirty_background_ratio、dirty_bytes以及dirty_ratio的说明定义:

==============================================================

dirty_background_bytes

Contains the amount of dirty memory at which the background kernel
flusher threads will start writeback.

Note: dirty_background_bytes is the counterpart of dirty_background_ratio. Only
one of them may be specified at a time. When one sysctl is written it is
immediately taken into account to evaluate the dirty memory limits and the
other appears as 0 when read.

==============================================================

dirty_background_ratio

Contains, as a percentage of total available memory that contains free pages
and reclaimable pages, the number of pages at which the background kernel
flusher threads will start writing out dirty data.

The total available memory is not equal to total system memory.

==============================================================

dirty_bytes

Contains the amount of dirty memory at which a process generating disk writes
will itself start writeback.

Note: dirty_bytes is the counterpart of dirty_ratio. Only one of them may be
specified at a time. When one sysctl is written it is immediately taken into
account to evaluate the dirty memory limits and the other appears as 0 when
read.

Note: the minimum value allowed for dirty_bytes is two pages (in bytes); any
value lower than this limit will be ignored and the old configuration will be
retained.

==============================================================

dirty_ratio

Contains, as a percentage of total available memory that contains free pages
and reclaimable pages, the number of pages at which a process which is
generating disk writes will itself start writing out dirty data.

The total available memory is not equal to total system memory.

==============================================================

    简单的跟大家说一下他们几个参数作用:

dirty_background_bytes:当系统的脏页缓冲内存达到该参数所指示的大小,内核后台刷新线程将会开始回写脏页内存,将脏页数据异步的刷入外存;

dirty_background_ratio:当系统脏页内存占用可用内存的百分比达到该值,内核后台刷新线程将会开始回写脏页内存,将脏页数据异步的刷入外存;

dirty_bytes:当系统的脏页缓冲大小达到了该参数的大小,写线程自身将会停止下一步操作而将脏页内存同步的刷入外存;

dirty_ratio:当系统脏页内存占用可用内存的百分比达到该值,写线程自身将会停止下一步操作而将脏页内存同步的刷入外存;

   需要注意的是,dirty_background_bytes和dirty_background_ratio同时只会有一个参数有效,比如,当你设置了dirty_background_ratio,那么dirty_background_bytes将会为0,而系统将按照dirty_background_ratio的大小进行相应操作,同样的,dirty_bytes和dirty_ratio也是同时只有一个参数有效。

    而dirty_background_bytes和dirty_bytes两者又有什么不同呢?简单来说,一个是异步,一个是同步吧。当脏页缓冲大小达到dirty_background_bytes限定的的大小之后,内核后台刷新线程将会开启将脏页内存回写外存,如果脏页大小增加很快,后台刷新线程没有及时的将脏页回写外存,系统脏页大小达到了dirty_bytes所限定的大小,那么此时调用write的写线程将会停止当前的操作而转去进行将脏页回写外存的操作。

    所以说到这里,不知道大家知道标题所说的,大量的写数据到外存时,为什么写线程偶尔出现卡顿的现象。应用层在大量的写数据到外存,脏页数量在快速增长,当达到dirty_background_bytes限制的大小之后,内核后台刷新线程开始将脏页数据回写外存,但脏页增长速度比后台刷新速度要快,所以会触碰到dirty_bytes限制的大小,此时不但内核的后台刷新线程会将脏页回写外存,应用层的write线程也将会将脏页回写外存,从而在用户层看,write线程出现卡顿。

    解决办法:估算用户层write线程的数据量以及内核后台刷新线程的回写速度,两者做一个均衡,设置dirty_background_bytes的值,在脏页数量达到一定大小的时候,启动后台刷新线程,同时在这个期间用户层的write线程写入的数据量不足以触发dirty_bytes的大小限制,这样,可以在减少IO交互的情况下又不会导致用户层的write线程卡顿。同理,通过设置dirty_background_ratio和dirty_ratio也可以达到类似的效果。

转载请注明出处!

猜你喜欢

转载自blog.csdn.net/weixin_41944449/article/details/80616594
今日推荐