我一直在通过net / core / dev.c和其他文件来查看如何获取当前configuration的networking设备列表,这certificate有点难以find。
最终目标是能够使用dev.c中的dev_get_stats获取networking设备统计信息,但是我需要知道当前的接口,所以我可以抓取net_device结构来传入。我必须在内核中执行此操作,因为我写了一个模块,它添加了一个新的/ proc /入口,这涉及到一些来自当前networking设备的统计信息,所以从我能收集到的信息必须在内核中完成。
如果有人能指点我如何获得接口,将不胜感激。
这应该是诀窍:
#include <linux/netdevice.h> struct net_device *dev; read_lock(&dev_base_lock); dev = first_net_device(&init_net); while (dev) { printk(KERN_INFO "found [%s]\n", dev->name); dev = next_net_device(dev); } read_unlock(&dev_base_lock);
给定一个struct net *net
标识您感兴趣的网络名称空间,您应该获取dev_base_lock
并使用for_each_netdev()
:
read_lock(&dev_base_lock); for_each_netdev(net, dev) { /* Inspect dev */ } read_unlock(&dev_base_lock);
(在较新的内核中,可以使用RCU,但在这种情况下可能是过度复杂化)。
要获得要使用的net
名称空间,您应该使用register_pernet_subsys()
注册您的proc
文件:
static const struct file_operations foostats_seq_fops = { .owner = THIS_MODULE, .open = foostats_seq_open, .read = seq_read, .llseek = seq_lseek, .release = foostats_seq_release, }; static int foo_proc_init_net(struct net *net) { if (!proc_net_fops_create(net, "foostats", S_IRUGO, &foostats_seq_fops)) return -ENOMEM; return 0; } static void foo_proc_exit_net(struct net *net) { proc_net_remove(net, "foostats"); } static struct pernet_operations foo_proc_ops = { .init = foo_proc_init_net, .exit = foo_proc_exit_net, }; register_pernet_subsys(&foo_proc_ops)
在你的foostats_seq_open()
函数中,你在net
命名空间中引用一个引用,并将其放在release函数中:
static int foostats_seq_open(struct inode *inode, struct file *file) { int err; struct net *net; err = -ENXIO; net = get_proc_net(inode); if (net == NULL) goto err_net; err = single_open(file, foostats_seq_show, net); if (err < 0) goto err_open; return 0; err_open: put_net(net); err_net: return err; } static int foostats_seq_release(struct inode *inode, struct file *file) { struct net *net = ((struct seq_file *)file->private_data)->private; put_net(net); return single_release(inode, file); }
然后foostats_seq_show()
函数可以获取net
,走设备,收集统计信息并生成输出:
static int sockstat6_seq_show(struct seq_file *seq, void *v) { struct net *net = seq->private; struct net_device *dev; int foostat, barstat; read_lock(&dev_base_lock); for_each_netdev(net, dev) { /* Inspect dev */ } read_unlock(&dev_base_lock); seq_printf(seq, "Foo: %d\n", foostat); seq_printf(seq, "Bar: %d\n", barstat); return 0; }