Linux内核proc文件系统的冰山一角 源自对/proc/net/dev文件中各网卡参数的疑问

本文主要是介绍Linux内核proc文件系统的冰山一角 源自对/proc/net/dev文件中各网卡参数的疑问,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Linux内核proc文件系统的冰山一角--源自对/proc/net/dev文件中各网卡参数的疑问  

l|字号 订阅

From: http://blog.csdn.net/zhoukejun/archive/2009/05/06/4153266.aspx

最近在调试网卡驱动时一直对/proc/net/dev 文件中各网卡参数是如何得来的有很大的疑问。
insmod 以太网卡驱动后,cat /proc/net/dev 可以看到多了eth0的信息。开始,一直以为是驱动的代码调用某个写/proc文件的函数,从而把eth0的信息写到/proc/net/dev文件里。 可是反复看代码也没有发现相关的函数。今天突然想先拿/proc/interrupt 来分析一下,看了看linux-2.6.28的代码,就有了这篇《Linux内核proc文件系统的冰山一角--源自/proc/net/dev文件中各网卡参数的疑问》。

(一)先分析/proc/interrupts 

linux-2.6.28/arch/arm/kernel/irq.c --> show_interrupt()

在linux-2.6.28/fs/proc/interrupt.c
module_init(proc_interrupts_init);
|
-->proc_interrupts_init()
|
--> proc_create("interrupts", 0, NULL, &proc_interrupts_operations); /*参数NULL说明是在/proc 目录下创建
名字为interrupts的文件。 */

一位伟大的程序员说过 -- "代码就是最好的文档". (黄金必杀句)
static const struct file_operations proc_interrupts_operations = {
.open = interrupts_open,
...
};

static int interrupts_open(struct inode *inode, struct file *filp)
{
return seq_open(filp, &int_seq_ops);
}

static const struct seq_operations int_seq_ops = {
...
.show = show_interrupts
};

linux-2.6.28/arch/arm/kernel/irq.c
show_interrupts()
{
...
for_each_present_cpu(cpu) {
sprintf(cpuname, "CPU%d", cpu);
seq_printf(p, " %10s", cpuname);
}
...
seq_printf(p, "%3d: ", i);
for_each_present_cpu(cpu)
seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
seq_printf(p, " %s", action->name);
for (action = action->next; action; action = action->next)
seq_printf(p, ", %s", action->name);
...
}

在这里如果能够想到irq_desc[]这个全局的结构数组, 就都明白了。

下面是一个实际运行 cat /proc/interrupts 的结果
CPU0
8: 2 GPIO-l eth0
11: 0 SC pxa25x_udc
14: 404 SC AC97
22: 43 SC FFUART
25: 0 SC DMA
26: 19388 SC ost0
67: 0 GPIO UCB1400
Err: 0




(二)再来看看/proc/net/dev

直接看代码吧,linux-2.6.28/net/core/dev.c

static int __net_init dev_proc_net_init(struct net *net)
{
...
if (!proc_net_fops_create(net, "dev", S_IRUGO, &dev_seq_fops))
goto out;
...
}

static int dev_seq_open(struct inode *inode, struct file *file)
{
return seq_open_net(inode, file, &dev_seq_ops,
sizeof(struct seq_net_private));
}

static const struct file_operations dev_seq_fops = {
...
.open = dev_seq_open,
...
};

static int dev_seq_open(struct inode *inode, struct file *file)
{
return seq_open_net(inode, file, &dev_seq_ops,
sizeof(struct seq_net_private));
}


static const struct seq_operations dev_seq_ops = {
...
.next = dev_seq_next,
...
.show = dev_seq_show,
};

/*
* Called from the PROCfs module. This now uses the new arbitrary sized
* /proc/net interface to create /proc/net/dev
*/
static int dev_seq_show(struct seq_file *seq, void *v)
{
if (v == SEQ_START_TOKEN)
seq_puts(seq, "Inter-| Receive "
" | Transmit\n"
" face |bytes packets errs drop fifo frame "
"compressed multicast|bytes packets errs "
"drop fifo colls carrier compressed\n");
else
dev_seq_printf_stats(seq, v);
return 0;
}


static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev)
{
struct net_device_stats *stats = dev->get_stats(dev);

seq_printf(seq, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu "
"%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
dev->name, stats->rx_bytes, stats->rx_packets,
stats->rx_errors,
stats->rx_dropped + stats->rx_missed_errors,
stats->rx_fifo_errors,
stats->rx_length_errors + stats->rx_over_errors +
stats->rx_crc_errors + stats->rx_frame_errors,
stats->rx_compressed, stats->multicast,
stats->tx_bytes, stats->tx_packets,
stats->tx_errors, stats->tx_dropped,
stats->tx_fifo_errors, stats->collisions,
stats->tx_carrier_errors +
stats->tx_aborted_errors +
stats->tx_window_errors +
stats->tx_heartbeat_errors,
stats->tx_compressed);
}


void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct net *net = seq_file_net(seq);
++*pos;
return v == SEQ_START_TOKEN ?
first_net_device(net) : next_net_device((struct net_device *)v);
}

下面是一个实际运行 cat /proc/net/dev 的结果
Inter-|Receive Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo:16200 185 0 0 0 0 0 0 16200 185 0 0 0 0 0 0
eth0:13817124 13810 0 0 0 0 0 0 3416037 13030 0 0 0 0 0 0
"%6s: %8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu " "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
17个参数完全匹配上了。 这里需要指出的是Linux的网卡设备是由linux的链表管理的,dev_seq_next的作用就不言而喻了



