ifstat源码阅读

本代码使用的是ifstat-1.1版本,在此基础上进行了简化修改,直接获取当前设备所有网卡的信息。代码已经没有了源码的模样,已经被修改的面目全非,仅仅是通过代码了解一下获取网络流量的方法。基本方法是通过两次读取/proc/net/dev(ifstat网络流量监控之/proc/net/dev文件)文件计算时间差来计算IO流量。

扫描设备的网卡用到了if_nameindex()系列函数,代码中给出了详细的注释。同时还可以上网去了解更详细的信息。

 

#include <unistd.h>
#include <string.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <errno.h>

#define PROC_FILE_PATH "/proc/net/dev"
/* interface flags */
#define IFSTAT_LOOPBACK 1
#define IFSTAT_DOWN     2
#define IFSTAT_HASSTATS 4
#define IFSTAT_HASINDEX 8
#define IFSTAT_TOTAL  128

/*网卡列表*/
struct ifstat_data 
{
    char *name;
    int namelen;
    unsigned long obout, obin, bout, bin;
    int flags;
    struct ifstat_data *next;
};

struct ifstat_list 
{
    struct ifstat_data *first;
    int flags;
};

/*设备数据*/
struct ifstat_driver
{
    char *name;
    /*驱动设备初始化,成功返回1*/
    int (*open_driver) (struct ifstat_driver *driver);
    /*扫描设备列表*/
    int (*scan_interfaces) (struct ifstat_driver *driver,struct ifstat_list *ifs);
    /*收集信息,并更新列表*/
    int (*get_stats) (struct ifstat_driver *driver,struct ifstat_list *ifs);
    /*关闭设备数据获取*/
    void (*close_driver) (struct ifstat_driver *driver);
    /*私有数据*/
    void *data;
};

struct proc_driver_data 
{
    char *file;
    int checked;
};


//重置标志信息
void ifstat_reset_interfaces(struct ifstat_list *ifs) 
{
    struct ifstat_data *ptr;
    int hasindex = 1;

    for (ptr = ifs->first; ptr != NULL; ptr = ptr->next) 
    {
        if (!(ptr->flags & IFSTAT_HASINDEX))
            hasindex = 0;
        ptr->flags &= ~(IFSTAT_HASSTATS|IFSTAT_HASINDEX);
    }
    if (hasindex)
        ifs->flags |= IFSTAT_HASINDEX;
    else
        ifs->flags &= ~IFSTAT_HASINDEX;
}

void ifstat_add_interface(struct ifstat_list *ifs, char *ifname, int flags) 
{
    struct ifstat_data *cur, *last;
    int len;

    /*检查网卡名称*/
    if (*ifname == '\0')
        return;
    len = strlen(ifname);

    last = NULL;
    for (cur = ifs->first; cur != NULL; cur = cur->next)
    {
        if (len == cur->namelen && cur->name[0] == ifname[0] &&
            !strncmp(cur->name + 1, ifname + 1, len - 1) &&
            !(flags & IFSTAT_TOTAL) && !(cur->flags & IFSTAT_TOTAL))
            return;
        last = cur;
    }

    if ((cur = calloc(1, sizeof(struct ifstat_data))) == NULL) 
    {
        printf("[%s %d]malloc error\n",__FUNCTION__,__LINE__);
        exit(EXIT_FAILURE);
    }
    cur->name = strdup(ifname);
    cur->namelen = len;
    cur->flags = flags;
    if (last != NULL)
        last->next = cur;
    if (ifs->first == NULL)
        ifs->first = cur;
}


void ifstat_free_interface(struct ifstat_data *data) 
{
    free(data->name);
    free(data);
}


struct ifstat_data *ifstat_get_interface(struct ifstat_list *ifs, char *ifname)
{
    struct ifstat_data *ptr;
    int len = strlen(ifname);

