很多情况下开发者调测程序需要在Linux下获取具体的IO的状况,目前常用的IO观察工具用vmstat和iostat,具体功能上说当然是iostat更胜一筹,在IO统计上时间点上更具体精细。但二者都是在全局上看到IO,宏观上的数据对于判断IO到哪个文件上毫无帮助,这个时候block_dump的作用就显现出来了。

一、使用方法:

需要先停掉syslog功能,因为具体IO数据要通过printk输出,如果syslog存在,则会往message产生大量IO,干扰正常结果

 
1
2
suse:~ # service syslog stop
Shutting down syslog services done

然后启动block_dump

 
1
suse:~ # echo 1 > /proc/sys/vm/block_dump

先说效果:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
suse:~ # dmesg | tail
dmesg(3414): dirtied inode 9594 (LC_MONETARY) on sda1
dmesg(3414): dirtied inode 9238 (LC_COLLATE) on sda1
dmesg(3414): dirtied inode 9241 (LC_TIME) on sda1
dmesg(3414): dirtied inode 9606 (LC_NUMERIC) on sda1
dmesg(3414): dirtied inode 9350 (LC_CTYPE) on sda1
kjournald(506): WRITE block 3683672 on sda1
kjournald(506): WRITE block 3683680 on sda1
kjournald(506): WRITE block 3683688 on sda1
kjournald(506): WRITE block 3683696 on sda1
kjournald(506): WRITE block 3683704 on sda1
kjournald(506): WRITE block 3683712 on sda1
kjournald(506): WRITE block 3683720 on sda1
kjournald(506): WRITE block 3683728 on sda1
kjournald(506): WRITE block 3683736 on sda1
kjournald(506): WRITE block 3683744 on sda1

通过dmesg信息可以看到IO正在写那些文件,有进程号,inode号,文件名和磁盘设备名;但每个文件写了多少呢,仅仅通过dirtied inode就看不出来了,还需要分析WRITE block,后面的数字并不是真正的块号,而是内核IO层获取的扇区号,除以8即为块号,然后根据debugfs工具的icheck和ncheck选项,就可以获取该文件系统块属于哪个具体文件,具体请google之。

二、基本原理:

block_dump的原理其实很简单,内核在IO层根据标志block_dump在IO提交给磁盘的关口卡主过关的每一个BIO,将它们的数据打出来:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void submit_bio(int rw, struct bio *bio)
{
     int count = bio_sectors(bio);
 
     bio->bi_rw |= rw;
 
/*
* If it's a regular read/write or a barrier with data attached,
* go through the normal accounting stuff before submission.
*/
     if (bio_has_data(bio) && !(rw & REQ_DISCARD)) {
         if (rw & WRITE) {
         count_vm_events(PGPGOUT, count);
     } else {
         task_io_account_read(bio->bi_size);
         count_vm_events(PGPGIN, count);
     }
 
     if (unlikely(block_dump)) {
         char b[BDEVNAME_SIZE];
         printk(KERN_DEBUG "%s(%d): %s block %Lu on %s (%u sectors)n",
              current->comm, task_pid_nr(current),
              (rw & WRITE) ? "WRITE" : "READ",
              (unsigned long long)bio->bi_sector,
              bdevname(bio->bi_bdev, b),
              count);
        }
    }
 
    generic_make_request(bio);
}

具体WRITE block块号和文件系统块号之间的对应关系在submit_bh函数中决定

 
1
bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9);

inode的block_dump实现是通过block_dump___mark_inode_dirty搞定的,这次把关口架在inode脏数据写回的路上,把每个过关的inode信息打出来:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void __mark_inode_dirty(struct inode *inode, int flags)
{
 
if (unlikely(block_dump))
block_dump___mark_inode_dirty(inode);
 
}
 
static noinline void block_dump___mark_inode_dirty(struct inode *inode)
{
if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) {
struct dentry *dentry;
const char *name = "?";
 
dentry = d_find_alias(inode);
if (dentry) {
spin_lock(&dentry->d_lock);
name = (const char *) dentry->d_name.name;
}
printk(KERN_DEBUG
"%s(%d): dirtied inode %lu (%s) on %sn",
current->comm, task_pid_nr(current), inode->i_ino,
name, inode->i_sb->s_id);
if (dentry) {
spin_unlock(&dentry->d_lock);
dput(dentry);
}
}

三、总结

1.内核由很多合适的关口来截获获取的IO信息,不改动内核,也可以用jprobe抢劫很多东西。

2.debugfs在大量的block–>file转换过程总太慢,自己用ext2fs写一个,效率应该能提高很多。

—结束—

block_dump观察Linux IO写入的具体文件OenHan

http://www.oenhan.com/block-dump-linux-io

[root@server-mysql log]# echo 5 > /proc/sys/vm/block_dump

[root@server-mysql log]# dmesg -c |grep mysqld
mysqld(11780): dirtied inode 1069049 (ib_logfile0) on sda3
mysqld(11780): dirtied inode 1069049 (ib_logfile0) on sda3
mysqld(11780): WRITE block 8236616 on sda3
mysqld(9674): dirtied inode 1069048 (ibdata1) on sda3
mysqld(9674): dirtied inode 1069048 (ibdata1) on sda3
mysqld(9674): WRITE block 8144896 on sda3
mysqld(9674): WRITE block 8144904 on sda3
mysqld(9674): WRITE block 8144912 on sda3
mysqld(9674): WRITE block 8144920 on sda3
mysqld(9674): WRITE block 8144928 on sda3
mysqld(9674): WRITE block 8144936 on sda3
mysqld(9674): WRITE block 8144944 on sda3
mysqld(9674): WRITE block 8144952 on sda3
mysqld(9674): dirtied inode 1071023 (kk.ibd) on sda3
mysqld(9674): dirtied inode 1071023 (kk.ibd) on sda3
mysqld(9663): WRITE block 32762104 on sda3
mysqld(9663): WRITE block 32762112 on sda3
mysqld(9663): WRITE block 32762120 on sda3
mysqld(9663): WRITE block 32762128 on sda3
mysqld(9663): WRITE block 16177376 on sda3
mysqld(9663): WRITE block 16177384 on sda3
mysqld(9663): WRITE block 16177392 on sda3
mysqld(9663): WRITE block 16177400 on sda3
mysqld(9658): WRITE block 8175616 on sda3


