进程上下文和中断上下文

文章目录

  • 进程的preempt_count变量
    • thread_info
    • preempt_count
  • hardirq相关
  • softirq相关
  • 上下文

原文链接: https://zhuanlan.zhihu.com/p/88883239

进程的preempt_count变量

thread_info

在内核中,上下文的设置和判断接口可以参考 include/linux/preempt.h 文件,整个机制的实现都依赖于一个变量:preempt_count,这个变量被定义在进程struct task_struct的 thread_info域中 ,也就是线程描述符中,线程描述符被放在内核栈的底部,在内核中可以通过 current_thread_info() 接口来获取进程的 thread_info:

static inline struct thread_info *current_thread_info(void)
{return (struct thread_info *)(current_stack_pointer & ~(THREAD_SIZE - 1));
}register unsigned long current_stack_pointer asm ("sp");

其中 THREAD_SIZE 通常的大小为 4K 或者 8K,取出当前内核栈的 sp 指针,通过简单地屏蔽掉 sp 的低 13 位,就可以获取到 thread_info 的基地址。

在 arm 中,preempt_count 是 per task 的变量,而在 x86 中,preempt_count 是 percpu 类型的变量。

preempt_count

请添加图片描述
作为控制上下文的变量, preempt_count 是 int 型,一共 32 位。通过设置该变量不同的位来设置内核中的上下文标志,包括硬中断上下文、软中断上下文、进程上下文等,通过判断该变量的值就可以判断当前程序所属的上下文状态。

整个 preempt_count 被分为几个部分:

  • bit 0-7:用于记录关闭调度的次数。中断上下文中,调度是关闭的,不会发生进程的切换,可以使用preempt_disable()来显示地关闭调度,关闭次数由第0到7个bits组成的preemption count(注意不是preempt count)来记录。每使用一次preempt_disable(),preemption count的值就会加1,使用preempt_enable()则会让preemption count的值减1。
  • bit 8-15:描述软中断的标志位,如果softirq count的值为正数,说明现在正处于softirq上下文中,因为软中断在单个CPU上是不会嵌套执行的,所以只需要用第8位就可以用来判断当前是否处于软中断的上下文中,其他的9-15位用于记录关闭软中断的次数
  • bit 16-19:描述硬中断嵌套次数,在老版本的linux 上支持中断的嵌套,但是自从 2.6 版本之后内核就不再支持中断嵌套,所以其实只用到了一位,如果这部分为正数表示在硬件中断上下文,为 0 则表示不在。
  • bit20 :用于指示 NMI 中断,只有两个状态:发生并处理 NMI 中断置 1,退出中断清除。
  • 其它 bit :没有使用到,保留

hardirq相关

preempt_count中的第16到19个bit表示hardirq count,它记录了进入hardirq/top half的嵌套次数,在这篇文章介绍的do_IRQ()中,irq_enter()用于标记hardirq的进入,此时hardirq count的值会加1。irq_exit()用于标记hardirq的退出,hardirq count的值会相应的减1。如果hardirq count的值为正数,说明现在正处于hardirq上下文中,代码中可借助in_irq()宏实现快速判断。注意这里的命名是"in_irq"而不是"in_hardirq"。

#define hardirq_count()	 (preempt_count() & HARDIRQ_MASK)
#define in_irq()  (hardirq_count())

hardirq count占据4个bits,理论上可以表示16层嵌套,但现在Linux系统并不支持hardirq的嵌套执行,所以实际使用的只有1个bit。

softirq相关

preempt_count中的第8到15个bit表示softirq count,它记录了进入softirq的嵌套次数,如果softirq count的值为正数,说明现在正处于softirq上下文中。由于softirq在单个CPU上是不会嵌套执行的,因此和hardirq count一样,实际只需要一个bit(bit 8)就可以了。但这里多出的7个bits并不是因为历史原因多出来的,而是另有他用。