    for (ptr = ifs->first; ptr != NULL; ptr = ptr->next)
    {
        if (len == ptr->namelen && ptr->name[0] == ifname[0] &&
            !strncmp(ptr->name + 1, ifname + 1, len - 1) &&
            !(ptr->flags & IFSTAT_TOTAL))
        {
            return ptr;
        }
    }
    return NULL;
}

void ifstat_set_interface_stats(struct ifstat_data *data,
												unsigned long bytesin,
												unsigned long bytesout)
{
    if (data->bout > bytesout || data->bin > bytesin) 
    {
        printf("[%s %d]warning: rollover for interface %s, reinitialising\n",__FUNCTION__,__LINE__, data->name);
        data->obout = bytesout;
        data->obin = bytesin;
    } 
    else
    {
        data->obout = data->bout;
        data->obin = data->bin;
    }
    data->bout = bytesout;
    data->bin = bytesin;
    data->flags |= IFSTAT_HASSTATS;
}


static void examine_interface(struct ifstat_list *ifs, char *name,int ifflags) 
{
    if ((ifflags & IFF_LOOPBACK) && !(ifs->flags & IFSTAT_LOOPBACK))
        return;
    if (!(ifflags & IFF_UP) && !(ifs->flags & IFSTAT_DOWN))
        return;
    ifstat_add_interface(ifs, name, 0);
}

static int ioctl_map_ifs(int sd,int (*mapf)(int sd, struct ifreq *ifr, void *data),void *mdata) 
{
	/*******************************************函数调用说明*************************************************
	if_nametoindex():指定网络接口名称字符串作为参数;
					  若该接口存在,则返回相应的索引,
					  否则返回0
	if_indextoname():指定网络接口索引以及一块长度至少为IF_NAMESIZE(16)字节的内存区域作为参数;
					  若索引对应的网络接口存在,则在内存区域中返回该接口的名称字符串,
					  否则返回NULL,并将errno设置为相应的值
	if_nameindex():返回动态分配的struct if_nameindex结构数组,数组中的每一个元素分别对应一个本地网络接口;
	struct if_nameindex结构的if_index字段为接口索引,if_name字段为接口名称字符串;
						索引为0且名称字符串为NULL表示结构数组的末尾;
						调用出错时,返回NULL,并将errno设置为相应的值
	if_freenameindex():通过if_nameindex()获取完毕接口名称与索引后,调用该函数以释放动态分配的内存区域。
	以上4个函数在系统的man文档中都可以查看相应的描述,且都是POSIX标准支持的,Linux内核可能未实现这些函数,
	或已实现但不同于POSIX标准。这些函数的原型声明与定义并未出现在CentOS 6.7的定制内核2.6.32-573.26.1.el6.x86_64
	以及原版内核2.6.32.5中,而是由系统的glibc-2.12实现:在glibc-2.12.2源码树中,
	函数的原型声明位于sysdeps/gnu/net/if.h与sysdeps/generic/net/if.h,
	函数的定义位于sysdeps/unix/sysv/linux/if_index.c中,
	本质上是对ioctl(2)的SIOCGIFNAME,SIOCGIFCONF,SIOCGIFINDEX等操作以及netlink套接字进行了封装
	************************************************************************************************************/
    struct if_nameindex *iflist, *cur;
    struct ifreq ifr;
    if ((iflist = if_nameindex()) == NULL) 
    {
        printf("[%s %d]if_nameindex error\n",__FUNCTION__,__LINE__);
        return 0;
    }

    for(cur = iflist; cur->if_index != 0 && cur->if_name != NULL; cur++) 
    {
        memcpy(ifr.ifr_name, cur->if_name, sizeof(ifr.ifr_name));
        ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
        if (!mapf(sd, &ifr, mdata))
            return 0;
    }
    if_freenameindex(iflist);
    return 1;
}