真是无语了,贴了一堆代码。不过最起码还有点代码,要不然岂不成了无code(哈哈哈,多么天真无邪的笑声)。


认 真想一下,突然醒悟了,“驱动的代码调用某个写/proc文件的函数把eth0的信息写到/proc/net/dev文件”的想法是不正确的,起码没有深 刻的理解Linux下文件的含义。Linux 的vfs 里各文件的读写等操作可以有不同的实现, 而上述的几个/proc 文件都没有write的实现,这就是从驱动的角度来跟踪内核代码没有收获的原因了,因为根本就没有去写/proc/net/dev这个文件,自然找不到向 /proc/net/dev添加eth0内容的函数了。
但是为什么cat /proc/net/dev的内容出现了变化呢?先说个看似不相关的话,魔术师大卫.科波菲尔的“消失自由女神像”是真的把自由女神像移走了吗?当然没 有,但是他给观众show出的景象里自由女神像是不存在的,观众就认为自由女神像消失了。Linux的vfs就魔术师一样,/proc的那些文件的操作函 数很特殊,不需要直接对/proc文件的内容进行写操作来添加内容,就能用充满魔力的show函数来给用户提供信息。

这篇关于Linux内核proc文件系统的冰山一角 源自对/proc/net/dev文件中各网卡参数的疑问的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/151608

相关文章

Java线程池核心参数原理及使用指南

《Java线程池核心参数原理及使用指南》本文详细介绍了Java线程池的基本概念、核心类、核心参数、工作原理、常见类型以及最佳实践,通过理解每个参数的含义和工作原理,可以更好地配置线程池,提高系统性能,... 目录一、线程池概述1.1 什么是线程池1.2 线程池的优势二、线程池核心类三、ThreadPoolE

Linux内核定时器使用及说明

《Linux内核定时器使用及说明》文章详细介绍了Linux内核定时器的特性、核心数据结构、时间相关转换函数以及操作API,通过示例展示了如何编写和使用定时器,包括按键消抖的应用... 目录1.linux内核定时器特征2.Linux内核定时器核心数据结构3.Linux内核时间相关转换函数4.Linux内核定时

C#借助Spire.XLS for .NET实现在Excel中添加文档属性

《C#借助Spire.XLSfor.NET实现在Excel中添加文档属性》在日常的数据处理和项目管理中,Excel文档扮演着举足轻重的角色,本文将深入探讨如何在C#中借助强大的第三方库Spire.... 目录为什么需要程序化添加Excel文档属性使用Spire.XLS for .NET库实现文档属性管理Sp

Linux镜像文件制作方式

《Linux镜像文件制作方式》本文介绍了Linux镜像文件制作的过程,包括确定磁盘空间布局、制作空白镜像文件、分区与格式化、复制引导分区和其他分区... 目录1.确定磁盘空间布局2.制作空白镜像文件3.分区与格式化1) 分区2) 格式化4.复制引导分区5.复制其它分区1) 挂载2) 复制bootfs分区3)

Linux服务器数据盘移除并重新挂载的全过程

《Linux服务器数据盘移除并重新挂载的全过程》:本文主要介绍在Linux服务器上移除并重新挂载数据盘的整个过程,分为三大步:卸载文件系统、分离磁盘和重新挂载,每一步都有详细的步骤和注意事项,确保... 目录引言第一步:卸载文件系统第二步:分离磁盘第三步:重新挂载引言在 linux 服务器上移除并重新挂p

Linux下屏幕亮度的调节方式

《Linux下屏幕亮度的调节方式》文章介绍了Linux下屏幕亮度调节的几种方法,包括图形界面、手动调节(使用ACPI内核模块)和外接显示屏调节,以及自动调节软件(CaliseRedshift和Reds... 目录1 概述2 手动调节http://www.chinasem.cn2.1 手动屏幕调节2.2 外接显

Linux(centos7)虚拟机没有IP问题及解决方案

《Linux(centos7)虚拟机没有IP问题及解决方案》文章介绍了在CentOS7中配置虚拟机网络并使用Xshell连接虚拟机的步骤,首先,检查并配置网卡ens33的ONBOOT属性为yes,然后... 目录输入查看ZFhrxIP命令:ip addr查看,没有虚拟机IP修改ens33配置文件重启网络Xh

Java JAR 启动内存参数配置指南(从基础设置到性能优化)

《JavaJAR启动内存参数配置指南(从基础设置到性能优化)》在启动Java可执行JAR文件时,合理配置JVM内存参数是保障应用稳定性和性能的关键,本文将系统讲解如何通过命令行参数、环境变量等方式... 目录一、核心内存参数详解1.1 堆内存配置1.2 元空间配置(MetASPace)1.3 线程栈配置1.

C#借助Spire.XLS for .NET实现Excel工作表自动化样式设置

《C#借助Spire.XLSfor.NET实现Excel工作表自动化样式设置》作为C#开发者,我们经常需要处理Excel文件,本文将深入探讨如何利用C#代码,借助强大的Spire.XLSfor.N... 目录为什么需要自动化工作表样式使用 Spire.XLS for .NET 实现工作表整体样式设置样式配置

linux实现对.jar文件的配置文件进行修改

《linux实现对.jar文件的配置文件进行修改》文章讲述了如何使用Linux系统修改.jar文件的配置文件,包括进入文件夹、编辑文件、保存并退出编辑器,以及重新启动项目... 目录linux对.jar文件的配置文件进行修改第一步第二步 第三步第四步总结linux对.jar文件的配置文件进行修改第一步进