文档章节

iopp替换iotop工具

我爱吃葱花
 我爱吃葱花
发布于 2016/10/08 12:29
字数 1633
阅读 228
收藏 1

复制下面代码 iopp.cc

然后放到服务器上,gcc -o iopp iopp.c 编译一下

运行  ./iopp -i -k -c 1 > io.log 这个命令就可以把实时的io信息打印出来啦

打印出来的各项含义:

  • pid 进程ID
  • rchar 将要从磁盘读取的字节数
  • wchar 已经写入或应该要写入磁盘的字节数
  • syscr 读I/O数
  • syscw 写I/O数
  • rbytes 真正从磁盘读取的字节数
  • wbytes 真正写入到磁盘的字节数
  • cwbytes 因为清空页面缓存而导致没有发生操作的字节数
  • command 执行的命令

代码如下:

#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;  
}  

程序git地址:git@code.csdn.net:snippets/406028.git

代码地址:https://code.csdn.net/snippets/406028#nogo

本文转载自:http://blog.csdn.net/hytfly/article/details/34496695

上一篇: Redis连接数异常
下一篇: 排序算法
我爱吃葱花
粉丝 28
博文 132
码字总数 35266
作品 0
海淀
数据库管理员
私信 提问
Iotop 0.6 发布,硬盘操作查看工具

Iotop 0.6 主要修复某些情况下退出程序导致空循环的 bug,安装脚本使用 sbin 目录替换 bin 目录。 如果你知道有程序在磨你的硬盘,但是你又不能确定是哪一个程序在磨你的硬盘,那么就用 ioto...

oschina
2013/05/28
1K
1
磁盘I/O高居不下,通过什么来查看占用I/O的进程?

iotop命令是一个用来监视磁盘I/O使用状况的top类工具。iotop具有与top相似的UI,其中包括PID、用户、I/O、进程等相关信息。Linux下的IO统计工具如iostat,nmon等大多数是只能统计到per设备的...

oldchild_qs
2018/06/29
0
0
logrotate故障排除分享:使用copytruncate轮询日志文件

我使用iotop工具定期抓取本地的io统计数据,通过zabbix客户端的key发送给zabbix服务器。这样就可以在zabbix上实时看到所有服务器的io数据了。在使用过程中发现。存放io数据的文件iotop.log增...

swanor
2016/03/21
0
0
Linux系统管理——进程和计划任务

1、进程 进程的管理是内核的重要功能之一,了解和熟练的完成进程管理是系统安全、性能效率优化的基础。 1.1、进程的性能及功能 内核的功用: 进程管理、文件系统、网络功能、内存管理、驱动程...

烽火狼烟_Gk
2018/01/31
0
0
硬盘操作查看工具--iotop

如果你知道有程序在磨你的硬盘,但是你又不能确定是哪一个程序在磨你的硬盘,那么就用 iotop来帮助你吧。 在Ubuntu里安装命令是: sudo apt-get install iotop 安装好之后在终端输入:iotop...

匿名
2009/06/17
18.1K
0

没有更多内容

加载失败,请刷新页面

加载更多

八、RabbitMQ的集群原理

集群架构 写在前面 RabbitMQ集群是按照低延迟环境设计的,千万不要跨越WAN或者互联网来搭建RabbitMQ集群。如果一定要在高延迟环境下使用RabbitMQ集群,可以参考使用Shovel和Federation工具。...

XuePeng77
今天
1
0
mac系统下,brew 安装mysql,用终端可以连接,navicat却连接不上?

问题: 1.报错? 2059 - Authentication plugin 'caching_sha2_password' cannot be loaded: dlopen(../Frameworks/caching_sha2_password.so, 2): image not found 2.自己通过设置,已经把密......

写bug的攻城狮
昨天
2
0
老生常谈,HashMap的死循环

问题 最近的几次面试中,我都问了是否了解HashMap在并发使用时可能发生死循环,导致cpu100%,结果让我很意外,都表示不知道有这样的问题,让我意外的是面试者的工作年限都不短。 由于HashMap...

群星纪元
昨天
5
0
拉普拉斯算子

拉普拉斯算子是二阶微分算子。 我们知道,一维离散信号一阶微分公式如下: 相应的,一维离散信号二阶微分公式如下: 由于图像有x和y两个方向,因此图像信号属于二维离散信号。其在x,y两个...

yepanl
昨天
3
0
记录"正则表达式"

详细请查看我的博客:https://blog.enjoytoshare.club/article/RegularExpression.html 1 写在前面 正则表达式(Regular Expression)在代码中常常简写为regex。正则表达式通常被用来检索、替...

wugenqiang
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部