百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

linux内核中断底半部之软中断

toyiye 2024-06-21 12:26 13 浏览 0 评论

软中断介绍

一、 软中断产生的原因

软中断:用于有效的实现内核的延期操作,也是底半部机制tasklet的基础

二、 数据结构

1)softirq_action

该结构是软中断的核心数据结构,代表软中断处理函数。

struct softirq_action

{

void (*action)(struct softirq_action *);

};

2)下面是软中断的类型,目前支持10个软中断类型。

/* 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

};

3)softirq_vec

该数组存储了已注册的软中断类型对应的处理函数,该数组非常重要

static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;

4)irq_cpustat_t

该结构体主要记录哪一个软中断需要进行处理

typedef struct {

unsigned int __softirq_pending;

} ____cacheline_aligned irq_cpustat_t;

三、 软中断的注册

要在内核中使用一个软中断,首先要进行注册,所谓注册,其实就是在数组softirq_vec中增加相应软中断的处理函数,调用函数定义如下:

/*

注册一个软中断,即在软中断向量数据中,增加软中断number为nr的处理函数

*/

void open_softirq(int nr, void (*action)(struct softirq_action *))

{

softirq_vec[nr].action = action;

}

四、 启动软中断

如果要启动某个软中断,则需要置位irq_stat[cpu].__softirq_pending中的相应位,而后续的处理工作则由do_softirq处理。

而设置__softirq_pending的操作则由函数__raise_softirq_irqoff来实现。

可以通过以下两种方法启动软中断:

1)在中断上下文中,通过调用函数raise_softirq,置位irq_stat[cpu].__softirq_pending中的相应软中断位,则会在中断结束后在函数irq_exit中调用invoke_softirq,实现软中断处理

2)在非中断上下文中,通过调用raise_softirq_irqoff,置位irq_stat[cpu].__softirq_pending中的相应软中断位,并唤醒软中断守护进程,通过软中断守护进程实现软中断的处理

3)在__do_softirq中,当该函数执行完时还有未决的软中断,则唤醒软中断守护进程,由软中断守护进程继续处理未决的软中断

以上3种方法中,不管是通过调用函数invoke_softirq,还是通过软中断守护进程来处理软中断,最终都会调用函数do_softirq、__do_softirq。

do_softirq主要完成以下工作

1) 首先判断当前是否在中断上下文中,若是则直接返回

2) 关闭irq,读取当前cpu的irq_stat[cpu].__softirq_pending

3) 判断__softirq_pending的值是否为0,若不为0则说明有软中断待处理,则调用__do_softirq

asmlinkage void do_softirq(void)

{

__u32 pending;

unsigned long flags;

if (in_interrupt())

return;

local_irq_save(flags);

pending = local_softirq_pending();

if (pending)

__do_softirq();

local_irq_restore(flags);

}

__do_softirq的定义如下:

其主要完成的工作有:

1) 获取irq_stat[cpu].__softirq_pending的值

2) 重置irq_stat[cpu].__softirq_pending的值为0,并开启软中断

3) 获取软中断向量数据softirq_vec

4) 在一个while循环中,对于每一个未处理的软中断,执行softirq_vec中相对应的action处理函数

5) 关闭中断,重新读取irq_stat[cpu].__softirq_pending的值,若该值不为0则

6) 在重复执行的次数没有超过MAX_SOFTIRQ_RESTART,且irq_stat[cpu].__softirq_pending的值不为0时,重新执行上述2、3、4、5的操作

7) 若已超过MAX_SOFTIRQ_RESTART,则调用wakeup_softirqd,唤醒软中断守护进程,由软中断守护进程继续处理

#define MAX_SOFTIRQ_RESTART 10

asmlinkage void __do_softirq(void)

{

struct softirq_action *h;

__u32 pending;

int max_restart = MAX_SOFTIRQ_RESTART;

int cpu;

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);

local_irq_enable();

h = softirq_vec;

do {

if (pending & 1) {

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;

} while (pending);

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();

}

