本文主要分析了Linux的iostat命令的源码,iostat的主要功能见博客:性能测试进阶指南——基础篇之磁盘IO

iostat源码共563行,应该算是Linux系统命令代码比较少的了。源代码中主要涉及到如下几个Linux的内核文件:

  • 1、/proc/diskstats——该文件是内核2.6以上的系统中的,记录了从Linux系统启动之后,所有磁盘的相关信息,该文件中每个参数代表的意义可以自行google或者baidu,或者见博客:/proc/diskstats参数含义
  • 2、/proc/partitions——partitions是2.4版本的系统中的,其含义基本与diskstats一样。
  • 3、/proc/stat——stat记录了自系统启动之后,CPU的信息,具体含义可以参考博客:性能测试进阶指南——基础篇一(系统资源的讲解)
  • 4、/proc/cpuinfo——iostat主要是从该内核文件中获取cpu的核心数的。

iostat源码解析

第一步,从/proc/cpuinfo中获取系统的cpu核心数,通过计算该文件中processor出现的次数便可以得到cpu的核心数;

第二步,通过判断文件/proc/diskstats和/proc/partitions是否存在,从而判断linux的内核是2.4版本还是2.6版本:如果/proc/diskstats文件存在,则为2.6版本;否则判断/proc/partitions是否存在,若存在,则为2.4版本;

第三部,分析iostat命令输入的参数,每个参数的功能可以在上一篇博客中找到:性能测试进阶指南——基础篇之磁盘IO

第四步,初始化,获取磁盘名称。以内核2.6为例,读取文件/proc/diskstats

104    0 cciss/c0d0 49787 19805 1597284 159946 20172754 28596938 390157514 1583532 0 1352168 1737502

第一个参数104和第二个参数0分别代表了major和minor,major是8的倍数,minor是16的倍数,只要同时符合这两个的条件,其对应的第三个参数cciss/c0d0便是所需要获取的磁盘名称;

第五步,进入主循环:

(1) 获取/proc/diskstats中每个磁盘的数据,例如:

104    0 cciss/c0d0 49787 19805 1597284 159946 20172754 28596938 390157514 1583532 0 1352168 1737502

每个参数对应的值为

104——major
0——minor
49787——rd_ios
19805——rd_merges
1597284——rd_sectors
159946——rd_ticks
20172754——wr_ios
28596938——wr_merges
390157514——wr_sectors
1583532——wr_ticks
1352168——ticks
1737502——aveq

(2) 获取/proc/stat中的数据,计算cpu的平均时间:分别获取cpu的user时间,nice时间,system时间,idle时间,iowait时间。计算中将nice时间并入user时间,将irq时间和softirq时间并入system时间。此处只计算cpu的平均和状态,不计算每隔核单独的状态。

(3)计算deltams时间,其中HZ是Linux的系统频率。

