- 浏览: 1476571 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (691)
- linux (207)
- shell (33)
- java (42)
- 其他 (22)
- javascript (33)
- cloud (16)
- python (33)
- c (48)
- sql (12)
- 工具 (6)
- 缓存 (16)
- ubuntu (7)
- perl (3)
- lua (2)
- 超级有用 (2)
- 服务器 (2)
- mac (22)
- nginx (34)
- php (2)
- 内核 (2)
- gdb (13)
- ICTCLAS (2)
- mac android (0)
- unix (1)
- android (1)
- vim (1)
- epoll (1)
- ios (21)
- mysql (3)
- systemtap (1)
- 算法 (2)
- 汇编 (2)
- arm (3)
- 我的数据结构 (8)
- websocket (12)
- hadoop (5)
- thrift (2)
- hbase (1)
- graphviz (1)
- redis (1)
- raspberry (2)
- qemu (31)
- opencv (4)
- socket (1)
- opengl (1)
- ibeacons (1)
- emacs (6)
- openstack (24)
- docker (1)
- webrtc (11)
- angularjs (2)
- neutron (23)
- jslinux (18)
- 网络 (13)
- tap (9)
- tensorflow (8)
- nlu (4)
- asm.js (5)
- sip (3)
- xl2tp (5)
- conda (1)
- emscripten (6)
- ffmpeg (10)
- srt (1)
- wasm (5)
- bert (3)
- kaldi (4)
- 知识图谱 (1)
最新评论
-
wahahachuang8:
我喜欢代码简洁易读,服务稳定的推送服务,前段时间研究了一下go ...
websocket的helloworld -
q114687576:
http://www.blue-zero.com/WebSoc ...
websocket的helloworld -
zhaoyanzimm:
感谢您的分享,给我提供了很大的帮助,在使用过程中发现了一个问题 ...
nginx的helloworld模块的helloworld -
haoningabc:
leebyte 写道太NB了,期待早日用上Killinux!么 ...
qemu+emacs+gdb调试内核 -
leebyte:
太NB了,期待早日用上Killinux!
qemu+emacs+gdb调试内核
转 http://blog.csdn.net/ustc_dylan/article/details/6334000?reload
Linux 的softirq机制是与SMP紧密不可分的。为此,整个softirq机制的设计与实现中自始自终都贯彻了一个思想:“谁触发,谁执行”(Who marks,Who runs),也即触发软中断的那个CPU负责执行它所触发的软中断,而且每个CPU都由它自己的软中断触发与控制机制。这个设计思想也使得softirq 机制充分利用了SMP系统的性能和特点。 多个softirq可以并行执行,甚至同一个softirq可以在多个processor上同时执行。
一、softirq的实现
每个softirq在内核中通过struct softirq_action来表示,另外,通过全局属组softirq_vec标识当前内核支持的所有的softirq。
二、softirq处理函数
struct softirq_action结构体中,只有一个函数指针成员action,即指向用户定义的softirq处理函数。当执行时,可以通过如下代码:
softirq_vec[i]->action(i);
一个注册的softirq在执行之前必须被激活,术语称为"raise the softirq"。被激活的softirq通常并不会立即执行,一般会在之后的某个时刻检查当前系统中是否有被pending的softirq,如果有就去执行,Linux内核中检查是否有softirq挂起的检查点主要有以下三类:
(1)硬件中断代码返回的时候
(2)ksoftirqd内核服务线程运行的时候
(3)在一些内核子系统中显示的去检查挂起的softirq
下面重点分析以下do_softirq(),了解Linux内核到底是怎么来处理softirq的。
实际的处理函数为__do_softirq:
三、使用softirq
softirq一般用在对实时性要求比较强的地方,当前的Linux内核中,只有两个子系统直接使用了softirq:网络子系统和块设备子系统。另外,增加新的softirq需要重新编译内核,因此,除非必须需要,最好考虑tasklet和kernel timer是否适合当前需要。
如果必须需要使用softirq,那么需要考虑的一个重要的问题就是新增加的softirq的优先级,默认情况下,softirq的数值越小优先级越高,根据实际经验,新增加的softirq最好在BLOCK_SOFTIRQ和TASKLET_SOFTIRQ之间。
softirq的处理函数通过open_softirq进行注册,此函数接收两个参数,一个是softirq的整数索引,另一个是该softirq对应的处理函数。例如在网络子系统中,注册了如下两个softirq及其处理函数:
open_softirq(NET_TX_SOFTIRQ, net_tx_action);
open_softirq(NET_RX_SOFTIRQ, net_rx_action);
前面提到,软中断处理函数注册后,还需要将该软中断激活,此软中断才能被执行,激活操作是通过raise_softirq函数来实现,在网络子系统中激活代码如下:
这里的__raise_softirq_irqoff和raise_softirq的区别是,前者在事先已经关中断的情况下可以被使用,后者自己完成中断的关闭和恢复。
Linux 的softirq机制是与SMP紧密不可分的。为此,整个softirq机制的设计与实现中自始自终都贯彻了一个思想:“谁触发,谁执行”(Who marks,Who runs),也即触发软中断的那个CPU负责执行它所触发的软中断,而且每个CPU都由它自己的软中断触发与控制机制。这个设计思想也使得softirq 机制充分利用了SMP系统的性能和特点。 多个softirq可以并行执行,甚至同一个softirq可以在多个processor上同时执行。
一、softirq的实现
每个softirq在内核中通过struct softirq_action来表示,另外,通过全局属组softirq_vec标识当前内核支持的所有的softirq。
/* softirq mask and active fields moved to irq_cpustat_t in * asm/hardirq.h to get better cache usage. KAO */ struct softirq_action { void (*action)(struct softirq_action *); }; static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp; Linux内核最多可以支持32个softirq(思考:为什么是32个?),但当前只实现了10个,如下: enum { HI_SOFTIRQ=0, TIMER_SOFTIRQ, NET_TX_SOFTIRQ, NET_RX_SOFTIRQ, BLOCK_SOFTIRQ, BLOCK_IOPOLL_SOFTIRQ, TASKLET_SOFTIRQ, SCHED_SOFTIRQ, HRTIMER_SOFTIRQ, RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */ NR_SOFTIRQS };
二、softirq处理函数
struct softirq_action结构体中,只有一个函数指针成员action,即指向用户定义的softirq处理函数。当执行时,可以通过如下代码:
softirq_vec[i]->action(i);
一个注册的softirq在执行之前必须被激活,术语称为"raise the softirq"。被激活的softirq通常并不会立即执行,一般会在之后的某个时刻检查当前系统中是否有被pending的softirq,如果有就去执行,Linux内核中检查是否有softirq挂起的检查点主要有以下三类:
(1)硬件中断代码返回的时候
/* * Exit an interrupt context. Process softirqs if needed and possible: */ void irq_exit(void) { account_system_vtime(current); trace_hardirq_exit(); sub_preempt_count(IRQ_EXIT_OFFSET); if (!in_interrupt() && local_softirq_pending()) invoke_softirq(); rcu_irq_exit(); #ifdef CONFIG_NO_HZ /* Make sure that timer wheel updates are propagated */ if (idle_cpu(smp_processor_id()) && !in_interrupt() && !need_resched()) tick_nohz_stop_sched_tick(0); #endif preempt_enable_no_resched(); }
(2)ksoftirqd内核服务线程运行的时候
static int run_ksoftirqd(void * __bind_cpu) { ... ... while (local_softirq_pending()) { /* Preempt disable stops cpu going offline. If already offline, we'll be on wrong CPU: don't process */ if (cpu_is_offline((long)__bind_cpu)) goto wait_to_die; do_softirq(); preempt_enable_no_resched(); cond_resched(); preempt_disable(); rcu_note_context_switch((long)__bind_cpu); } preempt_enable(); set_current_state(TASK_INTERRUPTIBLE); } __set_current_state(TASK_RUNNING); return 0; ... ... }
(3)在一些内核子系统中显示的去检查挂起的softirq
int netif_rx_ni(struct sk_buff *skb) { int err; preempt_disable(); err = netif_rx(skb); if (local_softirq_pending()) do_softirq(); preemptenable(); return err; }
下面重点分析以下do_softirq(),了解Linux内核到底是怎么来处理softirq的。
asmlinkage void do_softirq(void) { unsigned long flags; struct thread_info *curctx; union irq_ctx *irqctx; u32 *isp; if (in_interrupt()) /*首先判断是否在中断上下文中*/ return; local_irq_save(flags); if (local_softirq_pending()) { curctx = current_thread_info(); irqctx = __get_cpu_var(softirq_ctx); irqctx->tinfo.task = curctx->task; irqctx->tinfo.previous_esp = current_stack_pointer; /* build the stack frame on the softirq stack */ isp = (u32 *) ((char *)irqctx + sizeof(*irqctx)); call_on_stack(__do_softirq, isp); /* * Shouldnt happen, we returned above if in_interrupt(): */ WARN_ON_ONCE(softirq_count()); } local_irq_restore(flags); }
实际的处理函数为__do_softirq:
asmlinkage void __do_softirq(void) { struct softirq_action *h; __u32 pending; int max_restart = MAX_SOFTIRQ_RESTART; /*不启动ksoftirqd之前,最大的处理softirq的次数,经验值*/ int cpu; /*取得当前被挂起的softirq,同时这里也解释了为什么Linux内核最多支持32个softirq,因为pending只有32bit*/ pending = local_softirq_pending(); account_system_vtime(current); __local_bh_disable((unsigned long)__builtin_return_address(0)); lockdep_softirq_enter(); cpu = smp_processor_id(); restart: /* Reset the pending bitmask before enabling irqs */ set_softirq_pending(0);/*获取了pending的softirq之后,清空所有pending的softirq的标志*/ local_irq_enable(); h = softirq_vec; do { if (pending & 1) { /*从最低位开始,循环右移逐位处理pending的softirq*/ int prev_count = preempt_count(); kstat_incr_softirqs_this_cpu(h - softirq_vec); trace_softirq_entry(h, softirq_vec); h->action(h); /*执行softirq的处理函数*/ trace_softirq_exit(h, softirq_vec); if (unlikely(prev_count != preempt_count())) { printk(KERN_ERR "huh, entered softirq %td %s %p" "with preempt_count %08x," " exited with %08x?/n", h - softirq_vec, softirq_to_name[h - softirq_vec], h->action, prev_count, preempt_count()); preempt_count() = prev_count; } rcu_bh_qs(cpu); } h++; pending >>= 1; /*循环右移*/ } while (pending); local_irq_disable(); pending = local_softirq_pending(); if (pending && --max_restart) /*启动ksoftirqd的阈值*/ goto restart; if (pending) /*启动ksoftirqd去处理softirq,此时说明pending的softirq比较多,比较频繁,上面的处理过程中,又不断有softirq被pending*/ wakeup_softirqd(); lockdep_softirq_exit(); account_system_vtime(current); _local_bh_enable(); }
三、使用softirq
softirq一般用在对实时性要求比较强的地方,当前的Linux内核中,只有两个子系统直接使用了softirq:网络子系统和块设备子系统。另外,增加新的softirq需要重新编译内核,因此,除非必须需要,最好考虑tasklet和kernel timer是否适合当前需要。
如果必须需要使用softirq,那么需要考虑的一个重要的问题就是新增加的softirq的优先级,默认情况下,softirq的数值越小优先级越高,根据实际经验,新增加的softirq最好在BLOCK_SOFTIRQ和TASKLET_SOFTIRQ之间。
softirq的处理函数通过open_softirq进行注册,此函数接收两个参数,一个是softirq的整数索引,另一个是该softirq对应的处理函数。例如在网络子系统中,注册了如下两个softirq及其处理函数:
open_softirq(NET_TX_SOFTIRQ, net_tx_action);
open_softirq(NET_RX_SOFTIRQ, net_rx_action);
前面提到,软中断处理函数注册后,还需要将该软中断激活,此软中断才能被执行,激活操作是通过raise_softirq函数来实现,在网络子系统中激活代码如下:
/* Called with irq disabled */ static inline void ____napi_schedule(struct softnet_data *sd, struct napi_struct *napi) { list_add_tail(&napi->poll_list, &sd->poll_list); __raise_softirq_irqoff(NET_RX_SOFTIRQ); }
这里的__raise_softirq_irqoff和raise_softirq的区别是,前者在事先已经关中断的情况下可以被使用,后者自己完成中断的关闭和恢复。
- Segmentation_fault_in_Linux.pdf (309.3 KB)
- 下载次数: 0
发表评论
-
xl2tp 备份
2019-09-24 16:25 6892019年9月24日更新: 注意,需要开启firewall ... -
sdl笔记
2019-01-31 17:19 732sdl教程教程 https://github.com/Twin ... -
tinyemu
2019-01-24 17:59 1432参考https://bellard.org/jslinux/t ... -
aws搭建xl2tp给iphone使用
2018-12-26 21:37 18902019年12月26日 可以参考原来的配置 https:// ... -
consul的基本使用
2017-06-27 11:13 1399### 安装 [centos7上consul的安装](ht ... -
lvs的helloworld
2017-06-13 20:36 596###################lvs######### ... -
系统调用的helloworld
2017-05-04 16:14 632《2.6内核标准教程》 p293 #include < ... -
bitcoin和cgminer的安装
2017-04-05 22:45 1958参考 http://blog.csdn.net/rion_ch ... -
ceph安装和常用命令
2017-03-21 21:55 953/etc/hosts ssh-keygen ssh-copy- ... -
mobile terminal 笔记
2016-12-02 15:35 624找出旧的iphone4 越狱之后可以变个小操作系统 mobi ... -
socket基础和select(python)
2016-06-14 17:21 1799上接 c语言的socket基础ht ... -
socket基础(c语言)
2016-06-14 16:45 994不使用select 普通的基础socket连接,对多个客户端的 ... -
ffmpeg+nginx 的直播(2,直播摄像头和麦克风)
2016-05-28 20:21 4357假设我的服务器是centos7 192.168.139.117 ... -
ffmpeg+nginx 的直播(1,直播播放的视频文件)
2016-05-26 17:11 659164位操作系统centos7 ############ 1.一 ... -
socat和netcat(nc)
2016-04-29 22:36 1742转 原文链接: http://www.wenquan.name ... -
neutron基础九(qemu nat网络)
2016-02-06 17:21 1621接上基础八,kvm透传nested忽略 1.在主机ce ... -
neutron基础八(qemu 桥接网络)
2016-02-06 13:13 1542qemu的桥接和nat的qemu启动命令是一样的,但是后续的脚 ... -
neutron基础七(qemu tap)
2016-02-02 17:02 1030使用qemu 建立个虚拟机 然后用tap设备, 根据基础六,t ... -
neutron基础六(bridge fdb)
2016-01-28 18:30 2263转发表 在三台机器上建立三个namespace 192.16 ... -
南北流量
2016-01-23 23:26 1822一、三层网络架构: 接入层:负责服务器的接入和隔离 汇聚层:汇 ...
相关推荐
另外,内核源码中包含了大量的软中断处理函数,通过阅读和分析这些代码,可以深入理解软中断的具体实现。 在修改内核的软中断部分时,需要格外小心,因为这直接影响到系统的稳定性和性能。任何改动都应遵循内核开发...
对于开发者来说,了解这些源码有助于理解系统的工作原理,优化性能监控工具,甚至排查系统性能问题。 在Linux系统中,CPU占用率可以通过读取/proc/stat文件获取。这个文件包含了系统运行的各种统计信息,包括CPU...
### Tasklet原理与源码分析 #### 一、Tasklet基本概念 Tasklet是一种用于Linux内核中的中断下半部机制,它主要建立在softirq的基础上。这种机制在本质上与softirq相似,但提供了更为简单的编程接口和较为宽松的锁...
通过对内核源码的分析,我们可以深入了解IMQ的工作原理和技术细节。 首先,数据包在协议栈中的截留和重新注入是通过NF_QUEUE机制实现的。NF_QUEUE是一个内核的Netfilter模块,它提供了一种将数据包传递给用户空间...
在阅读和理解这个驱动代码时,需要熟悉Linux内核编程接口、网络协议栈的工作原理以及相关的硬件知识。此外,理解设备的硬件手册也是必要的,因为它们详细描述了设备的寄存器布局和操作方法。 总的来说,cs8900 ...
本文件旨在深入分析Linux操作系统的源代码,通过对核心部分的解读来帮助读者更好地理解Linux内核的工作原理。 #### 二、Linux操作系统特性 1. **抢先式多任务处理**:Linux支持真正的多任务处理,能够同时运行多个...
在Linux环境下,驱动程序是开源的,开发者可以通过阅读和修改源代码来理解其工作原理,甚至根据需要进行定制。这份"Linux设备驱动+源代码"的资料,对于学习和研究Linux内核、驱动开发以及硬件交互具有极大的价值。 ...
5.5.1 softirq延迟处理 234 5.5.2 tasklet延迟处理 239 5.5.3 work queue延迟处理 242 第6章 时间度量 249 6.1 硬件支持 250 6.1.1 实时钟RTC 250 6.1.2 系统时钟 250 6.2 软件架构 252 6.2.1 ...
5.5.1 softirq延迟处理 234 5.5.2 tasklet延迟处理 239 5.5.3 work queue延迟处理 242 第6章 时间度量 249 6.1 硬件支持 250 6.1.1 实时钟RTC 250 6.1.2 系统时钟 250 6.2 软件架构 252 6.2.1 ...
5.5.1 softirq延迟处理 234 5.5.2 tasklet延迟处理 239 5.5.3 work queue延迟处理 242 第6章 时间度量 249 6.1 硬件支持 250 6.1.1 实时钟RTC 250 6.1.2 系统时钟 250 6.2 软件架构 252 6.2.1 ...
5.5.1 softirq延迟处理 234 5.5.2 tasklet延迟处理 239 5.5.3 work queue延迟处理 242 第6章 时间度量 249 6.1 硬件支持 250 6.1.1 实时钟RTC 250 6.1.2 系统时钟 250 6.2 软件架构 252 6.2.1 ...
5.5.1 softirq延迟处理 234 5.5.2 tasklet延迟处理 239 5.5.3 work queue延迟处理 242 第6章 时间度量 249 6.1 硬件支持 250 6.1.1 实时钟RTC 250 6.1.2 系统时钟 250 6.2 软件架构 252 6.2.1 ...
5.5.1 softirq延迟处理 234 5.5.2 tasklet延迟处理 239 5.5.3 work queue延迟处理 242 第6章 时间度量 249 6.1 硬件支持 250 6.1.1 实时钟RTC 250 6.1.2 系统时钟 250 6.2 软件架构 252 6.2.1 ...
5.5.1 softirq延迟处理 234 5.5.2 tasklet延迟处理 239 5.5.3 work queue延迟处理 242 第6章 时间度量 249 6.1 硬件支持 250 6.1.1 实时钟RTC 250 6.1.2 系统时钟 250 6.2 软件架构 252 6.2.1 ...
5.5.1 softirq延迟处理 234 5.5.2 tasklet延迟处理 239 5.5.3 work queue延迟处理 242 第6章 时间度量 249 6.1 硬件支持 250 6.1.1 实时钟RTC 250 6.1.2 系统时钟 250 6.2 软件架构 252 6.2.1 ...
2. **API函数**: `hrtimer_start_range_ns`、`hrtimer_forward`、`hrtimer_get_softirq`等函数的声明,提供了操作hrtimer的接口。 3. **枚举类型**: 如`hrtimer_mode`定义了定时器的运行模式,如单次、周期性等。 ...