本文主要介绍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是如何运行的?的更多相关文章

  1. ceph--磁盘和rbd、rados性能测试工具和方法

    我在物理机上创建了5台虚拟机,搭建了一个ceph集群,结构如图: 具体的安装步骤参考文档:http://docs.ceph.org.cn/start/ http://www.centoscn.com/ ...

  2. ceph 性能测试

    我在物理机上创建了5台虚拟机,搭建了一个ceph集群,结构如图: 具体的安装步骤参考文档:http://docs.ceph.org.cn/start/ http://www.centoscn.com/ ...

  3. 理解Docker(3):Docker 使用 Linux namespace 隔离容器的运行环境

    本系列文章将介绍Docker的有关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...

  4. fio 2种画图方法 fio_generate_plots 和 gfio

    fio 安装fio apt-get install fio 可以把fio的输出数据自动画图的插件gnuplot apt-get install gnuplot 1.输出bw,lat和iops数据并画图 ...

  5. FIO 测试磁盘iops 以及读写

    最近在做mariadb的性能,感觉io 有瓶颈,就使用fio 来测试一下磁盘.下文为转载文章(温馨提示:此命令很伤硬盘,测试前请备份数据,- -我就写坏了一个.) FIO 是测试IOPS的非常好的工具 ...

  6. linux使用FIO测试磁盘的iops

    FIO是测试IOPS的非常好的工具,用来对硬件进行压力测试和验证,支持13种不同的I/O引擎,包括:sync,mmap, libaio, posixaio, SG v3, splice, null, ...

  7. 文件操作ofstream,open,close,ifstream,fin,依照行来读取数据, fstream,iosin iosout,fio.seekg(),文件写入和文件读写,文件拷贝和文件

     1.ofstream,open,close 写入文件 #include<iostream> #include<fstream> using namespace std; ...

  8. 【转】FIO使用指南

    原文地址:http://blog.csdn.net/yuesichiu/article/details/8722417 Fio压测工具和io队列深度理解和误区 这个文档是对fio-2.0.9 HOWT ...

  9. linux 磁盘IO测试工具:FIO (同时简要介绍dd工具测试)

    FIO是测试IOPS的非常好的工具,用来对硬件进行压力测试和验证.磁盘IO是检查磁盘性能的重要指标,可以按照负载情况分成照顺序读写,随机读写两大类. 目前主流的第三方IO测试工具有fio.iomete ...

随机推荐

  1. 无法在类...中找到资源".bmp"

    在WinForm中写的一个程序,在项目中添加了一个bmp图片,然后 public void SetSubType(int SubType) { m_subType = SubType; switch ...

  2. React—Native开发之原生模块向JavaScript发送事件

    首先,由RN中文网关于原生模块(Android)的介绍可以看到,RN前端与原生模块之 间通信,主要有三种方法: (1)使用回调函数Callback,它提供了一个函数来把返回值传回给JavaScript ...

  3. Aittit.attilax超级框架 api 规划大全

    Aittit.attilax超级框架 api 规划大全 1 Api分类2 1.1 核心2 1.2 属性2 1.3 CSS2 1.4 选择器2 1.5 文档处理3 1.6 筛选3 1.7 事件3 1.8 ...

  4. 产品相关 细说软件产品和业务 & 业务过程(流程) & 业务逻辑

    细说软件产品和业务& 业务过程(流程) & 业务逻辑   by:授客 QQ:1033553122   作为一名测试人猿,需要懂产品,不懂产品的测试猿不是好测试猿猴.而业务逻辑是软件产品 ...

  5. Activity被回收导致fragment的getActivity为空

    在编写含有Fragment代码的时候,经常会遇到这种情况,假如app长时间在后台运行,再点击进入会crash,而且fragment页面有重叠的现象. 如果系统内存不足.或者切换横竖屏.或者app长时间 ...

  6. Hive是读时模式

    Hive处理的数据是大数据,在保存表数据时不对数据进行校验,而是在读数据时校验,不符合格式的数据设置为NULL: 读时模式的优点是,加载数据库快. 传统的数据库如mysql.oracle是写时模式,不 ...

  7. 传递命令行参数示例代码 (C 和 Python)

    C语言 在 C 语言中, 使用 main 函数的输入参数 argc 和 argv 传入命令行参数. argc 为 int 类型, 表示传入命令行参数的个数 (argument count); argv ...

  8. Hibernate的increment主键生成机制带来的问题

    最近给学校做的系统,总出现主键插入冲突的问题.主键是通过hibernate自动生成的,设置increment属性,总出现Duplicate entry的错误.搜到解决方案如下: 在网站运行在apach ...

  9. Entity Framework对同一张表配置一对多关系

    在实际的项目开发中,可能会遇到同一张表同时保存自身和上级(或下级)的信息(一般是通过设置一个上级主键[ParentId]的列与主键[Id]关系) 例如:城市库,有国家.省.市...,省的ParentI ...

  10. 12 Things Developers Will Love About Oracle Database 12c Release 2

    by Chris Saxon-Oracle It's Here: Oracle Database 12c Release 2 (12.2) Is available on Oracle Cloud. ...