这个"他用"就是表示在进程上下文中,为了防止进程被softirq所抢占,关闭/禁止softirq的次数,比如每使用一次local_bh_disable(),softirq count高7个bits(bit 9到bit 15)的值就会加1,使用local_bh_enable()则会让softirq count高7个bits的的值减1。

代码中可借助in_softirq()宏快速判断当前是否在softirq上下文:

#define softirq_count()  (preempt_count() & SOFTIRQ_MASK)
#define in_softirq()	 (softirq_count())

上下文

不管是hardirq上下文还是softirq上下文,都属于我们俗称的中断上下文(interrupt context)。
请添加图片描述
为此,有一个名为in_interrupt()的宏专门用来判断当前是否在中断上下文中。

#define irq_count()	 (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK | NMI_MASK))			 
#define in_interrupt()  (irq_count())

与中断上下文相对应的就是俗称的进程上下文(process context)

#define in_task()  (!(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_OFFSET | NMI_MASK)))			   

需要注意的是,并不是只有进程才会处在process context,内核线程依然可以运行在process context。
在中断上下文中,调度是关闭的,不会发生进程的切换,这属于一种隐式的禁止调度,而在代码中,也可以使用preempt_disable()来显示地关闭调度,关闭次数由第0到7个bits组成的preemption count(注意不是preempt count)来记录。每使用一次preempt_disable(),preemption count的值就会加1,使用preempt_enable()则会让preemption count的值减1。preemption count占8个bits,因此一共可以表示最多256层调度关闭的嵌套。

处于中断上下文,或者显示地禁止了调度,preempt_count()的值都不为0,都不允许睡眠/调度的发生,这两种场景被统称为atomic上下文,可由in_atomic()宏给出判断。

#define in_atomic()	(preempt_count() != 0)

中断上下文、进程上下文和atomic上下文的关系大概可以表示成这样:
请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/379514.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

标题:凑算式

标题:凑算式 这个算式中AI代表19的数字,不同的字母代表不同的数字。 比如: 68/3952/714 就是一种解法, 53/1972/486 是另一种解法。 这个算式一共有多少种解法? 注意:你提交应该是个整数,不要…

Linux内存地址管理

文章目录系统内存布局内核地址的低端和高端内存概念低端内存高端内存地址转换和MMULinux中的四级分页模型虚拟地址字段页表处理将虚拟地址转换物理地址Linux系统中的每个内存地址都是虚拟的,它们不直接指向任何物理内存地址。每当访问内存位置时,可以执行…

录制caf 转 mp3

编译需要使用的 lame库http://www.cocoachina.com/bbs/read.php?tid108237参考的文章http://blog.csdn.net/ysy441088327/article/details/7392842说起来,我一直在找一个音频转换成mp3的方法。一年前,我成功编译出了一个lame for armv7的库。苦于不会使…

開發記要 詭異的變量

告別繁體文盲,從寫blog開始 Variable命名很重要,有多重要,看看.net和java的加密就知道, 都是把variable改到一塌糊塗,你想看看都沒門. 但是這幾天看遺留系統的代碼,真是大開眼界。 我一直以為別人寫a,b,c,d這些單字節variable已經很過分。直到我看到以下這幾個&#xff0…

排序算法---快速排序、堆排序、冒泡排序

排序算法1 快速排序代码实现stdlib库快排2 堆排序堆排序的基本思想如何构造一个大顶堆排序3 冒泡排序1 快速排序 文章原地址:https://blog.csdn.net/morewindows/article/details/6684558 快速排序的平均时间复杂度是0(NlogN),它采用了一种分治的策略&a…

项目总结:华南师范大学校园开发教育android客户端总结

忽略之前小打小闹,这个项目算是我的第一个项目--SCNU的网络公选课的android版本的客户端。项目是从5月中旬开始的,中间经历了几个星期的复习考试时间,到现在可以说是完工了吧(或许还有写细节要修改)。这个项目带给我蛮…

Linux系统编程---守护进程

1 守护进程的概述 Daemon(守护进程)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。它不需要用户输入就能运行而且提供某种服务,不是对整个系统就是对某个用户程序提供服务。Linux系统的大…

