Linux网络协议栈(三)——网络设备(2)
2.1、网络设备的注册与注销
注册网络设备发生在下列情形:
(1)加载网卡驱动程序
网卡驱动程序如果被编译进内核,则它在启动时被初始化,在运行时被作为模块加载。无论初始化是否发生,所以由驱动程序控制的网卡都被注册。
(2)插入可热拔插网络设备
当用户插入一块热拔插网卡,内核通知其对应的驱动程序以注册设备。(为了简单化,我们假定设备驱动程序已经被加载)。
两个主要的情形会导致设备注销:
(1)卸载网卡驱动程序
这只适用与驱动程序作为模块被加载的情形,当然不适于编译进内核的情况。当管理员卸载网卡设备驱动程序时,所有相关网卡的驱动程序都被注销。
(2)移除热拔插网络设备
当用户从正在运行且内核支持热拔插功能的系统中移除热拔插网卡时,网络设备被注销。
2.1.1、分配 net_device结构空间
在内核中,网络设备由结构net_device表示,在注册网络设备之前,必须为之分配内存空间,这一任务由net/core/dev.c中定义的alloc_netdev函数来完成:
Code
内核也提供了一些封装alloc_netdev功能的函数,如下:
alloc_etherdev函数用于以太网设备,所以它创建以字符串eth后跟唯一数字形式的设备名;第二点,它指派ether_setup作为配置函数,对于所有以太网卡来说,配置函数均把net_device结构的部分域初始化为公用值。
Code
2.1.2、注册网络设备
网络设备注册(a)与注销模型(b):
为了简单,来看看回环设备的注册:
Code
注:在这里,设备驱动初始化函数loopback_init并没有调用alloc_netdev来分配内存,而是直接调用kmalloc,实际上alloc_netdev只是对kmalloc的封装而已。
2.2、网络设备的方法
2.2.1、打开与关闭设备
打开网络设备
一旦设备注册即可使用,但它必须在用户(或用户空间应用程序)使能后才可以收发数据。dev_open 处理设备使能的请求,它定义在net/core/dev.c,定义如下:
Code
打开设备由以下几部组成:
(1)如果 dev->open 被定义则调用它。并非所有的驱动程序都初始化这个函数。
(2)设置 dev->state 的__LINK_STATE_START 标志位,标记设备打开并在运行。
(3)设置 dev->flags 的 IFF_UP 标志位标记设备启动。
(4)调用dev_activate所指函数初始化流量控制用的排队规则,并启动监视定时器。如
果用户没有配置流量控制,则指定缺省的先进先出(FIFO)队列。
(5)发送 NETDEV_UP 通知给 netdev_chain 通知链以通知对设备使能有兴趣的内核组件。
设备驱动的open方法
来看看3com网卡的驱动drivers/net/3c59x.c中的vortex_open,它是在vortex_init()中(即驱动程序初始化的过程中)赋给dev->open函数指针:
Code
关闭网络设备
Code
它由以下几步组成:
(1)发送 NETDEV_GOING_DOWN 通知到 netdev_chain 通知链以通知对设备禁止有兴趣的内核组件。
(2)调用 dev_deactivate 函数禁止出口队列规则,这样确保设备不再用于传输,并停止
不再需要的监控定时器。
(3)清除 dev->state 标志的__LINK_STATE_START 标志位,标记设备卸载。
(4)如果轮询动作被调度在读设备入队列数据包,则等待此动作完成。这是由于__LINK_STATE_START 标志位被清除,不再接受其它轮询在设备上调度,但在标志被清除前已有一个轮询正被调度。
(5)如果 dev->stop 指针不空则调用它,并非所有的设备驱动都初始化此函数指针。
(6)清除 dev->flags 的 IFF_UP 标志位标识设备关闭。
(7)发送 NETDEV_DOWN 通知给 netdev_chain 通知链,通知对设备禁止感兴趣的内核组件。
2.2.2、传输数据与接收数据
传输数据
网络子系统中,数据最后由链路层协议调用dev_queue_xmit(),位于net/core/dev.c,完成传输,而dev_queue_xmit又会调用具体网络适配器的驱动程序方法dev->hard_start_xmit(),从而驱动网络适配器最终完成数据传输,参见vortex_start_xmit()。
接收数据
当网络适配器接收一个数据帧时,就会触发一个中断,在中断处理程序(位于设备驱动)中,会分配sk_buff数据结构保存数据帧,最后会调用netif_rx(),将套接字缓冲区放入网络设备的输入队列。对于3c39x.c,其过程如下:
vortex_interrupt( )---> vortex_rx( )--->netif_rx( )。
来看看回环设备的发送与接收过程:
//derivers/net/loopback.c
/*首先调用skb_orphan把skb孤立,使它跟发送socket和协议栈不再有任何联系,也即对本机来说,
**这个skb的数据内容已经发送出去了,而skb相当于已经被释放掉了。对于环回设备接口来说,
**数据的发送工作至此已经全部完成,接下来,只要把这个实际上还未被释放的skb传回给协议栈
**的接收函数即可。
*/
static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct net_device_stats *lb_stats;
/////////相当于发送过程////////////////////
skb_orphan(skb); //////////以下相当于接收过程////////////////
skb->protocol=eth_type_trans(skb,dev);
skb->dev=dev;
#ifndef LOOPBACK_MUST_CHECKSUM
skb->ip_summed = CHECKSUM_UNNECESSARY;
#endif if (skb_shinfo(skb)->tso_size) {
BUG_ON(skb->protocol != htons(ETH_P_IP));
BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP); emulate_large_send_offload(skb);
return 0;
} dev->last_rx = jiffies; //接收到数据的时间
//统计信息
lb_stats = &per_cpu(loopback_stats, get_cpu());
lb_stats->rx_bytes += skb->len;
lb_stats->tx_bytes += skb->len;
lb_stats->rx_packets++;
lb_stats->tx_packets++;
put_cpu(); netif_rx(skb); return(0);
}
Linux网络协议栈(三)——网络设备(2)的更多相关文章
- (转)Linux网络协议栈(三)——网络设备(1)
网络设备(network device)是内核对网络适配器(硬件)的抽象与封装,并为各个协议实例提供统一的接口,它是硬件与内核的接口,它有两个特征:(1) 作为基于硬件的网络适配器与基于软件的协 ...
- Linux网络协议栈(三)——网络设备(1)
网络设备(network device)是内核对网络适配器(硬件)的抽象与封装,并为各个协议实例提供统一的接口,它是硬件与内核的接口,它有两个特征:(1) 作为基于硬件的网络适配器与基于软件的协 ...
- 理解 Linux 网络栈(1):Linux 网络协议栈简单总结
本系列文章总结 Linux 网络栈,包括: (1)Linux 网络协议栈总结 (2)非虚拟化Linux环境中的网络分段卸载技术 GSO/TSO/UFO/LRO/GRO (3)QEMU/KVM + Vx ...
- Linux 网络协议栈开发基础篇—— 网桥br0
一.桥接的概念 简单来说,桥接就是把一台机器上的若干个网络接口"连接"起来.其结果是,其中一个网口收到的报文会被复制给其他网口并发送出去.以使得网口之间的报文能够互相转发. 交换机 ...
- linux网络协议栈--路由流程分析
转:http://blog.csdn.net/hsly_support/article/details/8797976 来吧,路由 路由是网络的核心,是linux网络协议栈的核心,我们找个入口进去看看 ...
- Linux网络编程(三)
Linux网络编程(三) wait()还是waitpid() Linux网络编程(二)存在客户端断开连接后,服务器端存在大量僵尸进程.这是由于服务器子进程终止后,发送SIGCHLD信号给父进程,而父进 ...
- 由PPPOE看Linux网络协议栈的实现
http://www.cnblogs.com/zmkeil/archive/2013/05/01/3053545.html 这个标题起得比较纠结,之前熟知的PPPOE是作为PPP协议的底层载体,而实际 ...
- Linux网络协议栈(二)——套接字缓存(socket buffer)
Linux网络核心数据结构是套接字缓存(socket buffer),简称skb.它代表一个要发送或处理的报文,并贯穿于整个协议栈.1. 套接字缓存skb由两部分组成:(1) 报文数据:它 ...
- 深入理解Linux网络技术内幕——网络设备初始化
概述 内核的初始化过程过程中,与网络相关的工作如下所示: 内核引导时执行start_kernel,start_kernel结束之前会调用rest_init,rest_init初始化内核线 ...
随机推荐
- Codeforces Round #388 (Div. 2) A+B+C!
A. Bachgold Problem 任何一个数都可以由1和2组成,由于n是大于等于2的,也就是可以由2和3组成.要求最多的素数即素数越小越好,很明显2越多越好,如果n为奇数则再输出一个3即可. i ...
- centos 7 下vnc弹出窗口太小解决方法
使用以下参数启动 : vncserver :2 -geometry 800x600
- HDU 1102 Kruscal算法
题目大意:给定村庄的数量,和一个矩阵表示每个村庄到对应村庄的距离,矩阵主对角线上均为1 在给定一个数目Q,输入Q行之间已经有通道的a,b 计算还要至少修建多少长度的轨道 这道题目用Kruscal方法进 ...
- JS中的call()和apply()方法区别
如 果没接触过动态语言,以编译型语言的思维方式去理解javaScript将会有种神奇而怪异的感觉,因为意识上往往不可能的事偏偏就发生了,甚至觉得不可 理喻.如果在学JavaScript这自由而变幻无穷 ...
- Linux下出现launch failed.Binary not found的解决方案
Linux下出现launch failed.Binary not found的解决方案: Project->Properties->C/C++Build->Settings-> ...
- php桥接模式
php桥接模式 桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立地变化. 示例:当一个信息时根据发送渠道分为:QQ消息.email消息.短信消息等根据消息类型分为:普通.警告.危急等每种消息都 ...
- C#高级编程第9版 第二章 核心C# 读后笔记
System命名空间包含了最常用的.NET类型.对应前面第一章的.NET基类.可以这样理解:.NET类提供了大部分的功能,而C#语言本身是提供了规则. pseudo-code,哈哈,秀逗code.伪代 ...
- mySQL windows 服务
https://www.jizhuba.com/kejiyouxi/20171001/6006.html
- Space Ant--poj1696(极角排序)
http://poj.org/problem?id=1696 极角排序是就是字面上的意思 按照极角排序 题目大意:平面上有n个点然后有一只蚂蚁他只能沿着点向左走 求最多能做多少点 分析: 其实 ...
- Java面试题总结之Java基础(二)
Java面试题总结之Java基础(二) 1.写clone()方法时,通常都有一行代码,是什么? 答:super.clone(),他负责产生正确大小的空间,并逐位复制. 2.GC 是什么? 为什么要有G ...