ifconfig源码分析之与内核交互数据
《ifconfig源码分析之与内核交互数据》
本文档的Copyleft归rosetta所有,使用GPL发布,可以自由拷贝、转载,转载时请保持文档的完整性。
参考资料:《Linux设备驱动程序 第三版》,scull源码,Linux内核源码
来源:http://blog.csdn.net/rosetta/article/details/7563615
ifconifg是Linux提供的一个操作网络接口的应用层程序,虽然和设备驱动编写没什么联系,但分析它的部分核心代码有助于理解应用层和内核层交互过程。
这也是对《字符设备驱动程序编写基础》最后提出的问题的一个解答。
ifconifg.c文件一千多行再加上相关公共文件大概会达到二千行,只分析其与内核交互过程,其它部分有兴趣的朋友可以自行分析。
知识点:
* 获取ifconfig源码方法。
* ifconfig 输出结果解释。
* 应用层和内核层交互过程。
* ioctl的使用。
* 认识/proc/net/dev。
一、获取ifconifg源码包并编译。
[root@xxx net-tools-1.60]# type ifconfig
ifconfig is hashed (/sbin/ifconfig)
[root@xxx net-tools-1.60]# rpm -qf /sbin/ifconfig
net-tools-1.60-78.el5
可知ifconfig属于net-tools源码包,下载之。net-tools源码包不仅包含ifconifg,还包含常用的arp、route、netstat等工具源码。
直接make,应该会有错误,按着错误提示修改下源码即可。
二、ifconifg eth0执行结果解释
[root@ xxx]# ./ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:0C:29:9a:26:37
inet addr:192.168.95.162 Bcast:192.168.95.255 Mask:255.255.255.0
inet6 addr: fe80::21c:29ff:fe9b:2637/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2495308 errors:0 dropped:0 overruns:0 frame:0
TX packets:2215616 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:998016881 (951.7 MiB) TX bytes:886972155 (845.8 MiB)
Interrupt:18 Base address:0x2000
Link encap:Ethernet 本网卡接入的网络的类型是以太网。
HWaddr 00:0C:29:9a:26:37 本网卡的硬件地址。
inet6 addr: fe80::21c:29ff:fe9b:2637/64 Scope:Link ipv6地址。
UP 网卡状态为开启。
BROADCAST 支持广播。
RUNNING 网卡的网线被接上。
MULTICAST 支持多播。
MTU:1500 IP数据包的最大长度,带IP头。
RX表示接收数据包的情况。
TX表示发送数据包的情况。
如果网卡已经完成配置却还是无法与其它设备通信,那么从RX 和TX 的显示数据上可以简单地分析一下故障原因。在这种情况下,如果接收和传送的包的计数(packets)增加,那有可能是系统的IP地址出现了冲突;如果看到大量的错误(errors)和冲突(Collisions),那么这很有可能是网络的传输介质出了问题,例如网线不通或hub损坏。
collisions: 网络讯号碰撞的情况说明
txqueuelen: 传输缓区长度大小
三、认识/proc/net/dev
这里列出了所有网络设备的其属性状态和收发包情况。ifconfig会open这个设备查找匹配信息。
[root@xxx ipsec]# 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: 14920 167 0 0 0 0 0 0 14920 167 0 0 0 0 0 0
eth0:104165628 231316 5 5 0 0 0 0 27195571 185064 0 0 0 0 0 0
eth1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
eth2: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
sit0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ipsec0: 128 2 0 0 0 0 0 0 900 6 0 0 0 0 0 0
ipsec1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ipsec2: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ipsec3: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
sn0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
sn1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
四、分析./ifconfig eth0 源码执行流程
前面部分是对选项的解析判断,给出函数调用过程,具体内容跳过。
//ifconfig.c
main()
->if_print()//输入参数为"eth0"
->lookup_interface()
->do_if_fetch()
->if_fetch()//从内核获取网卡信息,也是和内核交互的核心
->ife_print()//再把接收到的数据以第二步的格式打出
int if_fetch(struct interface *ife)
{
struct ifreq ifr;
int fd;
char *ifname = ife->name;
strcpy(ifr.ifr_name, ifname);
if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)//skfd为本地域套接字,SIOCGIFFLAGS为传给内核的cmd,ifr接收从内核返回的数据。
return (-1);
ife->flags = ifr.ifr_flags;
strcpy(ifr.ifr_name, ifname);
if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
memset(ife->hwaddr, 0, 32);
else
memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);
ife->type = ifr.ifr_hwaddr.sa_family;
……
}
讲到这里,我觉得就讲完了,虽然没有很高深的内容,但原本在脑海中模糊的概念已经变得清晰。
再帖上一段内核有关ioctl处理的源码:
int dev_ioctl(unsigned int cmd, void __user *arg)
{
struct ifreq ifr;
int ret;
char *colon;
/* One special case: SIOCGIFCONF takes ifconf argument
and requires shared lock, because it sleeps writing
to user space.
*/
if (cmd == SIOCGIFCONF) {
rtnl_shlock();
ret = dev_ifconf((char __user *) arg);
rtnl_shunlock();
return ret;
}
if (cmd == SIOCGIFNAME)
return dev_ifname((struct ifreq __user *)arg);
if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
return -EFAULT;
ifr.ifr_name[IFNAMSIZ-1] = 0;
colon = strchr(ifr.ifr_name, ':');
if (colon)
*colon = 0;
/*
* See which interface the caller is talking about.
*/
switch (cmd) {
/*
* These ioctl calls:
* - can be done by all.
* - atomic and do not require locking.
* - return a value
*/
case SIOCGIFFLAGS://here case
case SIOCGIFMETRIC:
case SIOCGIFMTU:
case SIOCGIFHWADDR:
case SIOCGIFSLAVE:
case SIOCGIFMAP:
case SIOCGIFINDEX:
case SIOCGIFTXQLEN:
dev_load(ifr.ifr_name);
read_lock(&dev_base_lock);
ret = dev_ifsioc(&ifr, cmd);//here
read_unlock(&dev_base_lock);
if (!ret) {
if (colon)
*colon = ':';
if (copy_to_user(arg, &ifr,
sizeof(struct ifreq)))
ret = -EFAULT;
}
return ret;
……
}
/*
* Perform the SIOCxIFxxx calls.
*/
static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
{
int err;
struct net_device *dev = __dev_get_by_name(ifr->ifr_name);
if (!dev)
return -ENODEV;
switch (cmd) {
case SIOCGIFFLAGS: /* Get interface flags */
ifr->ifr_flags = dev_get_flags(dev);//给ifr赋值
return 0;
case SIOCSIFFLAGS: /* Set interface flags */
return dev_change_flags(dev, ifr->ifr_flags);
……
}
转载于:https://www.cnblogs.com/Ph-one/p/9024145.html
ifconfig源码分析之与内核交互数据相关推荐
- Linux内核源码分析—从用户空间复制数据到内核空间
Linux内核源码分析-从用户空间复制数据到内核空间 本文主要参考<深入理解Linux内核>,结合2.6.11.1版的内核代码,分析从用户空间复制数据到内核空间函数. 1.不描述内核同步. ...
- v35.03 鸿蒙内核源码分析(时间管理) | 内核基本时间单位是谁 | 百篇博客分析HarmonyOS源码
子曰:"譬如为山,未成一篑,止,吾止也:譬如平地,虽覆一篑,进,吾往也." <论语>:子罕篇 百篇博客系列篇.本篇为: v35.xx 鸿蒙内核源码分析(时间管理篇) | ...
- 鸿蒙内核代码 行,鸿蒙内核源码分析(CPU篇) | 内核是如何描述CPU的 ? | 祝新的一年牛气冲天 ! | v36.01...
本篇说清楚CPU 读本篇之前建议先读鸿蒙内核源码分析(总目录)进程/线程篇.指令是稳定的,但指令序列是变化的,只有这样计算机才能够实现用计算来解决一切问题这个目标.计算是稳定的,但计算的数据是多变的, ...
- 鸿蒙内核源码分析表,鸿蒙内核源码分析(双向链表篇) | 谁是内核最重要结构体 ? | 开篇致敬鸿蒙内核开发者 | v1.10...
谁是鸿蒙内核最重要的结构体? 答案一定是: LOS_DL_LIST(双向链表),它长这样.typedef struct LOS_DL_LIST {//双向链表,内核最重要结构体 struct LOS_ ...
- UDT 最新源码分析(五) -- 网络数据收发
UDT 最新源码分析 -- 网络数据收发 从接口实现看 UDT 网络收发 UDT 发送 send / sendmsg / sendfile UDT 接收 recv /recvmsg /recvfile ...
- djangorestframework源码分析2:serializer序列化数据的执行流程
djangorestframework源码分析 本文环境python3.5.2,djangorestframework (3.5.1)系列 djangorestframework源码分析-serial ...
- Linux内核 eBPF基础:ftrace源码分析:过滤函数和开启追踪
Linux内核 eBPF基础 ftrace基础:过滤函数和开启追踪 荣涛 2021年5月12日 本文相关注释代码:https://github.com/Rtoax/linux-5.10.13 上篇文章 ...
- Linux内核 eBPF基础:kprobe原理源码分析:源码分析
Linux内核 eBPF基础 kprobe原理源码分析:源码分析 荣涛 2021年5月11日 在 <Linux内核 eBPF基础:kprobe原理源码分析:基本介绍与使用>中已经介绍了kp ...
- v06.03 鸿蒙内核源码分析(调度队列) | 内核调度也需要排队 | 百篇博客分析HarmonyOS源码
子曰:"君子食无求饱,居无求安,敏于事而慎于言,就有道而正焉,可谓好学也已."<论语>:学而篇 百篇博客系列篇.本篇为: v06.xx 鸿蒙内核源码分析(调度队列篇) ...
- Linux内核源码分析《进程管理》
Linux内核源码分析<进程管理> 前言 1. Linux 内核源码分析架构 2. 进程原理分析 2.1 进程基础知识 2.2 Linux进程四要素 2.3 进程描述符 task_stru ...
最新文章
- 《例说8051:单片机程序设计案例教程》——2-4 指令格式
- javascript原型对象、原型链、构造函数
- paramterType和resultType的区别
- KVM安装Windows Server 2008 R2使用virtio硬盘
- ggplot2箱式图两两比较_作图技巧024篇ggplot2在循环中的坑
- 安装Ubuntu时的硬盘分区方案
- ASP基础教程之ASP AdRotator 组件的使用
- mvc html 辅助方法,MVC HTML辅助类常用方法记录
- 最速下滑法c语言程序,最速下降法 C语言.doc
- 互联网+时代的7个引爆点(读书笔记)
- 本地系统盘放到服务器上,如何将本地盘映射在云服务器上
- 开发管理---项目的范围、时间与成本
- Excel函数返回定期付息证券的应计利息
- 什么是分布式系统,这么讲不信你不会
- SSH Tunneling
- PG主程序模块(Main)——boot模式
- 基于Xposed框架截取安卓手机应用数据信息
- Weka安装及简单应用
- 双向绑定原理(个人理解)
- Velodyne已出货的激光雷达传感器价值达5亿美元
热门文章
- 作用域和请求参数传递
- mac系统一些快捷键
- 6)Thymelead th:with 局部变量 与 属性优先级 和 Thymeleaf 注释
- Location 对象操作 URL 使用详解
- arduino 读取串口信息hex_进阶教程1:Arduino串口通信与电脑控制LED
- 阶段1 语言基础+高级_1-3-Java语言高级_08-JDK8新特性_第3节 两种获取Stream流的方式_3_Stream流中的常用方法_filter...
- iOS开发之App上架流程(2017)
- 软件生命周期、面向对象基本概要
- bzoj4754: [Jsoi2016]独特的树叶
- 20169217 《Linux内核原理与分析》 第十周作业