邮箱服务器

一.邮箱服务器的基本概念 邮件的客户端:可以只安装在电脑上(C/S)的也可以是网页形式(B/S)的 邮件服务器:起到邮件的接受与推送的作用 邮件发送的协议: 协议:就是数据传输…

类加载器

一、类加载器 1,什么是类加载器? 类加载器就是用来加载字节码文件 2,类加载器的种类有哪些? 1)BootStrap:引导类加载器:加载都是最基础的文件 2)ExtClassLoader:扩展类加…

算法---链表

文章目录反转链表合并两个有序链表删除重复元素反转链表 反转链表包括两种,反转全部元素或者反转部分元素。在这里,我们约定:数据元素类型是struct LinkNode,要反转链表的第一个节点是head,head的前面一个节点是pre&a…

SSM

二、环境设置(MyEclipse) 1,字体设置 window–>Preference->General->Appearance->Colors and Fonts->Basic Text->Font 2,workspace字符集设置 window–>Preference->General->Appearance->W…

设计模式--Strategy 策略模式

所谓策略模式(Strategy Pattern),就是将策略 (算法) 封装为一个对象,易于相互替换,如同 USB 设备一样可即插即用;如果将策略、具体的算法和行为,编码在某个类或客户程序内部,将导至事后的修改和扩展不易。 …

打开eclipse出现Failed to load the JNI shared library “D:\java\jdk\bin\...\jre\bin\server\jvm.dll”如何解决?

eclipse打开的时候出现Failed to load the JNI shared library “D:\java\jdk\bin…\jre\bin\server\jvm.dll”如何解决?? 如图所示: 即代表你的jdk与eclipse的位数不一样!!! 你可以查看一下eclipse和jd…

圆形坠落模拟算法设计

目标:实现一个算法,模拟在一个封闭二维区域,圆形小球朝给定方向坠落的过程,实现二维区域的紧密填充。 像下面这样: 难点,及其简单解决: 1.如何把粒子移动尽可能远? 图中的粒子i&…

Maven详细教学

一、Maven简介 maven:是apache下的一个开源项目,是纯java开发,并且只是用来管理java项目的 依赖管理:就是对jar包的统一管理 可以节省空间 项目一键构建:mvn tomcat:run该代码可以将一个完整的项目运行起来&#xff0…

网站后台中对html标签的处理

最近做一个CMS&#xff0c;后台中需要使用在线编辑器对新闻进行编辑&#xff0c;然后发表。我用的在线编辑器是CKEditorCKFinder。也许是我为了让CKEditor更本地化吧&#xff0c;改了很多。后来发现在CKEditor中对文字设置字体、颜色、字号大小时文字的<span>标签会出现N…

<各国地图轮廓app>技术支持

如在app使用过程中遇到任何问题&#xff0c;请与开发者联系caohechunhotmail.com

ffplay SDL_OpenAudio (2 channels, 44100 Hz): WASAPI can‘t initialize audio client“

windows下&#xff1a; ffplay 提示"SDL_OpenAudio (2 channels, 44100 Hz): WASAPI can’t initialize audio client" 添加环境变量&#xff1a;SDL_AUDIODRIVERdirectsound

(扩展)欧几里德快速幂

GCD模板 __int64 gcd(__int64 a,__int64 b) {return b0? a:gcd(b,a%b); } 欧几里德算法又称辗转相除法&#xff0c;用于计算两个整数a,b的最大公约数。其计算原理依赖于下面的定理&#xff1a; gcd函数就是用来求(a,b)的最大公约数的。 gcd函数的基本性质&#xff1a; gcd(a,…

Silverlight + WCF异步调用 例子

看大家好像对我的NParsing框架不是很感兴趣&#xff08;写NParsing帖没人顶我&#xff09;&#xff0c;那就给大家来点“甜品”&#xff0c;换换口谓。来说说Silverlight方面的东西。 在Silverlight中数据通信只能用异步。有人会觉得写起来很麻烦&#xff0c;其实不然。也有很简…