static int ioctl_map_scan(int sd, struct ifreq *ifr, void *data) 
{
    if (ioctl(sd, SIOCGIFFLAGS, (char *)ifr) != 0)
        return 1;
    examine_interface((struct ifstat_list *) data, ifr->ifr_name,ifr->ifr_flags);
    return 1;
}

static int ioctl_scan_interfaces(struct ifstat_driver *driver,struct ifstat_list *ifs) 
{
    int sd;

    if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        printf("[%s %d]socket error\n",__FUNCTION__,__LINE__);
        return 0;
    }
    ioctl_map_ifs(sd, &ioctl_map_scan, (void *) ifs);
    close(sd);
    return 1;
} 

static int proc_open_driver(struct ifstat_driver *driver) 
{
    struct proc_driver_data *data;

    if ((data = malloc(sizeof(struct proc_driver_data))) == NULL) 
    {
        printf("[%s %d]malloc error\n",__FUNCTION__,__LINE__);
        return 0;
    }

    data->file = NULL;
    data->checked = 0;
    driver->data = (void *) data;

    return 1;
}

static void proc_close_driver(struct ifstat_driver *driver) 
{
    struct proc_driver_data *data = driver->data;

    if (data->file != NULL)
        free(data->file);
    free(data);
}

static int proc_get_stats(struct ifstat_driver *driver,struct ifstat_list *ifs) 
{
    char buf[1024];
    FILE *f;
    char *iface, *stats;
    unsigned long bytesin, bytesout;
    struct ifstat_data *cur;
    struct proc_driver_data *data = driver->data;
    char *file;
    if (data->file != NULL)
        file = data->file;
    else
        file = PROC_FILE_PATH;

    if ((f = fopen(file, "r")) == NULL)
    {
        printf("[%s %d]can't open %s: %s\n",__FUNCTION__,__LINE__, file, strerror(errno));
        return 0;
    }

    /*检查首行*/
    if (fgets(buf, sizeof(buf), f) == NULL)
        goto badproc;
    if (!data->checked && strncmp(buf, "Inter-|", 7))
        goto badproc;
    if (fgets(buf, sizeof(buf), f) == NULL)
        goto badproc;
    if (!data->checked)
    {
        if (strncmp(buf, " face |by", 9))
            goto badproc;
        data->checked = 1;
    }

    while (fgets(buf, sizeof(buf), f) != NULL) 
    {
        if ((stats = strchr(buf, ':')) == NULL)
            continue;
        *stats++ = '\0';
        iface = buf;
        while (*iface == ' ')
            iface++;
        if (*iface == '\0')
            continue;
        if (sscanf(stats, "%lu %*u %*u %*u %*u %*u %*u %*u %lu %*u", &bytesin, &bytesout) != 2)
            continue;

        if ((cur = ifstat_get_interface(ifs, iface)) != NULL)
            ifstat_set_interface_stats(cur, bytesin, bytesout);
    }
    fclose(f);
    return 1;

badproc:
    fclose(f);
    printf("[%s %d]%s: unsupported format\n",__FUNCTION__,__LINE__, file);
    return 0;
}


