ImageVerifierCode 换一换
格式:DOCX , 页数:12 ,大小:23.69KB ,
资源ID:3427457      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/3427457.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(《Linux协议栈源码分析》读书报告.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

《Linux协议栈源码分析》读书报告.docx

1、Linux协议栈源码分析读书报告读 书 报 告 题目 Linux协议栈源码分析 一、介绍1.1、中断模型Linux 支持 CPU 的外部硬件中断和内部中断。不管是内部还是外部中断,系统都会根据接收到的中断信息,查询idt表。idt 表依照中断源的位置按序组成,并对应中断服务程序(以及异常处理程序)的入口地址。Linux 系统在初始化页式虚存管理的初始化以后,便调用 trap_init 和 init_IRQ 两个函数进行中断机制的初始化。1.1.1、软中断内部中断包含系统调用陷入和异常。(1)系统调入陷入系统调用就是软件有计划地调用 CPU 提供的特殊指令,触发 CPU 内部产生一个中断,于是完

2、成一次核内核外运行空间的切换。(2)异常异常就是软件无意的执行了一个非法指令(比如除0)从而造成CPU内部引发一次中断。1.1.2、硬中断外部中断特指外部设备发出的中断信号。但这几种中断的 CPU 处理过程基本相同,即:在执行完当前指令后,或在执行当前指令期间,根据中断源所提供的“中断向量”,在内存中找到相应的 ISR(中断服务例程)然后调用之。1.2、硬中断和软中断的区别(1)软中断是执行中断指令产生的,而硬中断是由外设引发的。(2)硬中断的中断号是由中断控制器提供的,软中断的中断号由指令直接指出,无需使用中断控制器。(3)硬中断是可屏蔽的,软中断不可屏蔽。(4)硬中断处理程序要确保它能快速

3、地完成任务,这样程序执行时才不会等待较长时间,称为上半部。(5)软中断处理硬中断未完成的工作,是一种推后执行的机制,属于下半部。二、中断处理2.1、中断线每个能够产生中断的设备或者模块都会在内核中注册一个中断服务例程(ISR),当产生中断时,中断处理程序会被执行,在中断处理程序中,首先会保存中断向量号和上下文,之后执行中断线对应的中断服务例程。对于CPU来说,中断线是非常宝贵的资源,而由于计算机的发展,外部设备数量和种类越来越多,导致了中断线资源不足的情况,linux为了应对这种情况,实现了两种中断线分配方式,分别是:共享中断线,中断线动态分配。2.1.1、中断线分配方式(1)共享中断线多个设

4、备共用一条中断线,当此条中断线发生中断时,因为不可能预先知道哪个特定的设备产生了中断,因此,这条中断线上的每个中断服务例程都会被执行,以验证是哪个设备产生的中断(一般的,设备产生中断时,会标记自己的状态寄存器,中断服务例程通过检查每个设备的状态寄存器来查找产生中断的设备),因此共享中断线的分配方式是比较常见的。(2)中断线动态分配一条中断线在可能使用的时刻才与一个设备驱动程序关联起来,这样一来,即使几个硬件设备并不共享中断线,同一个中断向量也可以由这几个设备在不同时刻运行。2.1.2、特性(1)中断处理程序正在运行时,CPU会通知中断控制器屏蔽产生此中断的中断线。此中断线发出的信号被暂时忽略,

5、当中断处理程序结束时恢复此中断线。(2)在中断服务例程的设计中,原则上是立即处理紧急的操作,将非紧急的操作延后处理(交给软中断进行处理)。(3)中断处理程序是运行在中断上下文,但是其是代表进程运行的,因此它所代表的进行必须处于TASK_RUNNING状态,否则可能出现僵死情况,因此在中断处理程序中不能执行任何阻塞过程。2.2、硬中断处理2.2.1、硬中断的开关简单禁止和激活当前处理器上的本地中断:local_irq_disable();local_irq_enable();保存本地中断系统状态下的禁止和激活:unsigned long flags;local_irq_save(flags);l

6、ocal_irq_restore(flags);2.2.2、注册软中断处理函数设备驱动程序要处理硬件中断,必须挂接 ISR,则挂接一个 ISR 可以用这个函数,要注意的是你在挂接 ISR 之前要正确的初始化你的设备,并且要保证用正确的顺序挂接中断。里面 调用setup_irq就是把创建的irqaction挂接到对应中断的链表上,以至于handle_IRQ_event能根据 irq 号直接找到对应handler。/*Request_irq-allocate an interrupt lineIrq:要申请的中断号 Handler:就是传说中的ISRIrqflags:中断类型标志Devname:该

7、设备的名字,可以由人看懂的字符Dev_id:似乎是一个ID,但是实际上在我们要讨论的网络设备中就是net_device()结构的一个指针Flags:SA-SHIRQ 中断是共享的SA_INTERRUPI 需要禁止本地中断*/int request_irq(unsigned int irq, irqreturn_t (*handler)(int,void*,struct pt_regs*), undigned long irqflags, const char*devname, void *dev_id)int retval;atruct irqaction*action;action=(str

8、uct irqaction*)Kmalloc(sizeof(struct irqaction),GFR_ATOMIC);此handler就是刚才介绍的handle_IRQ_event 函数中要处理的handler。action-handler=handler;action-flags=irqflags;action-maks-0;action-name=devname;action-next=NULL;action-dev_id=dev_id;retval=setup_irq(irq,action);return retval;2.3、软中断处理2.3.1、软中断的开关禁止下半部,如softi

9、rq、tasklet和workqueue等:local_bh_disable();local_bh_enable();需要注意的是,禁止下半部时仍然可以被硬中断抢占。软中断由softirq_action结构体表示:structsoftirq_actionvoid(*action)(structsoftirq_action*);/*软中断的处理函数*/;2.3.2、注册软中断处理函数/*nr:软中断的索引号*action:软中断的处理函数*/voidopen_softirq(intnr,void(*action)(structsoftirq_action*)softirq_vecnr.actio

10、n=action;例如:open_softirq(NET_TX_SOFTIRQ, net_tx_action);open_softirq(NET_RX_SOFTIRQ, net_rx_action);2.3.3、待处理的软中断检查和执行1. 从一个硬件中断代码处返回时2. 在ksoftirqd内核线程中3. 在那些显示检查和执行待处理的软中断的代码中,如网络子系统中2.4、软中断处理和硬中断处理区别软件中断的处理方式和硬件处理路径是完全不一样的,它不必经过do_IRQ这个函数,而是直接跳转到内核中的代码执行sys_socketcall。实际上软中断是在处理完所有中断之后才会处理的。而且处理软中

11、断的时候还是处于中断上下文中。2.5、关于中断上下文的一些宏IRQ_INPROGRESS:当前还在中断上下文中IRQ_DISABLED:中断被禁止IRQ_PENDING:中断被挂住IRQ_REPLAY:继续中断处理IRQ_AUTODETECT:自动检测中断请求IRQ_WAITING:对于自动监测中断,此时可能还没有看到中断到来IRQ_LEVEL:使用中断优先级别Linux没有使用这项特性IRQ_MASKED:该中断被屏蔽了,将来不希望看到IRQ_PER_CPU:每个CPU都有一个IRQ三、中断处理中数据结构3.1、中断描述符中断描述符用于描述IRQ线的属性与状态,每个IRQ都有它自己的中断描述

12、符,这些中断描述符用一个数组保存, 这个数组就是中断描述符数组,整个中断描述符数组长度为NR_IRQS(通常为224)项。当产生一个中断或者异常时,首先会从中断描述符表中获取到一个中断向量号时(此中断向量号有可能表示中断,也可能表示的是一个异常),如果是一个中断导致的,会执行do_IRQ()函数,而在do_IRQ()函数中,会根据中断向量号,从中断描述符数组中获取对应的中断描述符,如下图:整个中断描述符结构如下:struct irq_desc struct irq_data irq_data; /* irq的统计信息,在proc中可查到 */unsigned int _percpu *ksta

13、t_irqs;/* 回调函数,当此中断产生中断时,会调用handle_irq,在handle_irq中进行遍历irqaction链表 * handle_simple_irq 用于简单处理; * handle_level_irq 用于电平触发中断的流控处理; * handle_edge_irq 用于边沿触发中断的流控处理; * handle_fasteoi_irq 用于需要响应eoi的中断控制器; * handle_percpu_irq 用于只在单一cpu响应的中断; * handle_nested_irq 用于处理使用线程的嵌套中断;*/irq_flow_handler_t handle_ir

14、q;#ifdefCONFIG_IRQ_PREFLOW_FASTEOIirq_preflow_handler_t preflow_handler;#endif /* 中断服务例程链表 */struct irqaction *action; /* IRQ action list */* 状态 */unsigned int status_use_accessors;/* 函数调用中使用,另一个名称为istate */unsigned int core_internal_state_do_not_mess_with_it; /* 嵌套深度,中断线被激活显示0,如果为正数,表示被禁止次数 */unsig

15、ned int depth; /* nested irq disables */unsigned int wake_depth; /* nested wake enables */* 此中断线上发生的中断次数 */unsigned int irq_count; /* For detecting broken IRQs */* 上次发生未处理中断时的jiffies值 */unsigned long last_unhandled; /* Aging timer for unhandled count */ /* 中断线上无法处理的中断次数,如果当第100000次中断发生时,有超过99900次是意外

16、中断,系统会禁止这条中断线 */unsigned int irqs_unhandled;atomic_t threads_handled;int threads_handled_last;/* 锁 */raw_spinlock_t lock; struct cpumask *percpu_enabled;#ifdef CONFIG_SMP /* CPU亲和力关系,其实就是每个CPU是占一个bit长度,某CPU上置为1表明该CPU可以进行这个中断的处理 */const struct cpumask *affinity_hint;struct irq_affinity_notify *affini

17、ty_notify;#ifdef CONFIG_GENERIC_PENDING_IRQ/* 用于调整irq在各个cpu之间的平衡 */cpumask_var_t pending_mask;#endif#endifunsigned long threads_oneshot;atomic_t threads_active;/* 用于synchronize_irq(),等待该irq所有线程完成 */wait_queue_head_t wait_for_threads;#ifdef CONFIG_PM_SLEEP/* irqaction数量 */unsigned int nr_actions;unsi

18、gned int no_suspend_depth;unsigned int force_resume_depth;#endif#ifdef CONFIG_PROC_FS/* 指向与IRQn相关的/proc/irq/n目录的描述符 */struct proc_dir_entry *dir;#endifint parent_irq;struct module *owner;/* 在/proc/interrupts所显示名称 */const char *name; _cacheline_internodealigned_in_smp;core_internal_state_do_not_mes_w

19、ith_it成员是用于记录此中断线状态的,中断线状态有如下几种形式:IRQS_AUTODETECT /* 该IRQ线用来进行硬件设备探测 */IRQS_SPURIOUS_DISABLED / 该IRQ线被禁止,是由于产生了欺骗性中断 IRQS_POLL_INPROGRESS /* 该IRQ进行轮询检查是否发生中断 */IRQS_ONESHOT/* 此IRQ没有在主处理函数中进行unmasked处理 */IRQS_REPLAY /* IRQ线已被禁止,但前一个出现的中断还没有被应答 */IRQS_WAITING/* 进行硬件设备探测时,会将所有没有挂载中断服务程序的IRQ线状态设置为IRQS_W

20、AITING,如果该IRQ上有中断产生,就清除这个状态,可以推断哪些引脚产生过中断 */IRQS_PENDING/* IRQ已经被应答(挂起),但是内核还没有进行处理 */IRQS_SUSPENDED /* 此IRQ被延迟 */ 3.2、中断描述符表和中断描述符数组在中断系统中有两个名字很相像的结构,就是中断描述符表和中断描述符数组。这里我们先说说中断描述符表。一个系统中的中断和异常加起来一共是256个,它们以向量的形式保存在中断描述符表中,每一个向量是8字节(整个表大小就是8 x 256=2048字节),其主要保存着权限位和向量对应的中断或异常处理程序的入口地址。而一般的,linux会将中断

21、描述符表中的031用于非屏蔽中断和异常,其他的中断用于32255之间。CPU把中断描述符表的向量类型分为三种类型:任务门、中断门、陷阱门。CPU为了防止恶意程序访问中断,限制了中断门的权限,而在某些时候,用户程序又必须使用中断,所以Linux把中断描述符的中断向量类型改为了5种:中断门,系统门,系统中断门,陷阱门,任务门。这个中断描述符表的基地址保存在idtr寄存器中。(1)中断门 用户程序不能访问的CPU中断门(权限字段为0),所有的中断处理程序都是这个,被限定在内核态执行。会清除IF标志,屏蔽可屏蔽中断。(2)系统门 用户程序可以访问的CPU陷阱门(权限字段为3)。我们的系统调用就是通过向

22、量128系统门进入的。(3)系统中断门 能够被用户进程访问的CPU陷阱门(权限字段为3),作为一个特别的异常处理所用。(4)陷阱门 用户进程不能访问的CPU陷阱门(权限字段为0),大部分异常处理程序入口都为陷阱门。(5)任务门 用户进程不能访问的CPU任务门(权限字段为0),Double fault异常处理程序入口。3.3、中断控制器描述符(PIC、APIC)为了方便说明,这里我们将PIC和APIC统称为中断控制器。中断控制器是作为中断(IRQ)和CPU核之间的一个桥梁而存在的,每个CPU内部都有一个自己的中断控制器,中断线并不是直接与CPU核相连,而是与CPU内部或外部的中断控制器相连。叫做

23、可编程中断控制器的原因是其本身有一定的寄存器,CPU可以通过操作设置中断控制器屏蔽某个中断引脚的信号,实现硬件上的中断屏蔽。中断控制器也可以级联提供更多的中断线,CPU的INTR与中断控制器的INT相连,INTA与ACK相连,当一个外部中断发生时(比如键盘中断IRQ1),中断控制器与CPU交互操作如下:IRQ1发生中断,主中断控制器接收到中断信号,检查中断屏蔽寄存器IRQ1是否被屏蔽,如果屏蔽则忽略此中断信号。将中断控制器中的中断请求寄存器对应的IRQ1位置位,表示收到IRQ1中断。中断控制器拉高INT引脚电平,告知CPU有中断发生。CPU每执行完一条指令时,都会检查INTR引脚是否被拉高,这

24、里已被拉高。CPU检查EFLAGS寄存器的中断运行标志位IF是否为1,若为1,表明允许中断,通过INTA向中断控制器发出应答。中断控制器接收到应答信号,将IRQ1的中断向量号发到数据总线上,此时CPU会通过数据总线读取IRQ1的中断向量号。最后,如果中断控制器需要EOI(End of Interrupt)信号,CPU则会发送,否则中断控制器自动将INT拉低,并清除IRQ1对应的中断请求寄存器位。在linux内核中,用struct irq_chip结构体描述一个可编程中断控制器,它的整个结构和调度器中的调度类类似,里面定义了中断控制器的一些操作,如下:struct irq_chip /* 中断控

25、制器的名字 */const char *name;/* 控制器初始化函数 */unsigned int (*irq_startup)(struct irq_data *data);/* 控制器关闭函数 */void (*irq_shutdown)(struct irq_data *data);/* 使能irq操作,通常是直接调用irq_unmask(),通过data参数指明irq */void (*irq_enable)(struct irq_data *data); /* 禁止irq操作,通常是直接调用irq_mask,严格意义上,他俩其实代表不同的意义,disable表示中断控制器根本就不

26、响应该irq,而mask时,中断控制器可能响应该irq,只是不通知CPU */void (*irq_disable)(struct irq_data *data); /* 用于CPU对该irq的回应,通常表示cpu希望要清除该irq的pending状态,准备接受下一个irq请求 */void (*irq_ack)(struct irq_data *data);/* 屏蔽irq操作,通过data参数表明指定irq */void (*irq_mask)(struct irq_data *data);/* 相当于irq_mask() + irq_ack() */void (*irq_mask_ack

27、)(struct irq_data *data);/* 取消屏蔽指定irq操作 */void (*irq_unmask)(struct irq_data *data);/* 某些中断控制器需要在cpu处理完该irq后发出eoi信号 */void (*irq_eoi)(struct irq_data *data);/* 用于设置该irq和cpu之间的亲和力,就是通知中断控制器,该irq发生时,那些cpu有权响应该irq */int(*irq_set_affinity)(struct irq_data *data, const struct cpumask *dest, bool force);i

28、nt (*irq_retrigger)(struct irq_data *data);/* 设置irq的电气触发条件,例如 IRQ_TYPE_LEVEL_HIGH(电平触发) 或 IRQ_TYPE_EDGE_RISING(边缘触发) */int (*irq_set_type)(struct irq_data *data, unsigned int flow_type);/* 通知电源管理子系统,该irq是否可以用作系统的唤醒源 */int (*irq_set_wake)(struct irq_data *data, unsigned int on);void (*irq_bus_lock)(s

29、truct irq_data *data);void (*irq_bus_sync_unlock)(struct irq_data *data);void (*irq_cpu_online)(struct irq_data *data);void (*irq_cpu_offline)(struct irq_data *data);void (*irq_suspend)(struct irq_data *data);void (*irq_resume)(struct irq_data *data);void (*irq_pm_shutdown)(struct irq_data *data);vo

30、id (*irq_calc_mask)(struct irq_data *data);void (*irq_print_chip)(struct irq_data *data, struct seq_file *p);int (*irq_request_resources)(struct irq_data *data);void (*irq_release_resources)(struct irq_data *data);unsigned long flags;3.4、中断服务例程(ISR)中断服务例程用于描述一个设备的中断处理(区别与中断处理函数),每个申请了中断的外部设备都会有一个中断服

31、务例程,其作用就是执行对应设备的中断处理。当多个设备共享IRQ线时,内核会将此IRQ线上所有设备的中断服务例程组织成一个链表并保存在中断描述符中,当此IRQ线产生中断时,中断处理函数会依次执行此IRQ线上的中断服务例程。内核使用struct irqaction描述一个中断服务例程:struct irqaction /* 此中断服务例程的中断处理函数 */ irq_handler_t handler; /* 设备ID,一般用于指向中断处理时需要的数据结构传入handler */ void *dev_id; /* 此中断服务例程在CPU上所对应的设备ID */ void _percpu *percpu_dev_i

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1