deltams = 1000.0 * ((new_cpu.user + new_cpu.system + new_cpu.idle + new_cpu.iowait) - (old_cpu.user + old_cpu.system + old_cpu.idle + old_cpu.iowait)) / ncpu / HZ; `

(4)计算IO

blkio.rd_ios = new_blkio[p].rd_ios - old_blkio[p].rd_ios;
blkio.rd_merges = new_blkio[p].rd_merges - old_blkio[p].rd_merges;
blkio.rd_sectors = new_blkio[p].rd_sectors - old_blkio[p].rd_sectors;
blkio.rd_ticks = new_blkio[p].rd_ticks - old_blkio[p].rd_ticks;
blkio.wr_ios = new_blkio[p].wr_ios - old_blkio[p].wr_ios;
blkio.wr_merges = new_blkio[p].wr_merges - old_blkio[p].wr_merges;
blkio.wr_sectors = new_blkio[p].wr_sectors - old_blkio[p].wr_sectors;
blkio.wr_ticks = new_blkio[p].wr_ticks - old_blkio[p].wr_ticks;
blkio.ticks = new_blkio[p].ticks - old_blkio[p].ticks;
blkio.aveq = new_blkio[p].aveq - old_blkio[p].aveq;
n_ios = blkio.rd_ios + blkio.wr_ios;
n_ticks = blkio.rd_ticks + blkio.wr_ticks;
n_kbytes = (blkio.rd_sectors + blkio.wr_sectors) / 2.0;
queue = blkio.aveq / deltams;
size = n_ios ? n_kbytes / n_ios : 0.0;
wait = n_ios ? n_ticks / n_ios : 0.0;
svc_t = n_ios ? blkio.ticks / n_ios : 0.0;
busy = 100.0 * blkio.ticks / deltams;
if (busy > 100.0) busy = 100.0;

rd_sectors和wr_sectors是扇区数,如果需要换算成KB等单位,需要除以2,1KB=2*512Bytes。512Bytes为1个扇区数。

(5)计算CPU

cpu.user = new_cpu.user - old_cpu.user;
cpu.system = new_cpu.system - old_cpu.system;
cpu.idle = new_cpu.idle - old_cpu.idle;
cpu.iowait = new_cpu.iowait - old_cpu.iowait;
total = (cpu.user + cpu.system + cpu.idle + cpu.iowait) / 100.0;
printf("%3.0f %3.0f ", cpu.user / total, cpu.system / total);
if (kernel == 6) printf("%3.0f ", cpu.iowait / total);
printf("%3.0f", cpu.idle / total);

(6) Save old stats:

old_blkio[p] = new_blkio[p];
old_cpu = new_cpu;

每隔采样时间循环执行第五步。

从源码中可以看出,第一次获取的时候,是没有old stats的,所有的old stats值均为0,即iostat在第一次输出的值为Linux启动之后至当前时间的一个平均状态值,在之后的输出值则为系统当前的实时磁盘I/O信息和CPU信息。

Linux内核源码详解——命令篇之iostat[zz]的更多相关文章

  1. [转]Linux内核源码详解--iostat

    Linux内核源码详解——命令篇之iostat 转自:http://www.cnblogs.com/york-hust/p/4846497.html 本文主要分析了Linux的iostat命令的源码, ...

  2. RocketMQ源码详解 | Broker篇 · 其一:线程模型与接收链路

    概述 在上一节 RocketMQ源码详解 | Producer篇 · 其二:消息组成.发送链路 中,我们终于将消息发送出了 Producer,在短暂的 tcp 握手后,很快它就会进入目的 Broker ...

  3. RocketMQ源码详解 | Broker篇 · 其四:事务消息、批量消息、延迟消息

    概述 在上文中,我们讨论了消费者对于消息拉取的实现,对于 RocketMQ 这个黑盒的心脏部分,我们顺着消息的发送流程已经将其剖析了大半部分.本章我们不妨乘胜追击,接着讨论各种不同的消息的原理与实现. ...

  4. RocketMQ源码详解 | Broker篇 · 其五:高可用之主从架构

    概述 对于一个消息中间件来讲,高可用功能是极其重要的,RocketMQ 当然也具有其对应的高可用方案. 在 RocketMQ 中,有主从架构和 Dledger 两种高可用方案: 第一种通过主 Brok ...

  5. RocketMQ源码详解 | Producer篇 · 其二:消息组成、发送链路

    概述 在上一节 RocketMQ源码详解 | Producer篇 · 其一:Start,然后 Send 一条消息 中,我们了解了 Producer 在发送消息的流程.这次我们再来具体下看消息的构成与其 ...

  6. RocketMQ源码详解 | Broker篇 · 其三:CommitLog、索引、消费队列

    概述 上一章中,已经介绍了 Broker 的文件系统的各个层次与部分细节,本章将继续了解在逻辑存储层的三个文件 CommitLog.IndexFile.ConsumerQueue 的一些细节.文章最后 ...

  7. RocketMQ源码详解 | Consumer篇 · 其一:消息的 Pull 和 Push

    概述 当消息被存储后,消费者就会将其消费. 这句话简要的概述了一条消息的最总去向,也引出了本文将讨论的问题: 消息什么时候才对被消费者可见? 是在 page cache 中吗?还是在落盘后?还是像 K ...

  8. 和菜鸟一起学linux内核源码之基础准备篇

    来源:http://blog.csdn.net/eastmoon502136/article/details/8711104 推荐阅读:linux内核源码最初版linux内核源代码,简单易懂,适合初学 ...

  9. epoll内核源码详解(转 作者:赛罗·奥特曼 来源:牛客网)

    发现自己发的一篇面经后,很多小伙伴向我索要epoll的内核源码实现,那我就在牛客网发下这源码还有自己总结的流程. 另外 网上很多博客说epoll使用了共享内存,这个是完全错误的 ,可以阅读源码,会发现 ...

随机推荐

  1. (Unity)Unity自定义Debug日志文件,利用VS生成Dll文件并使用Dotfuscated进展混淆,避免被反编译

    Unity自定义Debug日志文件,利用VS生成Dll文件并使用Dotfuscated进行混淆,避免被反编译. 1.打开VS,博主所用版本是Visual Studio 2013. 2.新建一个VC项目 ...

  2. 模板短信接口调用java,pythoy版(一) 网易云信

    说明 短信服务平台有很多,我只是个人需求,首次使用,算是测试用的,故选个网易(大公司). 稳定性:我只测试了15条短信... 不过前3条短信5分钟左右的延时,后面就比较快.... 我只是需要发短信,等 ...

  3. Activity的生命周期及各生命周期方法的作用

    一.Activity的生命周期中各个方法的作用 onCreate(): 做Activity上所需要数据的初始化工作. onStart(): 显示Activity界面,此时用户对界面可见但不可交互. o ...

  4. Linux内核分析之扒开系统调用的三层皮(上)

    一.原理总结 本周老师讲的内容主要包括三个方面,用户态.内核态和中断,系统调用概述,以及使用库函数API获取系统当前时间.系统调用是操作系统为用户态进程与硬件设备进行交互提供的一组接口,也是一种特殊的 ...

  5. 关于Yaf的一些说明[转Yaf作者]

    关于Yaf的一些说明[转Yaf作者] 说明下,这篇文章转至于yaf作者鸟哥的博文,因为最近在系统的学习Yaf框架,发现了这篇文章,感觉对于了解Yaf框架还是很有用处,所以转过来和大家分享一下 Yaf是 ...

  6. [算法]——全排列(Permutation)以及next_permutation

    排列(Arrangement),简单讲是从N个不同元素中取出M个,按照一定顺序排成一列,通常用A(M,N)表示.当M=N时,称为全排列(Permutation).从数学角度讲,全排列的个数A(N,N) ...

  7. PHP访问数据库

    1.原生mysql方式 <?php //最原生态的访问方式,不过SQL注入是个麻烦事 $con = mysql_connect("localhost","root& ...

  8. ContentControl 与 ViewModel (二)

    上文说到 可以使用DataTemplateSelector. 其实等于是用 DataTemplateSelector + 动态创建DataTemplate来实现. using System; usin ...

  9. 在Android中进行单元测试遇到的问题

    问题1.Cannot connect to VM  socket closed 在使用JUnit进行测试的时候,遇到这个问题.网上的解释是:使用Eclipse对Java代码进行调试,无论是远程JVM还 ...

  10. 说说分析bug的一些心得

    bug已经成为程序员工作中的一部分,作为从事嵌入式软件开发已有三年的我,经手的bug也不少了.先说说自己对于bug的心态变化吧,刚开始工作的时候,自己还是很喜欢bug的.那时,自己是负责维护别人的代码 ...