把握linux内核设计思想(三):下半部机制之软中断
中断处理程序以异步方式执行,其会打断其它重要代码,其执行时该中断同级的其它中断会被屏蔽,而且当前处理器上全部其它中断都有可能会被屏蔽掉,还有中断处理程序不能堵塞,所以中断处理须要尽快结束。因为中断处理程序的这些缺陷,导致了中断处理程序仅仅是整个硬件中断处理流程的一部分,对于那些对时间要求不高的任务。留给中断处理流程的另外一部分,也就是本节要讲的中断处理流程的下半部。
一般对时间很敏感、和硬件相关、要保证不被其他中断(特别是同样的中断)打断的这些任务放在中断处理程序中运行。其他任务考虑放在下半部运行。
asmlinkage void __init start_kernel(void)
{
char * command_line;
extern struct kernel_param __start___param[], __stop___param[]; smp_setup_processor_id();
......
softirq_init();//初始化软中断
...... /* Do the rest non-__init'ed, we're now alive */
rest_init();
}
void __init softirq_init(void)
{
int cpu; for_each_possible_cpu(cpu) {
int i; per_cpu(tasklet_vec, cpu).tail =
&per_cpu(tasklet_vec, cpu).head;
per_cpu(tasklet_hi_vec, cpu).tail =
&per_cpu(tasklet_hi_vec, cpu).head;
for (i = 0; i < NR_SOFTIRQS; i++)
INIT_LIST_HEAD(&per_cpu(softirq_work_list[i], cpu));
} register_hotcpu_notifier(&remote_softirq_cpu_notifier); //此处注冊两个软中断
open_softirq(TASKLET_SOFTIRQ, tasklet_action); open_softirq(HI_SOFTIRQ, tasklet_hi_action);
}
nr:软中断类型 action:软中断处理函数
void open_softirq(int nr, void (*action)(struct softirq_action *))
{
softirq_vec[nr].action = action;
}
struct softirq_action
{
void (*action)(struct softirq_action *);
}
static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;
从上面的代码中,我们能够看到:open_softirq()中.事实上就是对softirq_vec数组的nr项赋值.softirq_vec是一个32元素的数组,实际上linux内核仅仅使用了几项:
/* PLEASE, avoid to allocate new softirqs, if you need not _really_ high
frequency threaded job scheduling. For almost all the purposes
tasklets are more than enough. F.e. all serial device BHs et
al. should be converted to tasklets, not to softirqs.
*/ 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
};
有关网络子系统内容可參考文章:http://blog.csdn.net/shallnet/article/details/26269781
asmlinkage void do_softirq(void) { __u32 pending; unsigned long flags; //假设在硬件中断环境中就退出,软中断不能够在硬件中断上下文或者是在软中断环境中使用,使用in_interrupt()来防止软中断嵌套。和抢占硬中断环境。
if (in_interrupt()) return; //禁止本地中断 local_irq_save(flags); pending = local_softirq_pending();
//假设有软中断要处理,则进入__do_softirq()
if (pending) __do_softirq(); local_irq_restore(flags);
asmlinkage void __do_softirq(void)
{
struct softirq_action *h;
__u32 pending;
int max_restart = MAX_SOFTIRQ_RESTART;
int cpu; pending = local_softirq_pending(); //pending用于保留待处理软中断32位位图
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); local_irq_enable(); h = softirq_vec; do {
if (pending & 1) { //假设pending第n位被设置为1,那么处理第n位相应类型的软中断
int prev_count = preempt_count();
kstat_incr_softirqs_this_cpu(h - softirq_vec); trace_softirq_entry(h, softirq_vec);
h->action(h); //运行软中断处理函数
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; //pending右移一位,循环检查其每一位
} while (pending); //直到pending变为0,pending最多32位,所以循环最多运行32次。 local_irq_disable(); pending = local_softirq_pending();
if (pending && --max_restart)
goto restart; if (pending)
wakeup_softirqd(); lockdep_softirq_exit(); account_system_vtime(current);
_local_bh_enable();
}
把握linux内核设计思想(三):下半部机制之软中断的更多相关文章
- 把握linux内核设计思想系列【转】
转自:http://blog.csdn.net/shallnet/article/details/47734053 版权声明:本文为博主原创文章,未经博主允许不得转载.如果您觉得文章对您有用,请点击文 ...
- 把握linux内核设计思想系列
[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途] 本专栏分析linux内核的设计实现,包含系统调用.中断.下半部机制.时间管理. ...
- 把握linux内核设计思想(五):下半部机制之工作队列及几种机制的选择
[版权声明:尊重原创.转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途] 工作队列是下半部的第二种将工作推后运行形式.和软中断.task ...
- 把握linux内核设计思想(七):内核定时器和定时运行
[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途] 前面章节说到了把工作推后到除如今以外的时间运行的机制是下半部机 ...
- 把握linux内核设计思想(十三):内存管理之进程地址空间
[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet.文章仅供学习交流,请勿用于商业用途] 进程地址空间由进程可寻址的虚拟内存组成,Linux 的虚拟地址空间为0~4G字 ...
- 把握linux内核设计思想(二):硬中断及中断处理
[版权声明:尊重原创.转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途] 操作系统负责管理硬件设备.为了使系统和硬件设备的协同工作不减少机器性能.系统和 ...
- 把握linux内核设计思想(十二):内存管理之slab分配器
[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流.请勿用于商业用途] 上一节最后说到对于小内存区的请求,假设採用伙伴系统来进行分配,则会在页内产生非 ...
- Linux内核设计第三周——构造一个简单的Linux系统
Linux内核设计第三周 ——构造一个简单的Linux系统 一.知识点总结 计算机三个法宝: 存储程序计算机 函数调用堆栈 中断 操作系统两把宝剑: 中断上下文的切换 进程上下文的切换 linux内核 ...
- Linux内核设计第三周学习总结 跟踪分析Linux内核的启动过程
陈巧然 原创作品 转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验步骤 登陆实验楼虚 ...
随机推荐
- ActiveMQ学习笔记(21)----ActiveMQ集成Tomcat
1. 监控和管理Broker Web Console 方式:直接访问ActiveMQ的管理页面:http://localhost:8161/admin,默认的用户名和密码是admin/admin.具体 ...
- SQL 自动记录存储过程,表,函数的创建修改和删除 -相当于SVN一样
在项目开发过程中,项目管理者通常都很希望对项目的开发进展有一个日志的记录.代码的记录和管理可以通过TFS或者VSS等工具去管理.但是数据库却没有记录开发日志这一功能.这在实际开发中很不方便, ...
- 妙用$.extend
在js中,我们有时需要复制一个对象的值,而不是复制它的引用的时候,可以使用jquery的$.extend方法,简单代码如下 <script> var a = { "name&qu ...
- LAMP 建立 Wordpress 站点 Linux Apache MariaDB PHP
使用LAMP建立Wordpress, 要求如下: 准备工作: VMware 14 CentOS 7.4 最小化 安装镜像 Wordpress 安装包, 下载 预热: 使用VMware新建4台虚拟机, ...
- Object-C,数组NSArray
晚上回来,写了2个iOS应用程序. 就是在界面中,展示标签.一种是手动构造界面,然后绑定事件.另外一种是,使用自带的界面作为容器,但是手动向里面放其它界面元素. 书中的观点是,使用图形化界面,构造界面 ...
- 题解 洛谷 P3381 【【模板】最小费用最大流】
发了网络流,再来一发费用流 能做费用流的,网络流自然做得来,但在这还是不要脸的安利一下自己的博客(里面也有网络流的题解): 点我 扯远了... 费用流,就是在不炸水管的情况下求源点到汇点的最小费用. ...
- hadoop 2.6.0 LightWeightGSet源码分析
LightWeightGSet的作用用一个数组来存储元素,而且用链表来解决冲突.不能rehash.所以内部数组永远不用改变大小.此类不支持空元素. 此类也不是线程安全的.有两个类型參数.第一个用于查找 ...
- c++_benchMark_vector_list_deque
title: c++_benchMark_vector_list_deque date: 2015-08-01 22:32:39 作者:titer1 + ZhangYu 出处:www.drysalte ...
- Android Studio JNI体验
近期项目中须要调用c/c++的实现,Android是支持JNI的.所以体验了一下JNI的全过程 1. 前期环境准备 (1) 下载NDK,网址是https://developer.android.com ...
- Caused by: java.lang.ClassNotFoundException: com.njupt.libgdxbase.MainActivity
在使用libgdx来开发游戏时.假设遇到这样的问题.非常可能是由于你没有在libgdx的项目中导入Android的现骨干jar包导致的. 解决方法例如以下: 右击项目---"build pa ...