zoukankan      html  css  js  c++  java
  • atop 分析小记

    atop分析小记

    1. atop这个工具相当NB
    2. 项目中需要用到它的磁盘使用率统计值,为了一探究竟,挖了下它的代码

    atopsar

    atopsar实际就是atop的一个链接指向。
    从atop.c的main源码可以看到

    int
    main(int argc, char *argv[])
    {
        char *p;
        if ((p = strrchr(argv[0], '/')))
            p++;
        else
            p = argv[0];
    
        if (memcmp(p, "atopsar", 7) == 0)
            return atopsar(argc, argv);
    }
    

    源码编译

    实际读起代码来,还比较繁琐,为了快速找到我关注的东西,考虑干脆自己编译一份可执行文件,然后通过gdb单步跟踪,一步到位。

    可惜实际结果并不是很理想,还是坑了好一会儿……

    源码编译步骤

    虽然README介绍的相当干练:

    For interactive use, it is sufficient to install ATOP with the command
    (as root):
    
    	make systemdinstall
    
    		or
    
    	make sysvinstall
    

    可惜我make直接报错(大意如此):

    no rule to make version.h needed by version.c ...
    

    发现需要通过mkversion脚本生成 version.h,
    实际,项目需要的 version.c 也木有。

    附上我的

    // version.h
    #define	ATOPVERS	"ATOP3"
    #define	ATOPDATE	"2017/07/18 22:24:58"
    
    //version.c
    char        *getstrvers(void) {
        return "Version 3.2.0";
    }
    unsigned short  getnumvers(void) {
            return (0x1313);
    }
    

    第二件坑爹的事情

    虽然README提到这句,可是,它完全没提是必须的啊。
    我想偷个懒,直接注释相关引用,却发现进了另一个坑。
    最后老实下载了这个包,注意官网提供的netatop对内核有要求,
    我为了匹配内核版本号,下载了netatop-0.3.tar.gz

    The kernel module 'netatop' can be downloaded and installed separately from www.atoptool.nl/downloadnetatop.php

    第三件事

    netatop-0.3.tar.gz 下载好了,解压缩后,一定要重命名到Netatop.

    主要原因是: atop源码里面的两个依赖文件是做了链接的。。。

    lrwxrwxrwx 1 ubuntu ubuntu     21 Mar 24 15:54 netatopd.h -> ../Netatop/netatopd.h
    lrwxrwxrwx 1 ubuntu ubuntu     20 Mar 24 15:54 netatop.h -> ../Netatop/netatop.h
    

    编译

    修改 Makefile

    CFLAGS  += -O2 -I.
    # 改成
    CFLAGS  += -O0 -g -I.
    

    编译 make

    源码小小分析

    一路从 main函数追踪的话,大概是这么一条路

    main() -> atopsar() -> engine()
    -> reportheader()
    -> photosyst()
    

    主要的逻辑在 photosyst 这个函数里。

    里面罗列了读取系统的各种信息。

    CPU,内存,磁盘,网络、、、

    我关注的地方

        // 这里是实际读取磁盘信息的部分
        // 实际是读取了 /proc/diskstats文件
    	/*
    	** check if disk-statistics are provided (kernel 2.6 onwards)
    	*/
    	if ( (fp = fopen("diskstats", "r")) != NULL)
    	{
    		char 		diskname[256];
    		struct perdsk	tmpdsk;
    
    		si->dsk.ndsk = 0;
    		si->dsk.nmdd = 0;
    		si->dsk.nlvm = 0;
    
    		while ( fgets(linebuf, sizeof(linebuf), fp) )
    		{
    			nr = sscanf(linebuf,
    			      "%d %d %255s %lld %*d %lld %*d "
    			      "%lld %*d %lld %*d %*d %lld %lld",
    				&major, &minor, diskname,
    				&tmpdsk.nread,  &tmpdsk.nrsect,
    				&tmpdsk.nwrite, &tmpdsk.nwsect,
    				&tmpdsk.io_ms,  &tmpdsk.avque );
    
    			/*
    			** check if this line concerns the entire disk
    			** or just one of the partitions of a disk (to be
    			** skipped)
    			*/
    			if (nr == 9)	/* full stats-line ? */
    			{
    				switch ( isdisk(major, minor, diskname,
    							 &tmpdsk, MAXDKNAM) )
    				{
    				   case NONTYPE:
    				       continue;
    
    				   case DSKTYPE:
    					if (si->dsk.ndsk < MAXDSK-1)
    					  si->dsk.dsk[si->dsk.ndsk++] = tmpdsk;
    					break;
    
    				   case MDDTYPE:
    					if (si->dsk.nmdd < MAXMDD-1)
    					  si->dsk.mdd[si->dsk.nmdd++] = tmpdsk;
    					break;
    
    				   case LVMTYPE:
    					if (si->dsk.nlvm < MAXLVM-1)
    					  si->dsk.lvm[si->dsk.nlvm++] = tmpdsk;
    					break;
    				}
    			}
    		}
    
    		/*
     		** set terminator for table
     		*/
    		si->dsk.dsk[si->dsk.ndsk].name[0] = '';
    		si->dsk.mdd[si->dsk.nmdd].name[0] = '';
    		si->dsk.lvm[si->dsk.nlvm].name[0] = ''; 
    
    		fclose(fp);
    	}
    
    
    static struct {
    	char 	*regexp;
    	regex_t	compreg;
    	void	(*modname)(unsigned int, unsigned int,
    				char *, struct perdsk *, int);
    	int	retval;
    } validdisk[] = {
    	{ "^ram[0-9][0-9]*$",			{0},  (void *)0,   NONTYPE, },
    	{ "^loop[0-9][0-9]*$",			{0},  (void *)0,   NONTYPE, },
    	{ "^sd[a-z][a-z]*$",			{0},  nullmodname, DSKTYPE, },
    	{ "^dm-[0-9][0-9]*$",			{0},  lvmmapname,  LVMTYPE, },
    	{ "^md[0-9][0-9]*$",			{0},  nullmodname, MDDTYPE, },
    	{ "^vd[a-z][a-z]*$",                    {0},  nullmodname, DSKTYPE, },
    	{ "^hd[a-z]$",				{0},  nullmodname, DSKTYPE, },
    	{ "^rd/c[0-9][0-9]*d[0-9][0-9]*$",	{0},  nullmodname, DSKTYPE, },
    	{ "^cciss/c[0-9][0-9]*d[0-9][0-9]*$",	{0},  nullmodname, DSKTYPE, },
    	{ "^fio[a-z][a-z]*$",			{0},  nullmodname, DSKTYPE, },
    	{ "/host.*/bus.*/target.*/lun.*/disc",	{0},  abbrevname1, DSKTYPE, },
    	{ "^xvd[a-z][a-z]*[0-9]*$",		{0},  nullmodname, DSKTYPE, },
    	{ "^dasd[a-z][a-z]*$",			{0},  nullmodname, DSKTYPE, },
    	{ "^mmcblk[0-9][0-9]*$",		{0},  nullmodname, DSKTYPE, },
    	{ "^emcpower[a-z][a-z]*$",		{0},  nullmodname, DSKTYPE, },
    };
    
    
    // isdisk 通过预设的正则表达式过滤规则
    // 判断 /proc/diskstats 里的信息到底是不是磁盘
    // 正则在上文列出
    static int
    isdisk(unsigned int major, unsigned int minor,
               char *curname, struct perdsk *px, int maxlen)
    {
    	static int	firstcall = 1;
    	register int	i;
    
    	if (firstcall)		/* compile the regular expressions */
    	{
    		for (i=0; i < sizeof validdisk/sizeof validdisk[0]; i++)
    			regcomp(&validdisk[i].compreg, validdisk[i].regexp,
    								REG_NOSUB);
    		firstcall = 0;
    	}
    
    	/*
    	** try to recognize one of the compiled regular expressions
    	*/
    	for (i=0; i < sizeof validdisk/sizeof validdisk[0]; i++)
    	{
    		if (regexec(&validdisk[i].compreg, curname, 0, NULL, 0) == 0)
    		{
    			/*
    			** name-string recognized; modify name-string
    			*/
    			if (validdisk[i].retval != NONTYPE)
    				(*validdisk[i].modname)(major, minor,
    						curname, px, maxlen);
    
    			return validdisk[i].retval;
    		}
    	}
    
    	return NONTYPE;
    }
    
  • 相关阅读:
    台州 OJ 3847 Mowing the Lawn 线性DP 单调队列
    洛谷 OJ P1417 烹调方案 01背包
    快速幂取模
    台州 OJ 2649 More is better 并查集
    UVa 1640
    UVa 11971
    UVa 10900
    UVa 11346
    UVa 10288
    UVa 1639
  • 原文地址:https://www.cnblogs.com/morya/p/7203503.html
Copyright © 2011-2022 走看看