相关推荐

Python 可视化工具包(python常见的可视化工具)

喜欢用Python做项目的小伙伴不免会遇到这种情况:做图表时,用哪种好看又实用的可视化工具包呢?本文将介绍一些常用的Python可视化包,包括这些包的优缺点以及分别适用于什么样的场景。这篇文章...

Python的GPU编程实例——近邻表计算

目录技术背景...

python算法体验-3.python实现欧式距离的三种方式

欧式距离也称欧几里得距离,是最常见的距离度量,衡量的是多维空间中两个点之间的绝对距离。欧式距离源自N维欧氏空间中两点...

python实现Lasso回归分析(特征筛选、建模预测)

实现功能:...

python语言检测模块langid、langdetect使用

本文首发地址:https://blog.csdn.net/Together_CZ/article/details/86678423欢迎关注我的博客【Together_CZ】,我是沂水寒城!之前使用数据...

7天学会Python最佳可视化工具Seaborn(一):可视化变量间的关系

众所周知,Seaborn“可能”是Python下最友好、易用的可视化工具了,可视化效果也非常好。但是截止目前,并没有一份中文教程供广大国内Python使用者查阅学习。怎么能因为语言的问题,让大家错过这...

在Python中使用K-Means聚类和PCA主成分分析进行图像压缩

各位读者好,在这篇文章中我们尝试使用sklearn库比较k-means聚类算法和主成分分析(PCA)在图像压缩上的实现和结果。压缩图像的效果通过占用的减少比例以及和原始图像的差异大小来评估。图像压...

OpenCV-Python 相机校准 | 四十九

目标在本节中,我们将学习由相机引起的失真类型,如何找到相机的固有和非固有特性如何根据这些特性使图像不失真基础一些针孔相机会给图像带来明显的失真。两种主要的变形是径向变形和切向变形。径向变形会导致直线出...

python数据预处理技术(python 数据预处理)

在真实世界中,经常需要处理大量的原始数据,这些原始数据是机器学习算法无法理解的。为了让机器学习算法理解原始数据,需要对数据进行预处理。我们运行anaconda集成环境下的“jupyternotebo...

【Python可视化系列】一文教你绘制不同类型散点图(理论+源码)

这是...

OpenCV-Python 特征匹配 | 四十四

目标在本章中,我们将看到如何将一个图像中的特征与其他图像进行匹配。我们将在OpenCV中使用Brute-Force匹配器和FLANN匹配器Brute-Force匹配器的基础蛮力匹配器很简单。它使用第一...

实战python中Random模块使用(python中的random模块)

一、random模块简介Python标准库中的random函数,可以生成随机浮点数、整数、字符串,甚至帮助你随机选择列表序列中的一个元素,打乱一组数据等。要在Python中使用random模块,只需要...

Python随机模块22个函数详解(python随机函数的应用)

随机数可以用于数学,游戏,安全等领域中,还经常被嵌入到算法中,用以提高算法效率,并提高程序的安全性。平时数据分析各种分布的数据构造也会用到。random模块,用于生成伪随机数,之所以称之为伪随机数,是...

说冲A就冲A,这个宝藏男孩冯俊杰我pick了

爱奇艺新上架了一部网剧叫《最后一个女神》。有个惊人的发现,剧里男三居然是《青春有你》的训练生冯俊杰。剧组穷,戏服没几件,冯俊杰几乎靠一件背背佳撑起了整部剧。冯俊杰快速了解一下。四川人,来自觉醒东方,人...

唐山打人嫌犯陈继志去医院就医的背后,隐藏着三个精心设计的步骤

种种迹象表明,陈继志这帮人对处理打人之后的善后工作是轻车驾熟的,他们想实施的计划应该是这样的:首先第一步与伤者进同一家医院做伤情鉴定,鉴定级别最好要比对方严重,于是两位女伤者被鉴定为轻伤,他们就要求医...

取消回复欢迎 发表评论:

请填写验证码