服务器维护,服务器代维,安全设置,漏洞扫描,入侵检测服务

运维之家

 找回密码
 注册
搜索
查看: 4727|回复: 3

系统io优化

[复制链接]
dirtysea 发表于 2013-4-14 15:39:58 | 显示全部楼层 |阅读模式
linux下分析哪个进程最耗iowait

常用工具命令:
yum install sysstat iotop
hdparm -tT /dev/sda2
cat /proc/sys/vm/dirty_background_ratio 查看当前的值
iotop -o

先停掉syslog
service syslog stop

打开block dump:
echo 1 > /proc/sys/vm/block_dump

多次运行,查看结果
dmesg | egrep "READ|WRITE|dirtied" | egrep -o '([a-zA-Z]*)' | sort | uniq -c | sort -rn | head
排前的比较占用io

抓完后关掉block_dump和启动syslog:
echo 0 > /proc/sys/vm/block_dump
service syslog start

我的一台负荷较重的服务器,iowait经常在10%以上,因此这样查看了下,多次运行显示:

   1283 kjournald
   1059 httpd
    190 pdflush
-------------------------------------
看来kjournald是罪魁祸首?需要优化。

kjournald
EXT3文件系统的日志进程,具有3种模式:

journal - logs all filesystem data and metadata changes. The slowest of the three ext3 journaling modes, this journaling mode minimizes the chance of losing the changes you have made to any file in an ext3 filesystem.(记录所有文件系统上的元数据改变,最慢的一种模式,)
ordered - only logs changes to filesystem metadata, but flushes file data updates to disk before making changes to associated filesystem metadata. This is the default ext3 journaling mode.(默认使用的模式,只记录文件系统改变的元数据,并在改变之前记录日志)
writeback - only logs changes to filesystem metadata but relies on the standard filesystem write process to write file data changes to disk. This is the fastest ext3 journaling mode.(最快的一种模式,同样只记录修改过的元数据,依赖标准文件系统写进程将数据写到硬盘)

修改模式EXT3的工作模式;
vim /etc/fstab
/dev/hda5      /opt            ext3       data=writeback        1 0


iostat -x 1 10
Linux 2.6.18-92.el5xen 03/01/2010
avg-cpu:   %user %nice %system %iowait   %steal %idle
          1.10 0.00 4.82 39.54 0.07 54.46
Device:       rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await   svctm   %util
sda             0.00     3.50   0.40   2.50     5.60 48.00 18.48     0.00 0.97 0.97 0.28
sdb             0.00     0.00   0.00   0.00     0.00     0.00     0.00     0.00 0.00 0.00 0.00
sdc             0.00     0.00   0.00   0.00     0.00     0.00     0.00     0.00 0.00 0.00 0.00
sdd             0.00     0.00   0.00   0.00     0.00     0.00     0.00     0.00 0.00 0.00 0.00
sde             0.00     0.10   0.30   0.20     2.40     2.40     9.60     0.00 1.60 1.60 0.08
sdf              17.40     0.50 102.00   0.20 12095.20     5.60 118.40     0.70 6.81 2.09   21.36
sdg          232.40     1.90 379.70   0.50 76451.20 19.20 201.13     4.94 13.78 2.45   93.16
rrqm/s: 每秒进行 merge 的读操作数目。即 delta(rmerge)/s
wrqm/s:    每秒进行 merge 的写操作数目。即 delta(wmerge)/s
r/s:           每秒完成的读 I/O 设备次数。即 delta(rio)/s
w/s:       每秒完成的写 I/O 设备次数。即 delta(wio)/s
rsec/s: 每秒读扇区数。即 delta(rsect)/s
wsec/s:   每秒写扇区数。即 delta(wsect)/s
rkB/s:   每秒读K字节数。是 rsect/s 的一半,因为每扇区大小为512字节。(需要计算)
wkB/s: 每秒写K字节数。是 wsect/s 的一半。(需要计算)
avgrq-sz: 平均每次设备I/O操作的数据 大小 (扇区)。delta(rsect+wsect)/delta(rio+wio)
avgqu-sz: 平均I/O队列长度。即 delta(aveq)/s/1000 (因为aveq的单位为毫秒)。
await: 平均每次设备I/O操作的等待时间 (毫秒)。即 delta(ruse+wuse)/delta(rio+wio)
svctm: 平均每次设备I/O操作的服务 时间 (毫秒)。即 delta(use)/delta(rio+wio)
%util:    一秒中有百分之多少的时间用于 I/O 操作,或者说一秒中有多少时间 I/O 队列是非空的。即 delta(use)/s/1000 (因为use的单位为毫秒)