int ifstat_get_driver(struct ifstat_driver *driver) 
{
    static struct ifstat_driver drivers[] = 
    {
        {
			"proc", 
			&proc_open_driver,
			&ioctl_scan_interfaces,
			&proc_get_stats,
			&proc_close_driver
		},
        {NULL} 
    };
    
    if (drivers[0].name == NULL)
        return 0;
    memcpy(driver, &(drivers[0]), sizeof(struct ifstat_driver));
    driver->data = NULL;
    return 1;
}

  
/*
        eth0                  lo
  KB/s in  KB/s out    KB/s in  KB/s out
 14562.23  12345.25       0.00      0.00
*/			 
static void print_stats(struct ifstat_list *ifs,struct timeval *start,struct timeval *end)
{
    struct ifstat_data *ptr;
    int hasindex = 1;
    double delay, kbin, kbout, tkbin, tkbout, scale;

    delay = end->tv_sec - start->tv_sec + ((double) (end->tv_usec - start->tv_usec))/ (double) 1000000;
    scale = delay * 1024;

    tkbin = tkbout = 0;
    for (ptr = ifs->first; ptr != NULL; ptr = ptr->next) 
    {
        if (ptr->flags & IFSTAT_HASSTATS)
        {
            kbin = (double) (ptr->bin - ptr->obin) / (double) scale;
            tkbin += kbin;
            kbout = (double) (ptr->bout - ptr->obout) / (double) scale;
            tkbout += kbout;
            ptr->flags &= ~IFSTAT_HASSTATS;
        } 
        else if (ptr->flags & IFSTAT_TOTAL)
        {
            kbin = tkbin;
            kbout = tkbout;
        } 
        else
        {
            kbin = -1;
            kbout = -1;
        }

        if (ptr->flags & IFSTAT_HASINDEX)
            ptr->flags &= ~IFSTAT_HASINDEX;
        else
            hasindex = 0;

        if (kbin < 0)
            kbin = 0;

        if (kbout < 0)
            kbout = 0;

        printf("name:%s\tkbin:%0.2lfKB\tkout:%0.2lfKB\n",ptr->name,kbin,kbout);
    }

    if (hasindex)
        ifs->flags |= IFSTAT_HASINDEX;
    else
        ifs->flags &= ~IFSTAT_HASINDEX;
}

static void filter_interfaces(struct ifstat_list *ifs)
{
    struct ifstat_data *cur, *next, *parent;
    cur = ifs->first;
    parent = NULL;
    while (cur != NULL) 
    {
        if (!(cur->flags & IFSTAT_HASSTATS)) 
        {
            next = cur->next;
            if (parent != NULL)
                parent->next = next;
            else
                ifs->first = next;
            ifstat_free_interface(cur);
            cur = next;
        }
        else
        {
            parent = cur;
            cur = cur->next;
        }
    }
}


int main(int argc, char **argv)
{
    struct ifstat_list ifs;
    struct ifstat_driver driver;
    struct timeval start, tv_delay, tv;

    ifs.flags = 0;
    ifs.first = NULL;
  
    /*映射接口*/
    if (!ifstat_get_driver(&driver)) 
    {
        return EXIT_FAILURE;
    }

    /*初始化网卡设备*/
    if (driver.open_driver != NULL &&!driver.open_driver(&driver))
        return EXIT_FAILURE;

    if (ifs.first == NULL)
        driver.scan_interfaces(&driver, &ifs);

    /*第一次查询网卡数据*/
    if (ifs.first != NULL) 
    {
        if (driver.get_stats != NULL && !driver.get_stats(&driver, &ifs))
            return EXIT_FAILURE;
        gettimeofday(&start, NULL);//获取当前时间
        filter_interfaces(&ifs);
        ifstat_reset_interfaces(&ifs);
    }
    
    if (ifs.first == NULL) 
    {
        if (driver.close_driver != NULL)
            driver.close_driver(&driver);
        return EXIT_FAILURE;
    }
  
    if (ifs.flags & IFSTAT_TOTAL)
    {
        ifstat_add_interface(&ifs, "Total", IFSTAT_TOTAL);
    }
  
    tv_delay.tv_sec = 1;
    tv_delay.tv_usec = (int) ((1 - tv_delay.tv_sec) * 1000000);
    while(1)  
    {
    	printf("\n###############################################\n");
        tv = tv_delay;
        select(0, NULL, NULL, NULL, &tv);
        if (driver.get_stats != NULL && !driver.get_stats(&driver, &ifs))
            return EXIT_FAILURE;
        gettimeofday(&tv, NULL);
        print_stats(&ifs, &start, &tv);
        start = tv;
        fflush(stdout);
    }

    if (driver.close_driver != NULL)
        driver.close_driver(&driver);

    return EXIT_SUCCESS;
}

代码中涉及到的函数如图所示:

 

