测试工具sgp_dd分析
2012-05-15 17:28
239 查看
测试工具sgp_dd是sg3_utils包中的一个测试裸盘读写速度的工具,它利用多线程以将磁盘分区域并行读写的方式来测试
分析目的集中于信号处理方式、多线程以及SCSI命令简介
l sg_lib.h:SG通用库头文件;
l sg_cmds_basic.h:SG基本命令头文件;
l sg_io_linux: SG在linux平台上的io处理函数头文件;
一些关于默认块大小、默认每次传输块数、SCSI命令描述块大小(CDB:command descriptor block)、设备类型的宏定义:
通过stat()函数获得设备文件名代表的文件属性信息st,可通过查看st. st_mode判断是字符设备还是块设备,st. st_rdev的主次设备号,判断具体是哪种设备。相关函数和宏有:S_ISCHR()、S_ISBLK()、major()和minor等。
[root@oss5 ~]# sgp_dd --help | grep dpo
Usage: sgp_dd [bs=BS] [count=COUNT] [ibs=BS] [if=IFILE][iflag=FLAGS]
[obs=BS] [of=OFILE][oflag=FLAGS] [seek=SEEK] [skip=SKIP]
[--help] [--version]
[bpt=BPT] [cdbsz=6|10|12|16][coe=0|1] [deb=VERB] [dio=0|1]
[fua=0|1|2|3] [sync=0|1][thr=THR] [time=0|1] [verbose=VERB]
where:
bpt is blocks_per_transfer(default is 128)
bs must be device blocksize (default 512)
cdbsz size of SCSI READ orWRITE cdb (default is 10)
coe continue on error,0->exit (def), 1->zero + continue
count number of blocks tocopy (def: device size)
deb for debug, 0->none(def), > 0->varying degrees of debug
dio is direct IO,1->attempt, 0->indirect IO (def)
fua force unit access:0->don't(def), 1->OFILE, 2->IFILE,
3->OFILE+IFILE
if file or device to readfrom (def: stdin)
iflag comma separated listfrom: [coe,dio,direct,dpo,dsync,excl,
fua, null]
of file or device towrite to (def: stdout), OFILE of '.'
treated as /dev/null
oflag comma separated listfrom: [append,coe,dio,direct,dpo,dsync,
excl,fua,null]
sync 0->no sync(def), 1->SYNCHRONIZECACHE on OFILE after copy
thr is number of threads,must be > 0, default 4, max 16
time 0->no timing(def),1->time plus calculate throughput
verbose same as 'deb=VERB':increase verbosity
--help output this usagemessage then exit
--version output version stringthen exit
Copy from IFILE to OFILE, similar to ddcommand
specialized for SCSI devices, uses multiplePOSIX threads
读命令:
Disable Page Out (DPO) allows the initiator to warn the target that
the data being read isunlikely to be requested again soon and so is not worth keeping in the target'sdata cache. Force Unit Access (FUA) tells the target to fetch the data from themedia surface and to not use a cached copy
写命令:
Disable Page Out (DPO) allows the initiator to warn the target that
the data being writtenis unlikely to be read back soon and so is not worth keeping in the target'sdata cache. Force Unit Access (FUA) tells the target to immediately send thedata to the media surface and to not buffer it through a cache. The EBP bittells the
target that it may skip the erase process when writing data. TheRelAdr bit is used to indicate that the LBA value is relative (only used with linkedcommands)
结构体struct request_collection被typedef为Rq_coll,记录了一个sgp_dd命令总共要传输的数据:
该结构体实例对所有的线程都可见。
结构体struct request_element,被typedef为Rq_elem,每个实例仅被一个work thread看到,是一个work thread要传输的全部数据
看来,struct request_collect是总传输数据量的结构体,而struct request_element是其中的一个个分量,要传输的数据块选择bpt和请求要传输的数据总量(剩余量)中的小值。如下所示:
结构体struct sg_io_hdr
"[i]" 代表函数需要的输入值
"[o]" 函数执行完成后写入的值
"[i->o]" indicates a value that is conveyed from inputto output and apart from one special case,
is not used by the driver. The "[i->o]" members aremeant to aid an application matching
the request sent to a write() to the corresponding response receivedby a read().
"[*i]" indicates a pointer that is used for reading fromuser memory into the driver,仅用于指针
"[*o]" is a pointer used for writing,函数执行结果写入
"[*io]" indicates a pointer used for either reading orwriting.
成员dxfer_direction有以下取值:
· SG_DXFER_NONE:不需要传输数据。比如SCSI Test Unit Ready 命令。
· SG_DXFER_TO_DEV:将数据传输到设备。使用SCSI WRITE 命令。
· SG_DXFER_FROM_DEV:从设备输出数据。使用SCSI READ 命令。
· SG_DXFER_TO_FROM_DEV:双向传输数据。
· SG_DXFER_UNKNOWN:数据的传输方向未知。
6.1. interface_id
6.2. dxfer_direction
6.3. cmd_len
6.4. mx_sb_len
6.5. iovec_count
6.6. dxfer_len
6.7. dxferp
6.8. cmdp
6.9. sbp
6.10. timeout
6.11. flags
6.12. pack_id
6.13. usr_ptr
6.14. status
6.15. masked_status
6.16. msg_status
6.17. sb_len_wr
6.18. host_status
6.19. driver_status
6.20. resid
6.21. duration
6.22. info
分析目的集中于信号处理方式、多线程以及SCSI命令简介
包含文件及宏定义
除了包含linux中的库文件之外,在sgp_dd.c中还包含了3个头文件,跟sg有关:l sg_lib.h:SG通用库头文件;
l sg_cmds_basic.h:SG基本命令头文件;
l sg_io_linux: SG在linux平台上的io处理函数头文件;
一些关于默认块大小、默认每次传输块数、SCSI命令描述块大小(CDB:command descriptor block)、设备类型的宏定义:
#define FT_OTHER 1 /* filetype other than one of the following */ #define FT_SG 2 /* filetype is sg char device */ #define FT_RAW 4 /* filetype is raw char device */ #define FT_DEV_NULL 8 /* either "/dev/null" or "." as filename */ #define FT_ST 16 /* filetype is st char device (tape) */ #define FT_BLOCK 32 /* filetype is a block device */ #define FT_ERROR 64 /* couldn't "stat" file */ |
几个结构体
结构体struct flags_t,各种标记组合的结构体类型 | 域 | 描述 |
int | append | 用于设置打开标记O_APPEND |
int | coe | continue on error, 0->exit (def), 1->zero + continue 出错时时根据这个值决定如何处理 |
int | dio | is direct IO, 1->attempt, 0->indirect IO (def),用于设置struct sg_io_hdr的flags |= SG_FLAG_DIRECT_IO |
int | direct | |
int | dpo | 用于设置CDB |
int | dsync | 用于设置open标记O_SYNC |
int | excl | 用于设置open标记O_EXCL |
int | fua | force unit access: 0->don't(def), 1->OFILE, 2->IFILE, 3->OFILE+IFILE 用于设置CDB |
Usage: sgp_dd [bs=BS] [count=COUNT] [ibs=BS] [if=IFILE][iflag=FLAGS]
[obs=BS] [of=OFILE][oflag=FLAGS] [seek=SEEK] [skip=SKIP]
[--help] [--version]
[bpt=BPT] [cdbsz=6|10|12|16][coe=0|1] [deb=VERB] [dio=0|1]
[fua=0|1|2|3] [sync=0|1][thr=THR] [time=0|1] [verbose=VERB]
where:
bpt is blocks_per_transfer(default is 128)
bs must be device blocksize (default 512)
cdbsz size of SCSI READ orWRITE cdb (default is 10)
coe continue on error,0->exit (def), 1->zero + continue
count number of blocks tocopy (def: device size)
deb for debug, 0->none(def), > 0->varying degrees of debug
dio is direct IO,1->attempt, 0->indirect IO (def)
fua force unit access:0->don't(def), 1->OFILE, 2->IFILE,
3->OFILE+IFILE
if file or device to readfrom (def: stdin)
iflag comma separated listfrom: [coe,dio,direct,dpo,dsync,excl,
fua, null]
of file or device towrite to (def: stdout), OFILE of '.'
treated as /dev/null
oflag comma separated listfrom: [append,coe,dio,direct,dpo,dsync,
excl,fua,null]
sync 0->no sync(def), 1->SYNCHRONIZECACHE on OFILE after copy
thr is number of threads,must be > 0, default 4, max 16
time 0->no timing(def),1->time plus calculate throughput
verbose same as 'deb=VERB':increase verbosity
--help output this usagemessage then exit
--version output version stringthen exit
Copy from IFILE to OFILE, similar to ddcommand
specialized for SCSI devices, uses multiplePOSIX threads
读命令:
Disable Page Out (DPO) allows the initiator to warn the target that
the data being read isunlikely to be requested again soon and so is not worth keeping in the target'sdata cache. Force Unit Access (FUA) tells the target to fetch the data from themedia surface and to not use a cached copy
写命令:
Disable Page Out (DPO) allows the initiator to warn the target that
the data being writtenis unlikely to be read back soon and so is not worth keeping in the target'sdata cache. Force Unit Access (FUA) tells the target to immediately send thedata to the media surface and to not buffer it through a cache. The EBP bittells the
target that it may skip the erase process when writing data. TheRelAdr bit is used to indicate that the LBA value is relative (only used with linkedcommands)
结构体struct request_collection被typedef为Rq_coll,记录了一个sgp_dd命令总共要传输的数据:
类型 | 域 | 描述 |
int | infd | 读取数据的文件句柄,即输入设备 |
int64_t | skip | 从读取数据的文件开头跳过多少个块数据 |
int | in_type | 输入设备类型,FT_* |
int | cdbsz_in | 读取数据的CDB大小,默认是10 |
struct flags_t | in_flags | 标记集合 |
int64_t | in_blk | 下一个要读取的块的地址 |
int64_t | in_count | 初始化为dd_count(要读取的数据块总数),该成员代表要读取的总块数剩余值,每个线程读完成后都会减去实际读取的块数,每个线程每次读时看到的都不同 |
int64_t | in_rem_count | 残余读取块数,每次线程读取时,有可能无法读取指定的块数,in_rem_count初始化为in_count,每次一个线程完成一个读取操作,就把in_rem_count减去实际读取的blocks,最后命令结束时,用指定要传输的数据总数dd_count减去in_rem_count得到实际读取的数据总数 |
int | in_partial | 实际读取的数据大小非整数个块大小的个数 |
int | in_stop | 读取结束标记 |
pthread_mutex_t | in_mutex | 读取互斥锁 |
输出: | ||
int | outfd | 输出文件句柄 |
int64_t | seek | 输出首地址跳过的块数 |
int | out_type | 输出设备类型,FT_* |
int | cdbsz_out | 输出CDB大小,默认为10 |
struct flags_t | out_flags | 输出标记组合 |
int64_t | out_blk | 下一次要写入的块位置 |
int64_t | out_count | 初始化为dd_count,每一次线程写,都会减去该线程读取出而要写入的块数,每个线程看到的下一次输出要输出的总块数不同。 |
int64_t | out_rem_count | 初始化为dd_count,每一次线程写,都会减去该线程实际写入的块数,而不是读取出而要写入的块数。 |
int | out_partial | 实际输出的数据大小非整数个块大小的个数 |
int | out_stop | 输出结束标记 |
pthread_mutex_t | out_mutex | 输出互斥量 |
pthread_cond_t | out_sync_cv | hold writes until "in order" |
int | bs | 块大小 |
int | bpt | 每次传输多少块 |
int | dio_incomplete | 全部传输中使用dio方式的计数 |
int | sum_of_resids | Sg函数使用,总共残余的未输出的数据计数 |
pthread_mutex_t | aux_mutex | 主要是保护dio_incomplete和sum_of_resids成员 |
int | debug | 调试相关 |
结构体struct request_element,被typedef为Rq_elem,每个实例仅被一个work thread看到,是一个work thread要传输的全部数据
类型 | 域 | 描述 |
int | infd | 读取文件描述符 |
int | outfd | 输出文件描述符 |
int | wr | 指定in/out,1:out,0:in |
int64_t | blk | 下一个要读取/输出的块地址 |
int | num_blks | 块数 |
unsigned char * | buffp | 缓存开头,读取的数据放在这,要写的数据也放在这 |
unsigned char * | alloc_bp | 分配了一个缓冲空间,有缓存+1个页大小,上面的buffp指向1页之后的缓存开头 |
struct sg_io_hdr | io_hdr | Sg相关 |
unsigned char | cmd[MAX_SCSI_CDBSZ] | SCSI命令CDB |
unsigned char | sb[SENSE_BUFF_LEN] | Sg命令执行后的状态信息,从struct sg_io_hdr->sbp指向该缓冲区 |
int | bs | 块大小 |
int | dio_incomplete | DIO方式则=1,否则=0。DIO的设计方式是:如果用direct io且完成,则sg_io_hdr_t ->info成员的SG_INFO_DIRECT_IO位被设置,否则会以indirect io完成 |
int | resid | 这次线程传输中的残余数据数目,sg_函数中有用 |
int | cdbsz_in | 读取CDB大小 |
int | cdbsz_out | 输出CDB大小 |
struct flags_t | in_flags | 读取标记组合 |
struct flags_t | out_flags | 输出标记组合 |
int | debug |
/* Follow clp members are constant during lifetime of thread */ rep->bs = clp->bs; rep->infd = clp->infd; rep->outfd = clp->outfd; rep->debug = clp->debug; rep->cdbsz_in = clp->cdbsz_in; rep->cdbsz_out = clp->cdbsz_out; rep->in_flags = clp->in_flags; rep->out_flags = clp->out_flags; while(1) { status = pthread_mutex_lock(&clp->in_mutex); if (0 != status) err_exit(status, "lock in_mutex"); if (clp->in_stop || (clp->in_count <= 0)) { /* no more to do, exit loop then thread */ status = pthread_mutex_unlock(&clp->in_mutex); if (0 != status) err_exit(status, "unlock in_mutex"); break; } /*按最小者来*/ blocks = (clp->in_count > clp->bpt) ? clp->bpt : clp->in_count; rep->wr = 0; rep->blk = clp->in_blk; rep->num_blks = blocks; clp->in_blk += blocks; clp->in_count -= blocks; …………………………….. } |
类型 | 域 | 描述 |
int | interface_id | [i] 'S' (required) |
int | dxfer_direction | [i]数据传输方向 |
unsigned char | cmd_len | [i],CDB命令长度 |
unsigned char | mx_sb_len | [i],sence检测缓冲区最大长度,其中的实际数据长度为sb_len_wr |
unsigned short | iovec_count | [i],用于scatter方式 |
unsigned int | dxfer_len | [i],实际传输数据的长度 |
void * | dxferp | [i], [*io]输入/输出数据缓冲区 |
unsigned char * | cmdp | [i], [*i]CDB命令 |
unsigned char * | sbp | [i], [*o]sense缓冲区 |
unsigned int | timeout | [i] unit: millisecs |
unsigned int flags | flags | [i] |
int | pack_id | [i->o]用户标记请求,在命令队列时有效识别那个请求产生的输出结果,驱动用不着 |
void * | usr_ptr | [i->o],用户私有数据,驱动用不着 |
unsigned char | status | [o] |
unsigned char | masked_status | [o],去掉status中厂商信息并进行部分操作后的结果,与<scsi/scsi.h> (e.g. CHECK_CONDITION)可以匹配 |
unsigned char | msg_status | [o]消息层状态 |
unsigned char | sb_len_wr | [o],实际的sense缓冲数据长度 |
unsigned short | host_status | [o]来自主机适配器的状态 |
unsigned short | driver_status | [o]驱动状态 |
int | resid | [o]这次传输中的残余数据数目 |
unsigned int | duration | [o] |
unsigned int | info | [o] |
"[o]" 函数执行完成后写入的值
"[i->o]" indicates a value that is conveyed from inputto output and apart from one special case,
is not used by the driver. The "[i->o]" members aremeant to aid an application matching
the request sent to a write() to the corresponding response receivedby a read().
"[*i]" indicates a pointer that is used for reading fromuser memory into the driver,仅用于指针
"[*o]" is a pointer used for writing,函数执行结果写入
"[*io]" indicates a pointer used for either reading orwriting.
成员dxfer_direction有以下取值:
· SG_DXFER_NONE:不需要传输数据。比如SCSI Test Unit Ready 命令。
· SG_DXFER_TO_DEV:将数据传输到设备。使用SCSI WRITE 命令。
· SG_DXFER_FROM_DEV:从设备输出数据。使用SCSI READ 命令。
· SG_DXFER_TO_FROM_DEV:双向传输数据。
· SG_DXFER_UNKNOWN:数据的传输方向未知。
6.1. interface_id
6.2. dxfer_direction
6.3. cmd_len
6.4. mx_sb_len
6.5. iovec_count
6.6. dxfer_len
6.7. dxferp
6.8. cmdp
6.9. sbp
6.10. timeout
6.11. flags
6.12. pack_id
6.13. usr_ptr
6.14. status
6.15. masked_status
6.16. msg_status
6.17. sb_len_wr
6.18. host_status
6.19. driver_status
6.20. resid
6.21. duration
6.22. info
相关文章推荐
- 常用Java性能测试工具的分析与对比
- web性能测试分析-工具篇
- 自动测试和分析工具
- .NET程序内存分析工具CLRProfiler的使用(性能测试)
- [软件测试]网站压测工具Webbench源码分析
- 压力测试以及性能分析工具
- Android应用测试工具ThreadingTest查错实例分析
- 常用Java性能测试工具的分析与对比
- 测试工具LoadRunner和OpenSTA比较分析
- Android CPU Memory 资源测试和分析 (使用工具 0xbench + python + vmstat)
- 测试并优化基于软件的网络分析工具
- 常用软件测试工具的分析与比较
- WebPagetest网页前端性能测试工具和实现分析
- 【iOS测试系列】instruments工具的使用(一)- 通过leaks分析内存泄露
- [java]性能测试分析工具EclipseProfiler
- 性能测试分析工具-linux top命令详解
- OpenStack性能测试工具Rally实践和分析
- 转:智能模糊测试工具 Winafl 的使用与分析
- Linux性能测试工具-UnixBench--安装以及结果分析
- 使用dd工具对磁盘RAID5和10进行I/O性能测试