如果%util 接近100%,说明产生的I/O请求太多,I/O系统 已经满负荷,该磁盘
可能存在瓶颈;idle 小于70% IO压力就较大了,一般读取速度有较多的wait。

同时可以结合vmstat 查看查看b参数 (等待资源的进程数 )和wa参数(IO等待所占用的CPU时间的百分比,高过30%时IO压力高 )

另外还可以参考
一般:
svctm < await (因为同时等待的请求的等待时间被重复计算了),
svctm的大小一般和磁盘性能 有关 :CPU/内存 的负荷也会对其有影响,请求过多也会间接导致 svctm 的增加。
await: await的大小一般取决于服务时间(svctm) 以及 I/O 队列的长度和 I/O 请求的发出模式 。
如果svctm 比较接近await,说明I/O 几乎没有等待时间;
如果await 远大于svctm,说明I/O队列太长,应用 得到的响应时间变慢
如果响应时间超过了用户 可以容许的范围,这时可以考虑更换更快的磁盘,调整内核 elevator算法,优化 应用,或者升级 CPU 。
队列长度(avgqu-sz)也可作为衡量系统 I/O 负荷的指标,但由于 avgqu-sz 是按照单位时间的平均值,所以不能反映瞬间的 I/O 洪水。

别人一个不错的例子(I/O 系统vs超市排队)
举一个例子,我们在超市排队 checkout 时,怎么决定该去哪个交款台呢? 首当是看排的队人数,5个人总比20人要快吧?除了数人头,我们也常常看看前面人**的东西多少,如果前面有个采购了一星期食品的大妈,那么可以考虑换个 队排了。还有就是收银员的速度了,如果碰上了连钱都点不清楚的新手,那就有的等了。另外,时机也很重要,可能 5分钟前还人满为患的收款台,现在已是人去楼空,这时候交款可是很爽啊,当然,前提是那过去的 5 分钟里所做的事情比排队要有意义(不过我还没发现什么事情比排队还无聊的)。
I/O 系统也和超市排队有很多类似之处:
r/s+w/s 类似于交款人的总数
平均队列长度(avgqu-sz)类似于单位时间里平均排队人的个数
平均服务时间(svctm)类似于收银员的收款速度
平均等待时间(await)类似于平均每人的等待时间
平均I/O数据(avgrq-sz)类似于平均每人所买的东西多少
I/O 操作率 (%util)类似于收款台前有人排队的时间比例。
我们可以根据这些数据分析出 I/O 请求的模式,以及 I/O 的速度和响应时间。




 楼主| dirtysea 发表于 2013-4-15 16:22:39 | 显示全部楼层
linux硬盘速度测试方法
进行性能上的测试,主要速度方面的。
1.hdparm 测试结果
#hdparm -tT /dev/sdb1:
Timing cached reads:   5160 MB in  2.00 seconds = 2579.10 MB/sec
Timing buffered disk reads:  488 MB in  3.00 seconds = 162.58 MB/sec
2. copytree测试结果,复制文件目录到阵列中。
time cp -ra /etc /lib /boot /home /usr /initrd /mnt/test1
3.raid内文件树拷贝速度
time cp test1 test2
real    3m3.122s
user    0m2.236s
sys     0m49.753s
4.raid生成大文件速度
time yes abcdefghijklmnopqrstuvwxyz1234567890 >bigfile
real    1m35.974s
user    0m28.510s
sys     0m43.568s
12G= 12394221568
5. raid内大文件复制速度
time cp bigfile bigfile2
real    2m31.533s
user    0m1.730s
sys     0m50.252s



使用bonnie++测试磁盘及文件系统的性能


一、简介


