Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1881899
  • 博文数量: 376
  • 博客积分: 2147
  • 博客等级: 大尉
  • 技术积分: 3642
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-06 10:47
文章分类

全部博文(376)

文章存档

2019年(3)

2017年(28)

2016年(15)

2015年(17)

2014年(182)

2013年(16)

2012年(115)

我的朋友

分类: LINUX

2012-02-07 14:30:32

前面讲到,register_netdev首先为网络设备接口分配一个名称,然后将dev插入到一个叫做dev_base的网络设备全局链表中。由此我们 不难想到,通过访问dev_base,就可以遍历到系统中的所有网络设备,而每一个网络设备接口都有一个net_device结构来表示。该结构中有一个 成员函数指针:
    struct net_device_stats* (*get_stats)(struct net_device *dev);
它返回一个struct net_device_stats结构,该结构保存了所在网络设备接口的详细的流量统计信息:
    struct net_device_stats
    {
        unsigned long rx_packets; /* total packets received   */
        unsigned long tx_packets; /* total packets transmitted    */
        unsigned long rx_bytes; /* total bytes received     */
        unsigned long tx_bytes; /* total bytes transmitted  */
        unsigned long rx_errors; /* bad packets received     */
        unsigned long tx_errors; /* packet transmit problems */
        unsigned long rx_dropped; /* no space in linux buffers    */
        unsigned long tx_dropped;/* no space available in linux  */
        unsigned long multicast; /* multicast packets received   */
        unsigned long   collisions;

        /* detailed rx_errors: */
        unsigned long rx_length_errors;
        unsigned long rx_over_errors; /* receiver ring buff overflow  */
        unsigned long rx_crc_errors;/* recved pkt with crc error */
        unsigned long rx_frame_errors;/* recv'd frame alignment error */
        unsigned long rx_fifo_errors; /* recv'r fifo overrun      */
        unsigned long rx_missed_errors;/* receiver missed packet  */

    /* detailed tx_errors */
    unsigned long   tx_aborted_errors;
    unsigned long   tx_carrier_errors;
    unsigned long   tx_fifo_errors;
    unsigned long   tx_heartbeat_errors;
    unsigned long   tx_window_errors;

    /* for cslip etc */
    unsigned long   rx_compressed;
    unsigned long   tx_compressed;
};

    OK,有了这些基础知识,我们就可以写一个网络流量统计的内核模块了,这是一个最简单的程序,它每次被插入到内核中时,会在日志文件中打出当前系统上的所 有网络设备接口的传输的和收到的字节数和包数。我们可以把它进一步改造,输出到/proc文件系统,再通过用户空间的一个程序计算单位时间的流量,就成为 一个真正的网络流量统计程序了。
下面是代码:
/* netbase.c
 * helinqiang@hotmail.com
 * 2006-03-14
 */

#include
#include

MODULE_AUTHOR("Linqiang He, Hangzhou China");
MODULE_LICENSE("Dual BSD/GPL");

static int __init netbase_init_module(void)
{
    struct net_device *dev = dev_base;
    struct net_device_stats *stats;
    while( dev != NULL ){
        printk(KERN_INFO "dev name: %s\n", dev->name);
        stats = dev->get_stats(dev);
        printk(KERN_INFO "\ttransmitted bytes: %lu\n", stats->tx_bytes);
        printk(KERN_INFO "\treceived bytes: %lu\n", stats->rx_bytes);
        printk(KERN_INFO "\ttransmitted packets: %lu\n", stats->tx_packets);
        printk(KERN_INFO "\treceived packets: %lu\n", stats->rx_packets);
        dev = dev->next;
    }
    return 0;
}

static void __exit netbase_exit_module(void)
{
}

module_init(netbase_init_module);
module_exit(netbase_exit_module);

下面是在我的电脑上的某一时刻的输出结果:
Mar 14 21:22:34 localhost kernel: dev name: lo
Mar 14 21:22:34 localhost kernel:       transmitted bytes: 4660
Mar 14 21:22:34 localhost kernel:       received bytes: 4660
Mar 14 21:22:34 localhost kernel:       transmitted packets: 61
Mar 14 21:22:34 localhost kernel:       received packets: 61
Mar 14 21:22:34 localhost kernel: dev name: sit0
Mar 14 21:22:34 localhost kernel:       transmitted bytes: 0
Mar 14 21:22:34 localhost kernel:       received bytes: 0
Mar 14 21:22:34 localhost kernel:       transmitted packets: 0
Mar 14 21:22:34 localhost kernel:       received packets: 0
Mar 14 21:22:34 localhost kernel: dev name: eth0
Mar 14 21:22:34 localhost kernel:       transmitted bytes: 437071
Mar 14 21:22:34 localhost kernel:       received bytes: 4046403
Mar 14 21:22:34 localhost kernel:       transmitted packets: 2607
Mar 14 21:22:34 localhost kernel:       received packets: 17773
阅读(1175) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~