程序运行结果如图所示:

###############################################
name:ens2f0     kbin:402.55Kb   kout:6.43Kb
name:ens2f1     kbin:748.04Kb   kout:6.37Kb
name:ens3f0     kbin:0.00Kb     kout:0.00Kb
name:enp4s0f0   kbin:414.43Kb   kout:6.59Kb
name:enp4s0f1   kbin:518.85Kb   kout:6.46Kb
name:ens3f1     kbin:0.00Kb     kout:0.00Kb
name:bond0      kbin:2083.87Kb  kout:25.86Kb

###############################################
name:ens2f0     kbin:536.68Kb   kout:5.01Kb
name:ens2f1     kbin:395.57Kb   kout:5.36Kb
name:ens3f0     kbin:0.00Kb     kout:0.00Kb
name:enp4s0f0   kbin:583.30Kb   kout:5.08Kb
name:enp4s0f1   kbin:162.78Kb   kout:5.15Kb
name:ens3f1     kbin:0.00Kb     kout:0.00Kb
name:bond0      kbin:1678.33Kb  kout:20.60Kb

###############################################
name:ens2f0     kbin:334.01Kb   kout:5.66Kb
name:ens2f1     kbin:664.27Kb   kout:5.88Kb
name:ens3f0     kbin:0.00Kb     kout:0.00Kb
name:enp4s0f0   kbin:569.79Kb   kout:5.62Kb
name:enp4s0f1   kbin:464.94Kb   kout:5.63Kb
name:ens3f1     kbin:0.00Kb     kout:0.00Kb
name:bond0      kbin:2033.00Kb  kout:22.79Kb

###############################################
name:ens2f0     kbin:237.78Kb   kout:5.46Kb
name:ens2f1     kbin:459.81Kb   kout:5.27Kb
name:ens3f0     kbin:0.00Kb     kout:0.00Kb
name:enp4s0f0   kbin:605.53Kb   kout:5.15Kb
name:enp4s0f1   kbin:403.94Kb   kout:5.35Kb
name:ens3f1     kbin:0.00Kb     kout:0.00Kb
name:bond0      kbin:1714.43Kb  kout:21.23Kb

###############################################
name:ens2f0     kbin:432.40Kb   kout:5.66Kb
name:ens2f1     kbin:497.88Kb   kout:5.91Kb
name:ens3f0     kbin:0.00Kb     kout:0.00Kb
name:enp4s0f0   kbin:706.00Kb   kout:6.12Kb
name:enp4s0f1   kbin:409.88Kb   kout:6.02Kb
name:ens3f1     kbin:0.00Kb     kout:0.00Kb
name:bond0      kbin:2038.79Kb  kout:23.71Kb

 

简化一下代码,对于/proc/net/dev文件的读取以及对网络流量数据的监控理解起来会更简洁。

 

#include <unistd.h>
#include <string.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <errno.h>

#define PROC_FILE_PATH "/proc/net/dev"

/*网卡列表*/
struct ifstat_data 
{
    char *name;
    int namelen;
    unsigned long obout, obin, bout, bin;
    struct ifstat_data *next;
};

struct ifstat_data *ifstat_get_interface(struct ifstat_data *ifs, char *ifname)
{
    struct ifstat_data *ptr;
    int len = strlen(ifname);

    for (ptr = ifs; ptr != NULL; ptr = ptr->next)
    {
        if (len == ptr->namelen && ptr->name[0] == ifname[0] &&
            !strncmp(ptr->name + 1, ifname + 1, len - 1))
        {
            return ptr;
        }
    }
    return NULL;
}

void ifstat_set_interface_stats(struct ifstat_data *data,
												unsigned long bytesin,
												unsigned long bytesout)
{
    if (data->bout > bytesout || data->bin > bytesin) 
    {
        printf("[%s %d]warning: rollover for interface %s, reinitialising\n",__FUNCTION__,__LINE__, data->name);
        data->obout = bytesout;
        data->obin = bytesin;
    } 
    else
    {
        data->obout = data->bout;
        data->obin = data->bin;
    }
    data->bout = bytesout;
    data->bin = bytesin;
}