Bonnie++是一个硬盘和文件系统的基准性能测试工具,它通过一系列的简单测试来生成硬盘和文件系统的性能参数。其主程序提供两种风格的测试:针对单个文件的数据库风格的访问测试和针对大量小文件的创建和删除来模拟诸如Squid,INN,或者Maildir格式的Email这一类风格的访问测试。在选择RAID设定方法、文件系统的创建参数和NFS访问方式时,此工具可以提供有用的帮助信息。

Bonnie++对三个方面做基准测试:数据读、写速度,每秒可以完成的磁盘寻道次数和每秒可以完成的文件元数据操作次数。

元数据的性能表现跟运行着squid或为Maildir格式邮件服务器保存邮件时有很大关系,因为它们都是元数据操作密集型的应用。

Bonnie++目前的最新版本是1.03e,项目地址:http://www.coker.com.au/bonnie++/

二、安装

如果你的Linux系统是SUSE、Ubuntu或Fedora 9以上的版本,你可以使用各自的软件管理工具直接安装使用。当然,你也可以通过编译的方式来安装,其步骤如下:

# tar zxvf bonnie++-1.03e.tgz
# cd bonnie++-1.03e
# ./configure
# make && make install

安装完成以后会在/usr/local/sbin/目录中生成两个可执行文件,bonnie++(主测试程序)和zcav(裸盘吞吐量测试程序);同时也会在/usr/local/bin目录下生成两个可执行文件,用于生成可读性强的测试报告,它们是bon_csv2html和bon_csv2txt。

三、bonnie++的常用选项说明

-d DIR 用于测试的目录,即测试目标位置;
-s SIZE(MiB) 用于测试IO性能的文件的大小;如果指定的文件大小大于1G,bonnie++会将其分为多个大小为1G的文件;
-m 测试目标主机的主机名,仅用于显示测试结果时的主机标识;
-r 指定测试程度使用的内存大小;bonnie++一般要求指定的测试文件的大小至少为物理内存的2倍;如果测试时指定的文件过小,则可以通过指定所使用的物理内存大小来滞此条件;
-x 用于指定同时运行的测试数目;
-u 测试程序运行时关联的uid,如果以root用户的身份做测试,则此项必须明确指定。-g选项则用于指定gid;
-q 静默模式;
-f 快速模式,此种模式不进行IO测试;
-D 直接IO测试,用于测试大规模IO请求时的性能;

使用示例:
# bonnie++ -d /data -u root -s 4096 -m mail
Using uid:0, gid:0.
Writing with putc()...done
Writing intelligently...done
Rewriting...done
Reading with getc()...done
Reading intelligently...done
start 'em...done...done...done...
Create files in sequential order...done.
Stat files in sequential order...done.
Delete files in sequential order...done.
Create files in random order...done.
Stat files in random order...done.
Delete files in random order...done.
Version 1.03e ------Sequential Output------ --Sequential Input- --Random-
-Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP
mail 4G 70035 88 81580 15 34152 18 51171 94 75728 25 135.2 5
------Sequential Create------ --------Random Create--------
-Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
files /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP /sec %CP
16 +++++ +++ +++++ +++ +++++ +++ +++++ +++ +++++ +++ +++++ +++
mail,4G,70035,88,81580,15,34152,18,51171,94,75728,25,135.2,5,16,+++++,+++,+++++,+++,+++++,+++,+++++,+++,+++++,+++,+++++,+++

说明:
1、测试结果中显示形如的“++++”的符号表示此项测试时间小于500ms,所以被视作不准确结果不予显示;
2、每项测试都会显示两个结果,其中的%CP表示此项测试的CPU占用率;

四、zcav使用简介

ZCAV是“Zoned Constant Angular Velocity”的简写,用于测试裸盘的吞吐率。常用选项如下:

-b 读/写操作的数据块的大小,单位为MB:默认为100M;
-c 读/写整个磁盘的次数;
-f 读入数据时所用的文件;
-u 测试时使用的uid;-g 为使用的gid;
-w 通过向磁盘填充“0”的方式测试,会破坏原有文件。

使用示例:

# zcav -b 2048 /dev/sda3
#loops: 1, version: 1.03e
#block offset (GiB), MiB/s, time
0.00 82.84 24.721
2.00 72.28 28.335
# Read 4 gigs in 53 seconds, 77 megabytes per second.

 楼主| dirtysea 发表于 2013-4-16 13:43:35 | 显示全部楼层
smartctl使用详解:


功能:可以查看生产厂商、型号、序列号、容量、是否支持SMART、开启否
主页:http://smartmontools.sourceforge.net/
Centos安装:
yum -y install smartmontools

smartctl
-i 指定设备
-d 指定设备类型,例如:ata, scsi, marvell, sat, 3ware,N
-a 或A 显示所有信息
-l 指定日志的类型,例如:TYPE: error, selftest, selective, directory,background, scttemp[sts,hist]
-H 查看硬盘健康状态
-t short 后台检测硬盘,消耗时间短
-t long 后台检测硬盘,消耗时间长
-C -t short 前台检测硬盘,消耗时间短
-C -t long 前台检测硬盘,消耗时间长
-X 中断后台检测硬盘
-l selftest 显示硬盘检测日志
HP硬盘:
smartctl -s on -d  cciss,0 /dev/cciss/c0d0 开启SMART
smartctl  -a  -d cciss,0 -i /dev/cciss/c0d0  显示所有SMART信息
smartctl  -l error  -d cciss,0 -i /dev/cciss/c0d0 查看磁盘错误日志
+++++++++++++++++++++++smarted服务+++++++++++++++++

简单说下smartctl:smartd由kernel-utils包缺省安装。用命令 rpm -ql kernel-utils 可以列出kernel-utils包中的文件
它是一个守护进程(一个帮助程序),它能监视拥有自我监视,分析和汇报技术(Self-Monitoring, Analysis, and Reporting Technology - SMART)的硬盘。
主配置文件:/etc/smartd.conf
添加一行/dev/cciss/c0d0 -H -m sys@5iqiong.com
上边的配置表示smartd以静默状态工作,当SMART中报告PASSED的时候不理睬一旦出现Failure
 楼主| dirtysea 发表于 2013-4-16 15:18:28 | 显示全部楼层

监控每个进程使用I/O情况

 

 

iopp.c源码
/*
 * Copyright (C) 2008 Mark Wong
 */
 
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <ctype.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
 
#define PROC "/proc"
 
#define GET_VALUE(v) \
  p = strchr(p, ':'); \
  ++p; \
  ++p; \
  q = strchr(p, '\n'); \
  length = q - p; \
  if (length >= BUFFERLEN) \
  { \
   printf("ERROR - value is larger than the buffer: %d\n", __LINE__); \
   exit(1); \
  } \
  strncpy(value, p, length); \
  value[length] = '\0'; \
  v = atoll(value);
 
#define BTOKB(b) b >> 10
#define BTOMB(b) b >> 20
 
#define BUFFERLEN 255
#define COMMANDLEN 1024
#define VALUELEN 63
 
#define NUM_STRINGS 8
 
struct io_node
{
 int pid;
 long long rchar;
 long long wchar;
 long long syscr;
 long long syscw;
 long long read_bytes;
 long long write_bytes;
 long long cancelled_write_bytes;
 char command[COMMANDLEN + 1];
 struct io_node *next;
};
 
struct io_node *head = NULL;
int command_flag = 0;
int idle_flag = 0;
int mb_flag = 0;
int kb_flag = 0;
int hr_flag = 0;
 
/* Prototypes */
char *format_b(long long);
struct io_node *get_ion(int);
struct io_node *new_ion(char *);
void upsert_data(struct io_node *);
 
char *
format_b(long long amt)
{
 static char retarray[NUM_STRINGS][16];
 static int index = 0;
 register char *ret;
 register char tag = 'B';
 
 ret = retarray[index];
 index = (index + 1) % NUM_STRINGS;
 
 if (amt >= 10000) {
  amt = (amt + 512) / 1024;
  tag = 'K';
  if (amt >= 10000) {
   amt = (amt + 512) / 1024;
   tag = 'B';
   if (amt >= 10000) {
    amt = (amt + 512) / 1024;
    tag = 'G';
   }
  }
 }
 
 snprintf(ret, sizeof(retarray[index]) - 1, "%lld%c", amt, tag);
 
 return (ret);
}
 
