fio是如何运行的?
本文主要介绍fio是如何运行的,并且以单线程、单job为例
fio的入口在fio.c中的main函数,下面列出了main函数,此处只出示了一些调用的关键函数
int main(int argc, char *argv[], char *envp[])
{
parse_options(argc, argv);
fio_backend();
}
在main函数中主要调用了两个关键函数,parse_options,顾名思义,就是分析options,也就是fio的参数,而fio_backend()函数则是fio进程的入口
fio_backend()函数在backend.c文件中
int fio_backend(void)
{
......
run_threads();
......
}
在fio_backend()函数中,初始化一些数据结构之后,调用了run_threads()(backend.c)函数,该函数是fio用来创建譬如I/O, verify线程等。
/*
* Main function for kicking off and reaping jobs, as needed.
*/
static void run_threads(void)
{
......
todo = thread_number;
......
while (todo) {
if (td->o.use_thread) {
......
ret = pthread_create(&td->thread, NULL,thread_main, td);
ret = pthread_detach(td->thread);
......
}
......
}
在这个函数中,创建了thread_main线程(backend.c),这个线程功能是,生成I/O,发送并完成I/O,记录数据等。
/*
* Entry point for the thread based jobs. The process based jobs end up
* here as well, after a little setup.
*/
static void *thread_main(void *data)
{
........
/*
* May alter parameters that init_io_u() will use, so we need to
* do this first.
* 下面两个函数的主要功能是生成读写的参数,offset,len
*/
if (init_iolog(td))
goto err; if (init_io_u(td))
goto err;
......
while (keep_running(td)) {
do_io(td);
do_verify(td, verify_bytes);//如果需要verification的话
}
}
如果不考虑verify的话,下面主要看do_io(backend.c)函数。
/*
* Main IO worker function. It retrieves io_u's to process and queues
* and reaps them, checking for rate and errors along the way.
*
* Returns number of bytes written and trimmed.
*/
static uint64_t do_io(struct thread_data *td)
{
......
//下面是do_io的主循环,判断条件是,io_log里有生成的pos信息,而且已经iuuse的数据小于总数据,
while ((td->o.read_iolog_file && !flist_empty(&td->io_log_list)) ||
(!flist_empty(&td->trim_list)) || !io_bytes_exceeded(td) ||
td->o.time_based) {
......
io_u = get_io_u(td);// io_u,是一个io unit,是根据参数生成的io unit
......
ret = td_io_queue(td, io_u); //将io_u提交到队列中
switch (ret) {
case FIO_Q_COMPLETED: //处理错误,以及同步的操作
......
case FIO_Q_QUEUED://成功入队
bytes_issued += io_u->xfer_buflen;
case FIO_Q_BUSY: //队伍满了,重新入队
.......
/*
* See if we need to complete some commands. Note that we
* can get BUSY even without IO queued, if the system is
* resource starved.
*/
full = queue_full(td) || (ret == FIO_Q_BUSY && td->cur_depth);
if (full || !td->o.iodepth_batch_complete) {
min_evts = min(td->o.iodepth_batch_complete,td->cur_depth);
/*
* if the queue is full, we MUST reap at least 1 event
*/
if (full && !min_evts)
min_evts = ;
do {
ret = io_u_queued_complete(td, min_evts, bytes_done);
} while (full && (td->cur_depth > td->o.iodepth_low));
}
}
上面do_io函数的关键入队函数td_io_queue(ioengines.c)
int td_io_queue(struct thread_data *td, struct io_u *io_u)
{
......
ret = td->io_ops->queue(td, io_u);
......
else if (ret == FIO_Q_QUEUED) {
int r;
if (ddir_rw(io_u->ddir)) {
td->io_u_queued++;
td->ts.total_io_u[io_u->ddir]++;
}
if (td->io_u_queued >= td->o.iodepth_batch) {
r = td_io_commit(td);
if (r < )
return r;
}
}
}
int td_io_commit(struct thread_data *td)
{
......
int ret;
if (td->io_ops->commit) {
ret = td->io_ops->commit(td);
}
......
return ;
}
对于td->iops,它是在各个engines中定义了,以libaio(/engines/libaio.c)为例,调用的函数就是相应engines里对应的函数
static struct ioengine_ops ioengine = {
.name = "libaio",
.version = FIO_IOOPS_VERSION,
.init = fio_libaio_init,
.prep = fio_libaio_prep,
.queue = fio_libaio_queue,
.commit = fio_libaio_commit,
.cancel = fio_libaio_cancel,
.getevents = fio_libaio_getevents,
.event = fio_libaio_event,
.cleanup = fio_libaio_cleanup,
.open_file = generic_open_file,
.close_file = generic_close_file,
.get_file_size = generic_get_file_size,
.options = options,
.option_struct_size = sizeof(struct libaio_options),
};
对于reap流程里的io_u_queued_complete(io_u.c)函数
/*
* Called to complete min_events number of io for the async engines.
*/
int io_u_queued_complete(struct thread_data *td, int min_evts,
uint64_t *bytes)
{
...... ret = td_io_getevents(td, min_evts, td->o.iodepth_batch_complete, tvp);
......
} int td_io_getevents(struct thread_data *td, unsigned int min, unsigned int max,
struct timespec *t)
{
int r = ; if (min > && td->io_ops->commit) {
r = td->io_ops->commit(td);
if (r < )
goto out;
}
if (max > td->cur_depth)
max = td->cur_depth;
if (min > max)
max = min; r = ;
if (max && td->io_ops->getevents)
r = td->io_ops->getevents(td, min, max, t);
out:
......
return r;
}
这里调用的getevents也是各个engines里定义的函数
fio是如何运行的?的更多相关文章
- ceph--磁盘和rbd、rados性能测试工具和方法
我在物理机上创建了5台虚拟机,搭建了一个ceph集群,结构如图: 具体的安装步骤参考文档:http://docs.ceph.org.cn/start/ http://www.centoscn.com/ ...
- ceph 性能测试
我在物理机上创建了5台虚拟机,搭建了一个ceph集群,结构如图: 具体的安装步骤参考文档:http://docs.ceph.org.cn/start/ http://www.centoscn.com/ ...
- 理解Docker(3):Docker 使用 Linux namespace 隔离容器的运行环境
本系列文章将介绍Docker的有关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...
- fio 2种画图方法 fio_generate_plots 和 gfio
fio 安装fio apt-get install fio 可以把fio的输出数据自动画图的插件gnuplot apt-get install gnuplot 1.输出bw,lat和iops数据并画图 ...
- FIO 测试磁盘iops 以及读写
最近在做mariadb的性能,感觉io 有瓶颈,就使用fio 来测试一下磁盘.下文为转载文章(温馨提示:此命令很伤硬盘,测试前请备份数据,- -我就写坏了一个.) FIO 是测试IOPS的非常好的工具 ...
- linux使用FIO测试磁盘的iops
FIO是测试IOPS的非常好的工具,用来对硬件进行压力测试和验证,支持13种不同的I/O引擎,包括:sync,mmap, libaio, posixaio, SG v3, splice, null, ...
- 文件操作ofstream,open,close,ifstream,fin,依照行来读取数据, fstream,iosin iosout,fio.seekg(),文件写入和文件读写,文件拷贝和文件
1.ofstream,open,close 写入文件 #include<iostream> #include<fstream> using namespace std; ...
- 【转】FIO使用指南
原文地址:http://blog.csdn.net/yuesichiu/article/details/8722417 Fio压测工具和io队列深度理解和误区 这个文档是对fio-2.0.9 HOWT ...
- linux 磁盘IO测试工具:FIO (同时简要介绍dd工具测试)
FIO是测试IOPS的非常好的工具,用来对硬件进行压力测试和验证.磁盘IO是检查磁盘性能的重要指标,可以按照负载情况分成照顺序读写,随机读写两大类. 目前主流的第三方IO测试工具有fio.iomete ...
随机推荐
- css3动画运用
https://daneden.github.io/animate.css/ https://minimamente.com/example/magic_animations/ http://i ...
- Asp.net MVC 移除不用的视图引擎
Asp.net MVC 默认提供两个视图引擎,分别为: WebFormViewEngine 和 RazorViewEngine.MVC在查找视图时,会按照指定的顺序进行查找.当我们的MVC程序未找到相 ...
- Android批量打包提速 - 1分钟900个市场不是梦
版权声明: 欢迎转载,但请保留文章原始出处 作者:GavinCT 出处:http://www.cnblogs.com/ct2011/p/4152323.html 黎明前的黑暗 使用Ant或者Gradl ...
- Spring常用注解简单汇总
使用注解之前要开启自动扫描功能,其中base-package为需要扫描的包(含子包). <context:component-scan base-package="cn.test&qu ...
- Oracle EBS 报表日期格式问题
1.确保参数日期值集选择:FND_STANDARD_DATE 2.将程序的入口参数选择为 varchar2类型 3.注意输出和游标时参数的截断 to_date(substr(p_DATE_from, ...
- 如何让chrome浏览器自动翻译
我用的chrome浏览器,最初用的时候浏览器默认自动翻译英文,我感觉很麻烦.所以我选择了一律不翻译.但是我当我想翻译的的时候又不知道怎么操作.一直郁闷到现在.今天我突然发现了一个方法可以让你的浏览器自 ...
- Elasticsearch部分节点不能发现集群(脑裂)问题处理
**现象描述** es1,es2,es3三台es组成一个集群,集群状态正常, 当es1 服务器重启后,es1不能加到集群中,自己选举自己为master,这就产生了es集群中所谓的“脑裂” , 把es1 ...
- 18年10月31日 NOIP模拟赛
T1.exercise 题解 数据很小直接模拟 代码 #include<iostream> #include<cstdio> #include<cmath> #in ...
- IDEA 使用技巧 Update
IDEA使用起来和Eclipse很大区别. 1.快捷键. 因为一个个熟悉起来费时间,就直接在Preferences—keymap里选择了Eclipse OS X,这样快捷键就转换到了Mac下Eclip ...
- SGU---101 无向图的欧拉回路
题目链接: https://cn.vjudge.net/problem/SGU-101 题目大意: 给定你n张骨牌,每张牌左右两端有一个数字,每张牌的左右两端数字可以颠倒,找出一种摆放骨牌的顺序,使得 ...