static int ioctl_map_scan(int sd, struct ifreq *ifr, struct ifstat_data **ifs) 
{
    if (ioctl(sd, SIOCGIFFLAGS, (char *)ifr) != 0)
        return 1;

	if ((ifr->ifr_flags & IFF_LOOPBACK))
        return 1;
    if (!(ifr->ifr_flags & IFF_UP))
        return 1;

	struct ifstat_data *cur, *last = NULL;
    /*检查网卡名称*/
    if (*ifr->ifr_name == '\0')
        return 1;
	
    int len = strlen(ifr->ifr_name);
    for (cur = *ifs; cur != NULL; cur = cur->next)
    {
        if (len == cur->namelen && cur->name[0] == ifr->ifr_name[0] &&
            !strncmp(cur->name + 1, ifr->ifr_name + 1, len - 1))
            return 1;
        last = cur;
    }

    if ((cur = calloc(1, sizeof(struct ifstat_data))) == NULL) 
    {
        printf("[%s %d]malloc error\n",__FUNCTION__,__LINE__);
        exit(EXIT_FAILURE);
    }
	
    cur->name = strdup(ifr->ifr_name);
    cur->namelen = len;
    if (last != NULL)
        last->next = cur;
    if (*ifs == NULL)
        *ifs = cur;
    return 1;
}

static int ioctl_scan_interfaces(struct ifstat_data **ifs) 
{
    int sd;
	struct ifstat_data *ifs_temp = NULL;
    if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        printf("[%s %d]socket error\n",__FUNCTION__,__LINE__);
        return 0;
    }
    //ioctl_map_ifs(sd, &ioctl_map_scan, (void *) ifs);

	/*******************************************函数调用说明*************************************************
	if_nametoindex():指定网络接口名称字符串作为参数;
					  若该接口存在,则返回相应的索引,
					  否则返回0
	if_indextoname():指定网络接口索引以及一块长度至少为IF_NAMESIZE(16)字节的内存区域作为参数;
					  若索引对应的网络接口存在,则在内存区域中返回该接口的名称字符串,
					  否则返回NULL,并将errno设置为相应的值
	if_nameindex():返回动态分配的struct if_nameindex结构数组,数组中的每一个元素分别对应一个本地网络接口;
	struct if_nameindex结构的if_index字段为接口索引,if_name字段为接口名称字符串;
						索引为0且名称字符串为NULL表示结构数组的末尾;
						调用出错时,返回NULL,并将errno设置为相应的值
	if_freenameindex():通过if_nameindex()获取完毕接口名称与索引后,调用该函数以释放动态分配的内存区域。
	以上4个函数在系统的man文档中都可以查看相应的描述,且都是POSIX标准支持的,Linux内核可能未实现这些函数,
	或已实现但不同于POSIX标准。这些函数的原型声明与定义并未出现在CentOS 6.7的定制内核2.6.32-573.26.1.el6.x86_64
	以及原版内核2.6.32.5中,而是由系统的glibc-2.12实现:在glibc-2.12.2源码树中,
	函数的原型声明位于sysdeps/gnu/net/if.h与sysdeps/generic/net/if.h,
	函数的定义位于sysdeps/unix/sysv/linux/if_index.c中,
	本质上是对ioctl(2)的SIOCGIFNAME,SIOCGIFCONF,SIOCGIFINDEX等操作以及netlink套接字进行了封装
	************************************************************************************************************/
    struct if_nameindex *iflist, *cur;
    struct ifreq ifr;
    if ((iflist = if_nameindex()) == NULL) 
    {
        printf("[%s %d]if_nameindex error\n",__FUNCTION__,__LINE__);
        return 0;
    }

    for(cur = iflist; cur->if_index != 0 && cur->if_name != NULL; cur++) 
    {
        memcpy(ifr.ifr_name, cur->if_name, sizeof(ifr.ifr_name));
        ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
		
        if (!ioctl_map_scan(sd, &ifr, &ifs_temp))
            return 0;
		*ifs = ifs_temp;
    }
    if_freenameindex(iflist);
    close(sd);
    return 1;
} 

static int proc_get_stats(int *checked,struct ifstat_data *ifs) 
{
    char buf[1024];
    FILE *f;
    char *iface, *stats;
    unsigned long bytesin, bytesout;
    struct ifstat_data *cur;
    if ((f = fopen(PROC_FILE_PATH, "r")) == NULL)
    {
        printf("[%s %d]can't open %s: %s\n",__FUNCTION__,__LINE__, PROC_FILE_PATH, strerror(errno));
        return 0;
    }

    /*检查首行*/
    if (fgets(buf, sizeof(buf), f) == NULL)
        goto badproc;
    if (!*checked && strncmp(buf, "Inter-|", 7))
        goto badproc;
    if (fgets(buf, sizeof(buf), f) == NULL)
        goto badproc;
    if (!*checked)
    {
        if (strncmp(buf, " face |by", 9))
            goto badproc;
        *checked = 1;
    }

    while (fgets(buf, sizeof(buf), f) != NULL) 
    {
        if ((stats = strchr(buf, ':')) == NULL)
            continue;
        *stats++ = '\0';
        iface = buf;
        while (*iface == ' ')
            iface++;
        if (*iface == '\0')
            continue;

        if (sscanf(stats, "%lu %*u %*u %*u %*u %*u %*u %*u %lu %*u", &bytesin, &bytesout) != 2)
            continue;

        if ((cur = ifstat_get_interface(ifs, iface)) != NULL)
            ifstat_set_interface_stats(cur, bytesin, bytesout);
    }
    fclose(f);
    return 1;

badproc:
    fclose(f);
    printf("[%s %d]%s: unsupported format\n",__FUNCTION__,__LINE__, PROC_FILE_PATH);
    return 0;
}

static void print_stats(struct ifstat_data *ifs,struct timeval *start,struct timeval *end)
{
    struct ifstat_data *ptr;
    double delay, kbin, kbout;

    delay = (end->tv_sec - start->tv_sec + ((double) (end->tv_usec - start->tv_usec))/ (double) 1000000)*1024;

    for (ptr = ifs; ptr != NULL; ptr = ptr->next) 
    {
        kbin = (double) (ptr->bin - ptr->obin) / (double) delay;
        kbout = (double) (ptr->bout - ptr->obout) / (double) delay;
        if (kbin < 0)
            kbin = 0;

        if (kbout < 0)
            kbout = 0;

        printf("name:%s\tkbin:%0.2lfKB\tkout:%0.2lfKB\n",ptr->name,kbin,kbout);
    }
}


int main(int argc, char **argv)
{
    struct ifstat_data *ifs = NULL;
	int checked = 0;
    struct timeval start, tv_delay, tv;

    ioctl_scan_interfaces(&ifs);

    /*第一次查询网卡数据*/
    if (ifs != NULL) 
    {
        if (!proc_get_stats(&checked,ifs))
            return -1;
        gettimeofday(&start, NULL);//获取当前时间
    }else
        return -1;
      
    tv_delay.tv_sec = 1;
    tv_delay.tv_usec = (int) ((1 - tv_delay.tv_sec) * 1000000);
    while(1)  
    {
    	printf("\n###############################################\n");
        tv = tv_delay;
        select(0, NULL, NULL, NULL, &tv);
        if (!proc_get_stats(&checked,ifs))
            return -1;
        gettimeofday(&tv, NULL);
        print_stats(ifs, &start, &tv);
        start = tv;
        fflush(stdout);
    }	
    return 0;
}

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值