接收到帧时通知驱动程序

轮询

例如,内核可以持续读取设备上的一个内存寄存器,或者当一个定时器到期时就回头检查哪个寄存器。

中断

此时,当特定事件发生时,设备驱动程序会代表内核指示设备产生硬件中断。内核将中断其他活动,然后调用一个驱动程序
所注册的处理函数,以满足设备的需要。当事件是接收到一个帧时,处理函数就会把该帧排入队列某处,然后通知内核。

中断处理程序

表9-1 一些与软件中断及硬件中断相关API
函数/宏 描述
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网络技术内幕读书笔记(九)--中断与网络驱动程序的更多相关文章

  1. 深入理解linux网络技术内幕读书笔记(三)--用户空间与内核的接口

    Table of Contents 1 概论 1.1 procfs (/proc 文件系统) 1.1.1 编程接口 1.2 sysctl (/proc/sys目录) 1.2.1 编程接口 1.3 sy ...

  2. 深入理解linux网络技术内幕读书笔记(十)--帧的接收

    Table of Contents 1 概述 1.1 帧接收的中断处理 2 设备的开启与关闭 3 队列 4 通知内核帧已接收:NAPI和netif_rx 4.1 NAPI简介 4.1.1 NAPI优点 ...

  3. 深入理解linux网络技术内幕读书笔记(四)--通知链

    Table of Contents 1 概述 2 定义链 3 链注册 4 链上的通知事件 5 网络子系统的通知链 5.1 包裹函数 5.2 范例 6 测试实例 概述 [注意] 通知链只在内核子系统之间 ...

  4. 深入理解linux网络技术内幕读书笔记(二)--关键数据结构

    Table of Contents 1 套接字缓冲区: sk_buff结构 1.1 网络选项及内核结构 1.2 结构说明及操作函数 2 net_device结构 2.1 MTU 2.2 结构说明及操作 ...

  5. 深入理解linux网络技术内幕读书笔记(八)--设备注册与初始化

    Table of Contents 1 设备注册之时 2 设备除名之时 3 分配net_device结构 4 NIC注册和除名架构 4.1 注册 4.2 除名 5 设备初始化 6 设备类型初始化: x ...

  6. 深入理解linux网络技术内幕读书笔记(七)--组件初始化的内核基础架构

    Table of Contents 1 引导期间的内核选项 2 注册关键字 3 模块初始化代码 引导期间的内核选项 linux运行用户把内核配置选项传给引导记录,然后引导记录再把选项传给内核. 在引导 ...

  7. 深入理解linux网络技术内幕读书笔记(五)--网络设备初始化

    Table of Contents 1 简介 2 系统初始化概论 2.1 引导期间选项 2.2 中断和定时器 2.3 初始化函数 3 设备注册和初始化 3.1 硬件初始化 3.2 软件初始化 3.3 ...

  8. 深入理解linux网络技术内幕读书笔记(六)--PCI层与网络接口卡

    Table of Contents 1 本章涉及的数据结构 1.1 pci_device_id结构 1.2 pci_dev结构 1.3 pci_driver结构 2 PCI NIC设备驱动程序的注册 ...

  9. 深入理解linux网络技术内幕读书笔记(一)--简介

    Table of Contents 1 基本术语 1.1 本书常用的缩写 2 引用计数 2.1 引用计数函数 3 垃圾回收 3.1 异步 3.2 同步 4 函数指针 4.1 缺点 5 goto语句 5 ...

随机推荐

  1. 机器学习笔记——K-means

    K-means是一种聚类算法,其要求用户设定聚类个数k作为输入參数,因此,在执行此算法前,须要预计须要的簇的个数. 如果有n个点,须要聚到k个簇中.K-means算法首先从包括k个中心点的初始集合開始 ...

  2. crtmpserver 基本流程分析

    近期在研究crtmpserver,这里记录下学习过程,首先我们先分析下基本流程. 1.初始化流程 InitNetworking---初始化网络 Initialize Logger::Init()--- ...

  3. Java基础知识强化93:算一下你来到这个世界多少天的案例

    1. 分析: (1)键盘录入你的出生年月日 (2)把该字符串转换为一个日期 (3)通过该日期得到一个毫秒值 (4)获取当前时间的毫秒值 (5)用(4)-(3)得到一个毫秒值 (6)把E的毫秒值转换为天 ...

  4. web03--session

    1.创建session1.jsp <body> <form action="session2.jsp" method="post"> & ...

  5. css的clip裁剪

    clip 属性是用来设置元素的形状.用来剪裁绝对定位元素(absolute or fixed). clip有三种取值:auto |inherit|rect.inherit是继承,ie不支持这个属性, ...

  6. FineUI页面级别的参数配置

    Theme: 控件主题,目前支持三种主题风格(blue/gray/access,默认值:blue) Language: 控件语言(en/zh_CN/zh_TW/...,默认值:zh_CN) FormM ...

  7. 网络断开后重连downloadProvider继续下载问题调试分析

    最近在安卓4.4上遇到一个断开wifi后重新连接wifi, downloadProvider继续下载文件失败的问题.于是开始了解下载管理模块的断点续载功能:     1.首先,分析android lo ...

  8. iOS中使用Localizable.strings适配App在不同语言下文本的显示

    iOS开发中,若是使用xib或storyboard搭建界面视图,视图中固定显示的文本内容可以用localized添加不同语言适配.但是在实际中会有动态加载的文本,这些文字的适配就需要NSLocaliz ...

  9. 【C#学习笔记】二、面向对象编程

    2.1 抽象类与接口 1)概念 抽象类是特殊的类,只是不能被实例化:除此以外,具有类的其他特性:重要的是抽象类可以包括抽象方法,这是普通类所不能的.抽象方法只能声明于抽象类中,且不包含任何实现,派生类 ...

  10. 武汉科技大学ACM :1007: 华科版C语言程序设计教程(第二版)习题7.10

    Problem Description 输入n(n<100)个字符串,每个字符串长度不超过1000,将他们按字典顺序输出. Input 多组测试样例. 每组第一行有一个整数n表示有n个字符串. ...