int
get_cmdline(struct io_node *ion)
{
 int fd;
 int length;
 char filename[BUFFERLEN + 1];
 char buffer[COMMANDLEN + 1];
 char *p;
 char *q;
 
 
 length = snprintf(filename, BUFFERLEN, "%s/%d/cmdline", PROC, ion->pid);
 if (length == BUFFERLEN)
  printf("WARNING - filename length may be too big for buffer: %d\n",
    __LINE__);
 fd = open(filename, O_RDONLY);
 if (fd == -1)
  return 1;
 length = read(fd, buffer, sizeof(buffer) - 1);
 close(fd);
 buffer[length] = '\0';
 if (length == 0)
  return 2;
 if (command_flag == 0)
 {
  /*
   * The command is near the beginning; we don't need to be able to
   * the entire stat file.
   */
  p = strchr(buffer, '(');
  ++p;
  q = strchr(p, ')');
  length = q - p;
 }
 else
  p = buffer;
 length = length < COMMANDLEN ? length : COMMANDLEN;
 strncpy(ion->command, p, length);
 ion->command[length] = '\0';
 return 0;
}
 
struct io_node *
get_ion(int pid)
{
 struct io_node *c = head;
 
 while (c != NULL)
 {
  if (c->pid == pid)
   break;
  c = c->next;
 }
 return c;
}
 
int
get_tcomm(struct io_node *ion)
{
 int fd;
 int length;
 char filename[BUFFERLEN + 1];
 char buffer[BUFFERLEN + 1];
 char *p;
 char *q;
 
 length = snprintf(filename, BUFFERLEN, "%s/%d/stat", PROC, ion->pid);
 if (length == BUFFERLEN)
  printf("WARNING - filename length may be too big for buffer: %d\n",
    __LINE__);
 fd = open(filename, O_RDONLY);
 if (fd == -1)
  return 1;
 length = read(fd, buffer, sizeof(buffer) - 1);
 close(fd);
 /*
  * The command is near the beginning; we don't need to be able to
  * the entire stat file.
  */
 p = strchr(buffer, '(');
 ++p;
 q = strchr(p, ')');
 length = q - p;
 length = length < BUFFERLEN ? length : BUFFERLEN;
 
 strncpy(ion->command, p, length);
 ion->command[length] = '\0';
 return 0;
}
 
struct io_node *
insert_ion(struct io_node *ion)
{
 struct io_node *c;
 struct io_node *p;
 
 /* Check the head of the list as a special case. */
 if (ion->pid < head->pid)
 {
  ion->next = head;
  head = ion;
  return head;
 }
 
 c = head->next;
 p = head;
 while (c != NULL)
 {
  if (ion->pid < c->pid)
  {
   ion->next = c;
   p->next = ion;
   return head;
  }
  p = c;
  c = c->next;
 }
 
 /* Append to the end of the list. */
 if (c == NULL)
  p->next = ion;
 
 return head;
}
 
