获取 Linux 内核中的网络设备列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4494307/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting list of network devices inside the Linux kernel
提问by Peter Murfitt
I've been looking through net/core/dev.c and other files to try to find out how to get the list of network devices that are currently configured and it's proving to be a little difficult to find.
我一直在浏览 net/core/dev.c 和其他文件,试图找出如何获取当前配置的网络设备列表,但事实证明它有点难以找到。
The end goal is to be able to get network device statistics using dev_get_stats in dev.c, but I need to know the current interfaces so I can grab the net_device struct to pass in. I'm having to do this inside the kernel as I'm writing a module which adds in a new /proc/ entry which relates to some statistics from the current network devices so from what I can gather this must be done inside the kernel.
最终目标是能够在 dev.c 中使用 dev_get_stats 获取网络设备统计信息,但我需要知道当前的接口,以便我可以获取 net_device 结构来传入。我必须在内核中执行此操作,因为我正在编写一个模块,该模块添加了一个新的 /proc/ 条目,该条目与当前网络设备的一些统计信息相关,因此从我收集到的信息来看,这必须在内核中完成。
If someone could point me to how to get the interfaces it would be much appreciated.
如果有人能指出我如何获得接口,我将不胜感激。
采纳答案by eater
This ought to do the trick:
这应该可以解决问题:
#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);
回答by caf
Given a struct net *net
identifying the net namespace that you are interested in, you should grab the dev_base_lock
and use for_each_netdev()
:
给定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);
(In newer kernels, you can use RCU instead, but that is probably an overcomplication in this case).
(在较新的内核中,您可以改用 RCU,但在这种情况下这可能过于复杂)。
To obtain the net
namespace to use, you should be registering your proc
file with register_pernet_subsys()
:
要获取net
要使用的命名空间,您应该使用以下命令注册您的proc
文件register_pernet_subsys()
:
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)
In your foostats_seq_open()
function, you take a reference on the net
namespace, and drop it in the release function:
在你的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);
}
The foostats_seq_show()
function can then obtain the net
, walk the devices, gather the statistics and produce the output:
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;
}