深入理解linux网络技术内幕读书笔记(九)--中断与网络驱动程序
Table of Contents
接收到帧时通知驱动程序
轮询
例如,内核可以持续读取设备上的一个内存寄存器,或者当一个定时器到期时就回头检查哪个寄存器。
中断
此时,当特定事件发生时,设备驱动程序会代表内核指示设备产生硬件中断。内核将中断其他活动,然后调用一个驱动程序
所注册的处理函数,以满足设备的需要。当事件是接收到一个帧时,处理函数就会把该帧排入队列某处,然后通知内核。
中断处理程序
| 函数/宏 | 描述 |
|---|---|
| in_interrupt | 处于软硬件中断中,且抢占功能是关闭的 |
| in_softirq | 处于软件中断中 |
| in_irq | 处于硬件中断中 |
| softirq_pending | 软件中断未决 |
| local_softirq_pending | 本地软件中断未决 |
| __raise_softirq_irqoff | 设置与输入的软IRQ类型相关联的标识,将该软IRQ标记为未决 |
| raise_softirq_irqoff | 先关闭硬件中断,再调用__raise_softirq_irqoff,再恢复其原有状态 |
| raise_softirq | |
| __local_bh_enable | |
| local_bh_enable | |
| local_bh_disable | |
| local_irq_disable | |
| local_irq_enable | |
| local_irq_save | |
| local_irq_restore | |
| spin_lock_bh | |
| spin_unlock_bh |
抢占功能
- preempt_disable()
为当前任务关闭抢占功能。可以重复调用,递增一个引用计数器。 - preempt_enable()
- preempt_enable_no_resched()
开启抢占功能。preempt_enable_no_reched()只是递减一个引用计数器,使得其值为0时,可以让抢占再度开启。
下半部函数
内核2.4版本以后的下半部函数: 引入软IRQ
对并发的唯一限制就是何时,在一个CPU上每个软IRQ都只能有一个实例运行。
新式的软IRQ模型只有10种模型(include/linux/interrupt.h):
1: /* PLEASE, avoid to allocate new softirqs, if you need not _really_ high
2: frequency threaded job scheduling. For almost all the purposes
3: tasklets are more than enough. F.e. all serial device BHs et
4: al. should be converted to tasklets, not to softirqs.
5: */
6:
7: enum
8: {
9: HI_SOFTIRQ=,
10: TIMER_SOFTIRQ,
11: NET_TX_SOFTIRQ,
12: NET_RX_SOFTIRQ,
13: BLOCK_SOFTIRQ,
14: BLOCK_IOPOLL_SOFTIRQ,
15: TASKLET_SOFTIRQ,
16: SCHED_SOFTIRQ,
17: HRTIMER_SOFTIRQ,
18: RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */
19:
20: NR_SOFTIRQS
21: };
网络代码如何使用软IRQ
网络子系统在net/core/dev.c中注册接收发送软中断:
open_softirq(NET_TX_SOFTIRQ, net_tx_action);
open_softirq(NET_RX_SOFTIRQ, net_rx_action);
1: /*
2: * Initialize the DEV module. At boot time this walks the device list and
3: * unhooks any devices that fail to initialise (normally hardware not
4: * present) and leaves us with a valid list of present and active devices.
5: *
6: */
7:
8: /*
9: * This is called single threaded during boot, so no need
10: * to take the rtnl semaphore.
11: */
12: static int __init net_dev_init(void)
13: {
14: int i, rc = -ENOMEM;
15:
16: BUG_ON(!dev_boot_phase);
17:
18: if (dev_proc_init())
19: goto out;
20:
21: if (netdev_kobject_init())
22: goto out;
23:
24: INIT_LIST_HEAD(&ptype_all);
25: for (i = ; i < PTYPE_HASH_SIZE; i++)
26: INIT_LIST_HEAD(&ptype_base[i]);
27:
28: if (register_pernet_subsys(&netdev_net_ops))
29: goto out;
30:
31: /*
32: * Initialise the packet receive queues.
33: */
34:
35: for_each_possible_cpu(i) {
36: struct softnet_data *sd = &per_cpu(softnet_data, i);
37:
38: memset(sd, , sizeof(*sd));
39: skb_queue_head_init(&sd->input_pkt_queue);
40: skb_queue_head_init(&sd->process_queue);
41: sd->completion_queue = NULL;
42: INIT_LIST_HEAD(&sd->poll_list);
43: sd->output_queue = NULL;
44: sd->output_queue_tailp = &sd->output_queue;
45: #ifdef CONFIG_RPS
46: sd->csd.func = rps_trigger_softirq;
47: sd->csd.info = sd;
48: sd->csd.flags = ;
49: sd->cpu = i;
50: #endif
51:
52: sd->backlog.poll = process_backlog;
53: sd->backlog.weight = weight_p;
54: sd->backlog.gro_list = NULL;
55: sd->backlog.gro_count = ;
56: }
57:
58: dev_boot_phase = ;
59:
60: /* The loopback device is special if any other network devices
61: * is present in a network namespace the loopback device must
62: * be present. Since we now dynamically allocate and free the
63: * loopback device ensure this invariant is maintained by
64: * keeping the loopback device as the first device on the
65: * list of network devices. Ensuring the loopback devices
66: * is the first device that appears and the last network device
67: * that disappears.
68: */
69: if (register_pernet_device(&loopback_net_ops))
70: goto out;
71:
72: if (register_pernet_device(&default_device_ops))
73: goto out;
74:
75: open_softirq(NET_TX_SOFTIRQ, net_tx_action);
76: open_softirq(NET_RX_SOFTIRQ, net_rx_action);
77:
78: hotcpu_notifier(dev_cpu_callback, );
79: dst_init();
80: dev_mcast_init();
81: rc = ;
82: out:
83: return rc;
84: }
85:
86: subsys_initcall(net_dev_init);
softnet_data结构
每个CPU都有其队列,用来接收进来的帧。数据结构为:
1: /*
2: * Incoming packets are placed on per-cpu queues
3: */
4: struct softnet_data {
5: struct Qdisc *output_queue;
6: struct Qdisc **output_queue_tailp;
7: struct list_head poll_list;
8: struct sk_buff *completion_queue;
9: struct sk_buff_head process_queue;
10:
11: /* stats */
12: unsigned int processed;
13: unsigned int time_squeeze;
14: unsigned int cpu_collision;
15: unsigned int received_rps;
16:
17: #ifdef CONFIG_RPS
18: struct softnet_data *rps_ipi_list;
19:
20: /* Elements below can be accessed between CPUs for RPS */
21: struct call_single_data csd ____cacheline_aligned_in_smp;
22: struct softnet_data *rps_ipi_next;
23: unsigned int cpu;
24: unsigned int input_queue_head;
25: unsigned int input_queue_tail;
26: #endif
27: unsigned dropped;
28: struct sk_buff_head input_pkt_queue;
29: struct napi_struct backlog;
30: };
深入理解linux网络技术内幕读书笔记(九)--中断与网络驱动程序的更多相关文章
- 深入理解linux网络技术内幕读书笔记(三)--用户空间与内核的接口
Table of Contents 1 概论 1.1 procfs (/proc 文件系统) 1.1.1 编程接口 1.2 sysctl (/proc/sys目录) 1.2.1 编程接口 1.3 sy ...
- 深入理解linux网络技术内幕读书笔记(十)--帧的接收
Table of Contents 1 概述 1.1 帧接收的中断处理 2 设备的开启与关闭 3 队列 4 通知内核帧已接收:NAPI和netif_rx 4.1 NAPI简介 4.1.1 NAPI优点 ...
- 深入理解linux网络技术内幕读书笔记(四)--通知链
Table of Contents 1 概述 2 定义链 3 链注册 4 链上的通知事件 5 网络子系统的通知链 5.1 包裹函数 5.2 范例 6 测试实例 概述 [注意] 通知链只在内核子系统之间 ...
- 深入理解linux网络技术内幕读书笔记(二)--关键数据结构
Table of Contents 1 套接字缓冲区: sk_buff结构 1.1 网络选项及内核结构 1.2 结构说明及操作函数 2 net_device结构 2.1 MTU 2.2 结构说明及操作 ...
- 深入理解linux网络技术内幕读书笔记(八)--设备注册与初始化
Table of Contents 1 设备注册之时 2 设备除名之时 3 分配net_device结构 4 NIC注册和除名架构 4.1 注册 4.2 除名 5 设备初始化 6 设备类型初始化: x ...
- 深入理解linux网络技术内幕读书笔记(七)--组件初始化的内核基础架构
Table of Contents 1 引导期间的内核选项 2 注册关键字 3 模块初始化代码 引导期间的内核选项 linux运行用户把内核配置选项传给引导记录,然后引导记录再把选项传给内核. 在引导 ...
- 深入理解linux网络技术内幕读书笔记(五)--网络设备初始化
Table of Contents 1 简介 2 系统初始化概论 2.1 引导期间选项 2.2 中断和定时器 2.3 初始化函数 3 设备注册和初始化 3.1 硬件初始化 3.2 软件初始化 3.3 ...
- 深入理解linux网络技术内幕读书笔记(六)--PCI层与网络接口卡
Table of Contents 1 本章涉及的数据结构 1.1 pci_device_id结构 1.2 pci_dev结构 1.3 pci_driver结构 2 PCI NIC设备驱动程序的注册 ...
- 深入理解linux网络技术内幕读书笔记(一)--简介
Table of Contents 1 基本术语 1.1 本书常用的缩写 2 引用计数 2.1 引用计数函数 3 垃圾回收 3.1 异步 3.2 同步 4 函数指针 4.1 缺点 5 goto语句 5 ...
随机推荐
- Meth | apt-get update ,upgarde 和dist-upgrade 的区别
#sudo apt-get update 获得最近的软件包的列表:列表中包含一些包的信息,比如这个包是否更新过#sudo apt-get dist-upgrade 如果这个包没有发布更新,就不管它:如 ...
- 6、第六课,js jquery20150928
1.声明事件,给事件添加动作 function MyClick() { alert("这是我的第一个js") } 2.js特点 A.js区分大小写 B.弱类型变量,定义一个变量 v ...
- hdu 2218
题意: 切蛋糕问题 水题...... AC代码: #include <iostream> using namespace std; int main() { int a[6],i,n; c ...
- SQL 无法打开物理文件 XXX.mdf",操作系统错误 5:"5(拒绝访问。)"
用T-SQL命令附加数据库时,出现如下异常信息: 无法打开物理文件 XXX.mdf".操作系统错误 5:"5(拒绝访问.)". (Microsoft SQL Server ...
- 自定义异常throw
简单自定义一个年龄小于等于0,或者大于120会出现的异常 首先继承父类Exception,调用父类的构造器,这样才可以报出自己想要的异常 public class AgeException exten ...
- css与div小结
前些时间学习css与div的课程 什么是css呢 Css 级联样式表或层叠样式表(Cascading Style Sheet) 是能够真正做到 网页表现与内容分离的一种样式设计语言.相对于传统HTML ...
- 3D跑酷游戏《月影忍者之疾风狂逃》
<月影忍者之疾风狂逃>是一款3D跑酷游戏,也是我实习的时候参与的一个项目,在那个公司我学到了很多东西,谢谢他们.大家可以去玩玩这个游戏啊,还是不错的哦.
- Oracle数据库之创建表结构
Oracle数据库之创建表结构 主键与外键 主键:关系型数据库中的一条记录中有若干个属性,若其中的某一个属性组(可以是一个属性,也可以是多个)能唯一标识一条记录,那么该属性组就是主键. 外键:关系型数 ...
- Css溢出隐藏
display: -webkit-box;-webkit-line-clamp: 2; /*多少行数之后显示为省略...*/word-wrap: break-word;word-break: ...
- php设计模式2策略模式
<?php /** ****************************************************** * 策略模式:策略模式针对一组算法,将每一个算法封装到具有共同接 ...