void
get_stats()
{
 DIR *dir = opendir(PROC);
 struct dirent *ent;
 char filename[BUFFERLEN + 1];
 char buffer[BUFFERLEN + 1];
 
 char value[BUFFERLEN + 1];
 
 /* Display column headers. */
 if (hr_flag == 1)
  printf("%5s %5s %5s %8s %8s %5s %6s %7s %s\n", "pid", "rchar", "wchar",
    "syscr", "syscw", "reads", "writes", "cwrites", "command");
 else if (kb_flag == 1)
  printf("%5s %8s %8s %8s %8s %8s %8s %8s %s\n", "pid", "rchar", "wchar",
    "syscr", "syscw", "rkb", "wkb", "cwkb", "command");
 else if (mb_flag == 1)
  printf("%5s %8s %8s %8s %8s %8s %8s %8s %s\n", "pid", "rchar", "wchar",
    "syscr", "syscw", "rmb", "wmb", "cwmb", "command");
 else
  printf("%5s %8s %8s %8s %8s %8s %8s %8s %s\n", "pid", "rchar", "wchar",
    "syscr", "syscw", "rbytes", "wbytes", "cwbytes", "command");
 
 /* Loop through the process table and display a line per pid. */
 while ((ent = readdir(dir)) != NULL)
 {
  int rc;
  int fd;
  int length;
 
  char *p;
  char *q;
 
  struct io_node *ion;
  struct io_node *old_ion;
 
  long long rchar;
  long long wchar;
  long long syscr;
  long long syscw;
  long long read_bytes;
  long long write_bytes;
  long long cancelled_write_bytes;
 
  if (!isdigit(ent->d_name[0]))
   continue;
 
  ion = new_ion(ent->d_name);
 
  if (command_flag == 1)
   rc = get_cmdline(ion);
  if (command_flag == 0 || rc != 0)
   /* If the full command line is not asked for or is empty... */
   rc = get_tcomm(ion);
 
  if (rc != 0)
  {
   free(ion);
   continue;
  }
 
  /* Read 'io' file. */
  length = snprintf(filename, BUFFERLEN, "%s/%s/io", PROC, ent->d_name);
  if (length == BUFFERLEN)
   printf("WARNING - filename length may be too big for buffer: %d\n",
     __LINE__);
  fd = open(filename, O_RDONLY);
  if (fd == -1)
  {
   free(ion);
   continue;
  }
  length = read(fd, buffer, sizeof(buffer) - 1);
  close(fd);
  buffer[length] = '\0';
 
  /* Parsing the io file data. */
  p = buffer;
  GET_VALUE(ion->rchar);
  GET_VALUE(ion->wchar);
  GET_VALUE(ion->syscr);
  GET_VALUE(ion->syscw);
  GET_VALUE(ion->read_bytes);
  GET_VALUE(ion->write_bytes);
  GET_VALUE(ion->cancelled_write_bytes);
 
  old_ion = get_ion(ion->pid);
 
  /* Display the pid's io data. */
  if (old_ion != NULL)
  {
   rchar = ion->rchar - old_ion->rchar;
   wchar = ion->wchar - old_ion->wchar;
   syscr = ion->syscr - old_ion->syscr;
   syscw = ion->syscw - old_ion->syscw;
   read_bytes = ion->read_bytes - old_ion->read_bytes;
   write_bytes = ion->write_bytes - old_ion->write_bytes;
   cancelled_write_bytes = ion->cancelled_write_bytes -
     old_ion->cancelled_write_bytes;
 
   if (kb_flag == 1 && hr_flag == 0)
   {
    rchar = BTOKB(rchar);
    wchar = BTOKB(wchar);
    syscr = BTOKB(syscr);
    syscw = BTOKB(syscw);
    read_bytes = BTOKB(read_bytes);
    write_bytes = BTOKB(write_bytes);
    cancelled_write_bytes = BTOKB(cancelled_write_bytes);
   }
   else if (mb_flag == 1 && hr_flag == 0)
   {
    rchar = BTOMB(rchar);
    wchar = BTOMB(wchar);
    syscr = BTOMB(syscr);
    syscw = BTOMB(syscw);
    read_bytes = BTOMB(read_bytes);
    write_bytes = BTOMB(write_bytes);
    cancelled_write_bytes = BTOMB(cancelled_write_bytes);
   }
 
   if (!(idle_flag == 1 && rchar == 0 && wchar == 0 && syscr == 0 &&
     syscw == 0 && read_bytes == 0 && write_bytes == 0 &&
     cancelled_write_bytes == 0)) {
    if (hr_flag == 0)
     printf("%5d %8lld %8lld %8lld %8lld %8lld %8lld %8lld %s\n",
       ion->pid,
       rchar,
       wchar,
       syscr,
       syscw,
       read_bytes,
       write_bytes,
       cancelled_write_bytes,
       ion->command);
    else
     printf("%5d %5s %5s %8lld %8lld %5s %6s %7s %s\n",
       ion->pid,
       format_b(rchar),
       format_b(wchar),
       syscr,
       syscw,
       format_b(read_bytes),
       format_b(write_bytes),
       format_b(cancelled_write_bytes),
       ion->command);
   }
  }
  else if (idle_flag != 1)
   /*
    * No previous data, show 0's instead of calculating negatives
    * only if we are shoring idle processes.
    */
   printf("%5d %8d %8d %8d %8d %8d %8d %8d %s\n",
     ion->pid, 0, 0, 0, 0, 0, 0, 0, ion->command);
 
  upsert_data(ion);
 }
 closedir(dir);
 return;
}
 
struct io_node *
new_ion(char *pid)
{
 struct io_node *ion;
 
 ion = (struct io_node *) malloc(sizeof(struct io_node));
 bzero(ion, sizeof(struct io_node));
 ion->pid = atoi(pid);
 
 return ion;
}
 
void
upsert_data(struct io_node *ion)
{
 struct io_node *n;
 
 /* List is empty. */
 if (head == NULL)
 {
  head = ion;
  return;
 }
 
 /* Check if we have seen this pid before. */
 n = head;
 while (n != NULL)
 {
  if (n->pid == ion->pid)
  {
   n->rchar = ion->rchar;
   n->wchar = ion->wchar;
   n->syscr = ion->syscr;
   n->syscw = ion->syscw;
   n->read_bytes = ion->read_bytes;
   n->write_bytes = ion->write_bytes;
   n->cancelled_write_bytes = ion->cancelled_write_bytes;
   /*
    * If the pids wrap, then the command may be different then before.
    */
   strcpy(n->command, ion->command);
   free(ion);
   return;
  }
  n = n->next;
 }
 
 /* Add this pid to the list. */
 head = insert_ion(ion);
 return;
}
 
void
usage()
{
 printf("usage: iopp -h|--help\n");
 printf("usage: iopp [-ci] [-k|-m] [delay [count]]\n");
 printf("            -c, --command display full command line\n");
 printf("            -h, --help display help\n");
 printf("            -i, --idle hides idle processes\n");
 printf("            -k, --kilobytes display data in kilobytes\n");
 printf("            -m, --megabytes display data in megabytes\n");
 printf("            -u, --human-readable display data in kilo-, mega-, or giga-bytes\n");
}
 
int
main(int argc, char *argv[])
{
 int c;
 
 int delay = 0;
 int count = 0;
 int max_count = 1;
 
 while (1)
 {
  int option_index = 0;
  static struct option long_options[] = {
    { "command", no_argument, 0, 'c' },
    { "help", no_argument, 0, 'h' },
    { "human-readable", no_argument, 0, 'u' },
    { "idle", no_argument, 0, 'i' },
    { "kilobytes", no_argument, 0, 'k' },
    { "megabytes", no_argument, 0, 'm' },
    { 0, 0, 0, 0 }
  };
 
  c = getopt_long(argc, argv, "chikmu", long_options, &option_index);
  if (c == -1)
  {
   /* Handle delay and count arguments. */
 
   if (argc == optind)
    break; /* No additional arguments. */
   else if ((argc - optind) == 1)
   {
    delay = atoi(argv[optind]);
    max_count = -1;
   }
   else if ((argc - optind) == 2)
   {
    delay = atoi(argv[optind]);
    max_count = atoi(argv[optind + 1]);
   }
   else
   {
    /* Too many additional arguments. */
    usage();
    return 3;
   }
   break;
  }
 
  switch (c)
  {
  case 'c':
   command_flag = 1;
   break;
  case 'h':
   usage();
   return 0;
  case 'i':
   idle_flag = 1;
   break;
  case 'k':
   kb_flag = 1;
   break;
  case 'm':
   mb_flag = 1;
   break;
  case 'u':
   hr_flag = 1;
   break;
  default:
   usage();
   return 2;
  }
 }
 
 while (max_count == -1 || count++ < max_count)
 {
  get_stats();
  if (count != max_count)
   sleep(delay);
 }
 return 0;
}
 编译一下,就可以使用了

gcc -o iopp iopp.c
./iopp -i -k 5

如果不知道使用方法可以先--help

您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|小黑屋|手机版|Archiver|运维之家

GMT+8, 2022-1-25 13:15 , Processed in 0.120502 second(s), 18 queries .

Powered by Dirtysea

© 2008-2020 Dirtysea.com.

快速回复 返回顶部 返回列表