block_dump观察Linux IO写入的具体文件(mysqld)的更多相关文章

  1. linux 日志写入到指定文件中

    php  /data/xxx/aaa.php > test.log 2>&1 >覆盖, >>追加 2>&1 表示不仅命令行正常的输出保存到test. ...

  2. <实训|第十一天>学习一下linux中的进程,文件查找,文件压缩与IO重定向

    [root@localhost~]#序言 在今后的工作中,运维工程师每天的例行事务就是使用free -m,top,uptime,df -h...每天都要检查一下服务器,看看是否出现异常.那么今天我们就 ...

  3. Java基础知识强化之IO流笔记52:IO流练习之 把一个文件中的字符串排序后再写入另一个文件案例

    1. 把一个文件中的字符串排序后再写入另一个文件 已知s.txt文件中有这样的一个字符串:"hcexfgijkamdnoqrzstuvwybpl" 请编写程序读取数据内容,把数据排 ...

  4. linux 利用cat写入一段文件

    linux 利用cat写入一段文件 cat >> /etc/rc.local <<EOFsysctl -w net.ipv4.icmp_echo_ignore_all=1sys ...

  5. 如何在屏幕上查看命令的输出以及在Linux中写入文件

    在Linux中输出命令可以做很多事情(http://www.nanke0834.com) 您可以将命令的输出分配给变量,将其发送到另一个命令/程序以通过管道进行处理或将其重定向到文件以进行进一步分析. ...

  6. Linux IO模型和网络编程模型

    术语概念描述: IO有内存IO.网络IO和磁盘IO三种,通常我们说的IO指的是后两者. 阻塞和非阻塞,是函数/方法的实现方式,即在数据就绪之前是立刻返回还是等待. 以文件IO为例,一个IO读过程是文件 ...

  7. linux IO诊断命令集

    IO.sh ##iostat是查看磁盘活动统计情况 ##显示全部设备负载情况 r/s: 每秒完毕的读 I/O 设备次数.即 rio/s:w/s: 每秒完毕的写 I/O 设备次数.即 wio/s等 io ...

  8. Linux驱动开发常用头文件

    头文件目录中总共有32个.h头文件.其中主目录下有13个,asm子目录中有4个,linux子目录中有10个,sys子目录中有5个.这些头文件各自的功能如下: 1.主目录 <a.out.h> ...

  9. linux io优化

    场景:xml文件解析入库:并备份 问题:磁盘io异常,经常100%busy: linux io优化方法: 1.修改磁盘挂着参数,修改为writeback模式:对于文件读取频繁的可以设置noatime: ...

随机推荐

  1. Android 自定义seekbar中,thumb被覆盖掉一部分问题

    (图一)  (图二)    (图三) 做一个自定义的seekbar,更改其背景图片: <com.android.Progress android:id="@+id/focus_seek ...

  2. mysql select count(filed) 问题(where条件没有数据匹配的话也有数据返回)。

    问题: SELECT count(*),user_id FROM tb_rp_logintrace WHERE id=-1 返回结果: count(*), user_id 0             ...

  3. CreateObject("Wscript.Shell")用法

    WScript.Shell是WshShell对象的ProgID,创建WshShell对象可以运行程序.操作注册表.创建快捷方式.访问系统文件夹.管理环境变量. 该对象有一个run方法. Run 方法创 ...

  4. 【HDOJ】1058 Humble Numbers

    简单题,注意打表,以及输出格式.这里使用了可变参数. #include <stdio.h> #define MAXNUM 5845 #define ANS 2000000000 int b ...

  5. Pizza pieces

    Pizza pieces Description In her trip to Italy, Elizabeth Gilbert made it her duty to eat perfect piz ...

  6. 结构体typedef struct dtuple_struct dtuple_t;

    /** Structure for an SQL data tuple of fields (logical record) */ struct dtuple_struct { ulint info_ ...

  7. linux 系统获取网络ip, mask, gateway, dns信息小程序

    net_util.c #define WIRED_DEV                   "eth0"     #define WIRELESS_DEV             ...

  8. Eclipse反编译插件: Jodeclipse与JadClipse

    Eclipse反编译插件: Jodeclipse与JadClipse Jodeclipse 是Jode的Eclipse插件,JadClipse是Jad的Eclipse插件,它们都是非常好的反编译插件. ...

  9. SQL Server触发器以及如何在SQL Server Manager中调试触发器

    ·只有inserted表有数据时,当前操作为insert:·inserted和deleted两张表都有数据时,当前操作为update:·只有deleted表有数据时,当前操作为delete. 1. C ...

  10. wuzhicms后台菜单的添加

    红色部分都是从菜单管理处添加而来.只有少数是自定义的. 开发一个模块,首先就是菜单的管理.而,不需要的功能也可以在在菜单管理处隐藏或删除. 添加菜单: