前面讲到,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
阅读(1235) | 评论(0) | 转发(0) |