• 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;
    }
    
  • 相关阅读:
    wqs二分
    FLAG区
    Codeforces | CF1033D 【Divisors】
    Nowcoder | [题解-N210]牛客OI月赛2-提高组
    Codeforces | CF1041F 【Ray in the tube】
    Nowcoder | [题解-N189]牛客OI赛制测试赛3
    Codeforces | CF1029F 【Multicolored Markers】
    Codeforces | CF1037D 【Valid BFS?】
    Codeforces | CF1028C 【Rectangles】
    Codeforces | CF1029C 【Maximal Intersection】
  • 原文地址:https://www.cnblogs.com/morya/p/7203503.html
Copyright © 2020-2023  润新知