依JEDEC eMMC及经验辛苦整理,原创保护,禁止转载。
主页 《元存储-CSDN博客》
内容摘要
全文 15000 字, 主要内容
Linux 中 eMMC 初始化
Linux eMMC 调试工具 MMC -utils
MMC -utils 功能
MMC -utils 使用方
Linux/Android eMMC 性能测试工具
DD tes
FIO test
IOZone test
Kernal mmc_test
本篇所在内容以实用线索,对于每个Tool 也无法全部讲完。 读者不需要死记硬背,收藏一下,当成一个工具书来使用即可。
对于工具选择一个自己趁手的即可,没有最好的, 只有最合适的。如果比较简单的使用,就用 MMC -utils 和 keneral mmc_test 即可。 如果比较深入的就用 MMC -utils 和 DD test 和 FIO Test 这些, DD 上手简单, FIO 相对很专业,当然用起来会复杂些。
引子
文中以Linux 说明,因为Android 是基于 Linux 内核, 所以文中的方法同样适用于 Android.
因为SD、SDIO和 MMC 等非常相似, Linux 是怎么识别 MMC 的呢? 设备初始化时识别过程如下:
[3] MMC -utils的MMC调试工具,由Ulf Hansson维护,你可以在下面的公共git存储库中找到它:
https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git
这个开源工具是在Linux 环境使用的。Android 的核心也是 Linux, 也可以使用这个 tool. 因为eMMC 和 MMC 的区别只是一个是焊接的, 一个是插入式的。这个tool 对 eMMC 和 MMC 都适用。
先来看看有什么功能吧, 不需要记住每个功能怎么用,知道可以用它来做什么就好了。
mmc-utils工具可以做以下事情:
可以通过mmc不带参数来查看用法
Usage:
mmc extcsd read
Print extcsd data from .
mmc writeprotect get
Determine the eMMC writeprotect status of .
mmc writeprotect set
Set the eMMC writeprotect status of .
This sets the eMMC to be write-protected until next boot.
mmc disable 512B emulation
Set the eMMC data sector size to 4KB by disabling emulation on
.
mmc enh_area set <-y|-n>
Enable the enhanced user area for the .
Dry-run only unless -y is passed.
NOTE! This is a one-time programmable (unreversible) change.
mmc write_reliability set <-y|-n>
Enable write reliability per partition for the .
Dry-run only unless -y is passed.
NOTE! This is a one-time programmable (unreversible) change.
mmc status get
Print the response to STATUS_SEND (CMD13).
mmc bootpart enable
Enable the boot partition for the .
To receive acknowledgment of boot from the card set
to 1, else set it to 0.
mmc bkops enable
Enable the eMMC BKOPS feature on .
NOTE! This is a one-time programmable (unreversible) change.
mmc hwreset enable
Permanently enable the eMMC H/W Reset feature on .
NOTE! This is a one-time programmable (unreversible) change.
mmc hwreset disable
Permanently disable the eMMC H/W Reset feature on .
NOTE! This is a one-time programmable (unreversible) change.
mmc sanitize
Send Sanitize command to the .
This will delete the unmapped memory region of the device.
mmc help|--help|-h
Show the help.
mmc --help
Show detailed help for a command or subset of commands.
0.1
用法示例
mmc extcsd read /dev/mmc0
linux emmc 性能测试主要有 4 种工具:
到底哪种好呢? 仁者见仁, 看在我把 DD 放在第一个讲, 你就知道我喜欢哪个了^^
写入性能测试
我们分为两种情况来测试
写入块设备
cache 分区一般是用来存放 OTA 升级包的,正常状态下挂载失败也不影响系统的正常运行,所以我们拿 cache 分区来作写入测试,先找到 cache 对应的块设备文件
1 2 3 |
KKHi3751V810:/ #ls -l /dev/block/platform/soc/f9830000.emmc/by-name/cache < lrwxrwxrwx 1 root root 21 1970-01-01 08:00 /dev/block/platform/soc/f9830000.emmc/by-name/cache -> /dev/block/mmcblk0p18 KKHi3751V810:/ # |
cache 分区的块设备文件为 /dev/block/mmcblk0p18。
写入测试:
1 2 3 4 5 6 |
KKHi3751V810:/ # echo 1 > /proc/sys/vm/drop_caches KKHi3751V810:/ # busybox dd if=/dev/zero of=/dev/block/mmcblk0p18 bs=1M count=1024 conv=fsync 1024+0 records in 1024+0 records out 1073741824 bytes (1.0GB) copied, 24.122624 seconds, 42.4MB/s KKHi3751V810:/ # |
输入文件为 /dev/zero,是一个虚拟设备,我们可以认为这个设备的读取速度无限大,也就是读取速度不会影响到写入的速度。
bs=1M : 一次写入 1M
count=1024 : 写入 1024 次,也就是写入的数据总量为 1G
conv=fsync : dd 结束前,把数据同步到 emmc,如果没加这个参数的话,数据可能还在缓存之中。为了确保数据准确,一定要加这个参数。
重复测试几次,速度基本在 42M/s 左右。
写入文件
1 2 3 4 5 6 |
KKHi3751V810:/ # echo 1 > /proc/sys/vm/drop_caches KKHi3751V810:/ # busybox dd if=/dev/zero of=/data/ddtest.bin bs=1M count=1024 conv=fsync < 1024+0 records in 1024+0 records out 1073741824 bytes (1.0GB) copied, 30.607905 seconds, 33.5MB/s KKHi3751V810:/ # |
重复测试几次,速度基本在 33M/s 左右。相对直接写块设备文件慢了 10M/s 左右。这可能是文件系统带来的影响。
读取测试
读取块设备
直接用我们上面介绍清除缓存的例子就行,这里就不再重复了。
从上面的例子得到的数据为 203M/s 左右。
读取文件
1 2 3 4 5 6 |
KKHi3751V810:/ # echo 1 > /proc/sys/vm/drop_caches KKHi3751V810:/ # busybox dd if=/data/ddtest.bin of=/dev/null bs=1M count=1024 1024+0 records in 1024+0 records out 1073741824 bytes (1.0GB) copied, 4.915286 seconds, 208.3MB/s KKHi3751V810:/ # |
直接拿测试写入速度时生成的文件,重复测试几次,速度基本上在 208MB/s 左右。
转载自: linux emmc test - 知乎
可以得到iops,读写带宽速率等信息。
读写速度与队列深度,块大小,线程数量等有密切关系,这与ssd的工作原理有关
1.随机读(Random read)
fio -filename=/tmp/test_randread -direct=1 -iodepth 1 -thread -rw=randread -ioengine=psync -bs=16k -size=30G -numjobs=10 -runtime=600 -group_reporting -name=mytest
当10个thread时
Run status group 0 (all jobs):
READ: io=51200MB, aggrb=257806KB/s, minb=257806KB/s, maxb=257806KB/s, mint=203365msec, maxt=203365msec
当一个thread时
Run status group 0 (all jobs):
READ: io=1024.0MB, aggrb=27522KB/s, minb=27522KB/s, maxb=27522KB/s, mint=38099msec, maxt=38099msec
当2个thread时
Run status group 0 (all jobs):
READ: io=2048.0MB, aggrb=48400KB/s, minb=48400KB/s, maxb=48400KB/s, mint=43329msec, maxt=43329msec
随机写(Random write)
fio -filename=./test_randread -direct=1 -iodepth 1 -thread -rw=randwrite -ioengine=psync -bs=16k -size=1G -numjobs=10 -runtime=600 -group_reporting -name=mytest
Run status group 0 (all jobs):
WRITE: io=10240MB, aggrb=66959KB/s, minb=66959KB/s, maxb=66959KB/s, mint=156599msec, maxt=156599msec
Disk stats (read/write):
sda: ios=1/655282, merge=0/86, ticks=0/135704, in_queue=135652, util=86.80%
顺序读(Sequential read)
fio -filename=./test_randread -direct=1 -iodepth 1 -thread -rw=read -ioengine=psync -bs=16k -size=1G -numjobs=5 -runtime=600 -group_reporting -name=mytest
Run status group 0 (all jobs):
READ: io=5120.0MB, aggrb=45658KB/s, minb=45658KB/s, maxb=45658KB/s, mint=114829msec, maxt=114829msec
顺序写(Sequential write)
fio -filename=./test_randread -direct=1 -iodepth 1 -thread -rw=write -ioengine=psync -bs=16k -size=1G -numjobs=5 -runtime=600 -group_reporting -name=mytest
Run status group 0 (all jobs):
WRITE: io=2048.0MB, aggrb=15644KB/s, minb=15644KB/s, maxb=15644KB/s, mint=134053msec, maxt=134053msec
关于 fio 运行问题
在android平台上运行fio,发现fio无法正常运行,原因有两个
FIO 测试实战
写入文件速度
KKHi3751V810:/ # echo 1 > /proc/sys/vm/drop_caches
KKHi3751V810:/ # fio -filename=/dev/block/mmcblk0p18 -direct=1 -iodepth 1 -thread -rw=randwrite -ioengine=psync -bs=1m -size=1G -numjobs=4 -runtime=60 -group_reporting -name=rand_write_1m
rand_write_1m: (g=0): rw=randwrite, bs=1M-1M/1M-1M/1M-1M, ioengine=psync, iodepth=1
...
fio-2.2.6
Starting 4 threads
Jobs: 3 (f=3): [w(3),_(1)] [98.1% done] [0KB/80734KB/0KB /s] [0/78/0 iops] [eta 00m:01s]
rand_write_1m: (groupid=0, jobs=4): err= 0: pid=8316: Wed Feb 12 21:03:34 2020
write: io=4096.0MB, bw=83067KB/s, iops=81, runt= 50493msec
clat (msec): min=10, max=1361, avg=48.60, stdev=44.45
lat (msec): min=10, max=1361, avg=48.86, stdev=44.44
clat percentiles (msec):
| 1.00th=[ 18], 5.00th=[ 22], 10.00th=[ 23], 20.00th=[ 26],
| 30.00th=[ 34], 40.00th=[ 37], 50.00th=[ 46], 60.00th=[ 48],
| 70.00th=[ 58], 80.00th=[ 65], 90.00th=[ 76], 95.00th=[ 87],
| 99.00th=[ 104], 99.50th=[ 114], 99.90th=[ 758], 99.95th=[ 1123],
| 99.99th=[ 1369]
bw (KB /s): min= 1343, max=41353, per=25.49%, avg=21171.93, stdev=4637.55
lat (msec) : 20=1.51%, 50=60.52%, 100=36.40%, 250=1.37%, 500=0.02%
lat (msec) : 750=0.05%, 1000=0.05%, 2000=0.07%
cpu : usr=0.43%, sys=1.13%, ctx=10620, majf=0, minf=6
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued : total=r=0/w=4096/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
WRITE: io=4096.0MB, aggrb=83067KB/s, minb=83067KB/s, maxb=83067KB/s, mint=50493msec, maxt=50493msec
Disk stats (read/write):
mmcblk0: ios=54/8332, merge=5/888, ticks=60872/378355, in_queue=439181, util=100.00%
KKHi3751V810:/ #
4个线程的平均写入速度为 bw=83067KB/s,大概是 80M/s, 比 dd 也快了一倍多。
读取文件速度
KKHi3751V810:/ # echo 1 > /proc/sys/vm/drop_caches
KKHi3751V810:/ # fio -filename=/dev/block/mmcblk0 -direct=1 -iodepth 1 -thread -rw=randread -ioengine=psync -bs=1m -size=1G -numjobs=4 -runtime=60 -group_reporting -name=rand_read_1m
rand_read_1m: (g=0): rw=randread, bs=1M-1M/1M-1M/1M-1M, ioengine=psync, iodepth=1
...
fio-2.2.6
Starting 4 threads
Jobs: 1 (f=1): [_(3),r(1)] [96.2% done] [148.5MB/0KB/0KB /s] [148/0/0 iops] [eta 00m:01s]
rand_read_1m: (groupid=0, jobs=4): err= 0: pid=7889: Wed Feb 12 20:56:21 2020
read : io=4096.0MB, bw=171813KB/s, iops=167, runt= 24412msec
clat (msec): min=4, max=9350, avg=19.50, stdev=215.06
lat (msec): min=4, max=9350, avg=19.50, stdev=215.06
clat percentiles (msec):
| 1.00th=[ 7], 5.00th=[ 8], 10.00th=[ 8], 20.00th=[ 11],
| 30.00th=[ 11], 40.00th=[ 11], 50.00th=[ 11], 60.00th=[ 14],
| 70.00th=[ 14], 80.00th=[ 14], 90.00th=[ 14], 95.00th=[ 14],
| 99.00th=[ 16], 99.50th=[ 30], 99.90th=[ 2638], 99.95th=[ 4113],
| 99.99th=[ 9372]
bw (KB /s): min= 964, max=145420, per=46.41%, avg=79740.53, stdev=25495.41
lat (msec) : 10=13.77%, 20=85.55%, 50=0.29%, 100=0.12%, 500=0.05%
lat (msec) : 750=0.05%, 2000=0.05%, >=2000=0.12%
cpu : usr=0.22%, sys=3.16%, ctx=9195, majf=0, minf=1030
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued : total=r=4096/w=0/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
READ: io=4096.0MB, aggrb=171813KB/s, minb=171813KB/s, maxb=171813KB/s, mint=24412msec, maxt=24412msec
Disk stats (read/write):
mmcblk0: ios=8365/46, merge=15/47, ticks=633927/61332, in_queue=695214, util=99.20%
KKHi3751V810:/ #
4个线程的平均读速度为 bw=171813KB/s, 大概为 170M/s。
Android 系统源码中并没有 iozone,我们得自己人官网上下载编译,我下载时最新版本为 iozone3_489, 这个版本已经有 Android.mk 在代码里面了, 将源码放到 Android 系统源码里面 mm 即可。
随机读写测试:
KKHi3751V810:/ # echo 1 > /proc/sys/vm/drop_caches
KKHi3751V810:/ # iozone -azecI -+n -L64 -S32 -r1m -s1024m -i0 -i2 -w -f /data/iozonetest.bin
Iozone: Performance Test of File I/O
Version $Revision: 3.489 $
Compiled for 64 bit mode.
Build: linux-arm
Contributors:William Norcott, Don Capps, Isom Crawford, Kirby Collins
Al Slater, Scott Rhine, Mike Wisner, Ken Goss
Steve Landherr, Brad Smith, Mark Kelly, Dr. Alain CYR,
Randy Dunlap, Mark Montague, Dan Million, Gavin Brebner,
Jean-Marc Zucconi, Jeff Blomberg, Benny Halevy, Dave Boone,
Erik Habbinga, Kris Strecker, Walter Wong, Joshua Root,
Fabrice Bacchella, Zhenghua Xue, Qin Li, Darren Sawyer,
Vangel Bojaxhi, Ben England, Vikentsi Lapa,
Alexey Skidanov, Sudhir Kumar.
Run began: Wed Feb 12 20:47:58 2020
Auto Mode
Cross over of record size disabled.
Include fsync in write timing
Include close in write timing
O_DIRECT feature enabled
No retest option selected
Record Size 1024 kB
File size set to 1048576 kB
Setting no_unlink
Command line used: iozone -azecI -+n -L64 -S32 -r1m -s1024m -i0 -i2 -w -f /data/iozonetest.bin
Output is in kBytes/sec
Time Resolution = 0.000001 seconds.
Processor cache size set to 32 kBytes.
Processor cache line size set to 64 bytes.
File stride size set to 17 * record size.
random random bkwd record stride
kB reclen write rewrite read reread read write read rewrite read fwrite frewrite fread freread
1048576 1024 74782 0 199299 71520
iozone test complete.
KKHi3751V810:/ #
从结果来看,随机读速度为 199299 kB/s , 大概为 200M/s。 随机写速度为 71520 kB/s, 大概为 70M/s。
重复测试几次结果差不多,读的速度基本跟 dd 的一致。写入的比 dd 的快了将近一倍。
转载自: Linux kernel mmc 框架说明,包括mmc_test使用方法_运维_kivy_xian的博客-CSDN博客
使用linux kernel中自带的mmc_test.ko进行mmc的功能测试,包括速率设置,总线位宽设置,复操作,trim操作,命令和基本数据读写等特性测试。可以按照如下步骤:
1.CONFIG_MMC_BLOCK=n,CONFIG_MMC_TEST=y。或者CONFIG_MMC_BLOCK=y, CONFIG_MMC_TEST=y。如果选用后一种配置,需要再系统起来后,在总线driver中手动bind和unbind,见后面;
2.CONFIG_DEBUG_FS=y,CONFIG_DEBUG_KERNEL=y,这两项在我们项目的kernel的defconfig中已经配置,所以不需要进行改动;
3. mount -t debugfs none /sys/kernel/debug,这个我们的project中已经挂载了,不需要进行改动;
完成上面三项后,启动系统,如果在步骤1中CONFIG_MMC_BLOCK=y,那么需要先执行执行如下操作:
etau:/ # ls sys/bus/mmc/devices/
mmc0:aaaa
etau:/sys/bus/mmc/drivers # ls
mmc_test/ mmcblk/
etau:/sys/bus/mmc/drivers # cd mmcblk/
etau:/sys/bus/mmc/drivers/mmcblk # ls -al
total 0
drwxr-xr-x 2 root root 0 2000-01-01 01:27 .
drwxr-xr-x 4 root root 0 2000-01-01 01:27 ..
--w------- 1 root root 4096 2000-01-01 01:28bind
lrwxrwxrwx 1 root root 0 2000-01-01 01:28 mmc0:aaaa ->../../../../devices/soc0/20a50000.rda-mmc0/mmc_host/mmc0/mmc0:aaaa
--w------- 1 root root 4096 2000-01-01 01:28uevent
--w------- 1 root root 4096 2000-01-01 01:28unbind
etau:/sys/bus/mmc/drivers/mmcblk #echo –n mmc0:aaaa> unbind
etau:/sys/bus/mmc/drivers # cdmmc_test/
etau:/sys/bus/mmc/drivers/mmc_test # ls
bind uevent unbind
etau:/sys/bus/mmc/drivers/mmc_test #echo –n mmc0:aaaa> bind
完成上述操作后,完成了mmc0:aaaa和mmc_test driver的绑定。后续步骤完全一致,如下:
etau:/sys/kernel/debug/mmc0/mmc0:aaaa# cat testlist
1: Basic write (no data verification)
2: Basic read (no data verification)
3: Basic write (with data verification)
4: Basic read (with data verification)
5: Multi-block write
6: Multi-block read
7: Power of two block writes
8: Power of two block reads
9: Weird sized block writes
10: Weird sized block reads
11: Badly aligned write
12: Badly aligned read
13: Badly aligned multi-block write
14: Badly aligned multi-block read
15: Correct xfer_size at write (start failure)
16: Correct xfer_size at read (start failure)
17: Correct xfer_size at write (midway failure)
18: Correct xfer_size at read (midway failure)
19: Highmem write
20: Highmem read
21: Multi-block highmem write
22: Multi-block highmem read
23: Best-case read performance
24: Best-case write performance
25: Best-case read performance into scattered pages
26: Best-case write performance from scatteredpages
27: Single read performance by transfer size
28: Single write performance by transfer size
29: Single trim performance by transfer size
30: Consecutive read performance by transfer size
31: Consecutive write performance by transfer size
32: Consecutive trim performance by transfer size
33: Random read performance by transfer size
34: Random write performance by transfer size
35: Large sequential read into scattered pages
36: Large sequential write from scattered pages
37: Write performance with blocking req 4k to 4MB
38: Write performance with non-blocking req 4k to 4MB
39: Read performance with blocking req 4k to 4MB
40: Read performance with non-blocking req 4k to 4MB
41: Write performance blocking req 1 to 512 sg elems
42: Write performance non-blocking req 1 to 512 sg elems
43: Read performance blocking req 1 to 512 sg elems
44: Read performance non-blocking req 1 to 512 sg elems
45: Reset test
然后执行etau:/sys/kernel/debug/mmc0/mmc0:aaaa# echo 1 > test可以看到测试结果:
[314034.644348] mmc0: Starting tests of cardmmc0:aaaa...
[314034.645080] mmc0: Test case 1. Basicwrite (no data verification)...
[314034.647583] mmc0: Result: OK
[314034.647827] mmc0: Tests completed.
[1] Linux kernel mmc 框架说明,包括mmc_test使用方法_运维_kivy_xian的博客-CSDN博客
[2] linux emmc test - 知乎
[3] MMC tools introduction — The Linux Kernel documentation
免责声明:
本文根据公开信息整理,旨在介绍更多的存储知识,所载文章仅为作者观点,不构成投资或商用建议。本文仅用于学习交流, 不允许商用。若有疑问或有侵权行为请联系作者处理。