关于preempt count的疑问

Linux中的preempt_count - 知乎

https://www.cnblogs.com/hellokitty2/p/15652312.html

LWN:关于preempt_count()的四个小讨论!-CSDN博客

主要是参考这些文章

之前一直认为只要是in_interrupt()返回非0值,那么就可以认为当前在中断上下文。即使中一个内核线程里面in_interrupt返回非0值(比如local_bh_disable)

但是最近又有另外一种说法,in_interrupt(),in_softirq()这两个只有是真正的中断上半部以及软中断上下文才会返回非0值。在进程上下文中使用这两个函数一定会返回false或者是不应该在一个内核线程里面调用???(我这句话说的不太准确,具体是啥记不清楚了)。

其实我之前理解,类似于in_interrupt这些函数最终都是通过preempt count来判断的。只要这变量的值不为0,那就是非进程上下文,并不会因为调用的地方实际是在一个内核线程里面还是软中断处理流程里面而改变。只要是改变了preempt count的值,那就等同于改变了当前代码的一个上下文。

因此准备重新回顾一下preempt count的作用。

在像 Linux 这样的多任务系统中,没有任何一个线程可以保证它每次想运行的时候都能独占处理器。内核总是有能力(多数情况下)抢占一个正在运行的线程,而选择一个优先级更高的线程来执行。那个新线程可能是另一个不同的进程,但也可能是一个硬件中断,或者什么其他外部事件。为了正确地协调系统中所有任务能正确运行,内核必须跟踪当前的执行状态(execution state),包括已经被抢占或可能阻止线程被抢占的各种情况。

用来进行这个追踪记录的基础,就是在系统中每个任务里存储的 preemption counter。

这个 counter 可以用来指示当前线程的状态、它是否可以被抢占,以及它是否被允睡眠。要实现这个功能的话,就必须在这个 counter 里面记录若干种不同状态,因此这个 preempt_count 也被分成了几个字段(sub-fields):

#define PREEMPT_BITS	8
#define SOFTIRQ_BITS	8
#define HARDIRQ_BITS	4
#define NMI_BITS	1

preempt_count 这个成员被用来判断当前进程是否可以被抢占。如果 preempt_count 不等于0(可能是代码调用preempt_disable显式的禁止了抢占,也可能是处于中断上下文等),说明当前不能进行抢占,如果 preempt_count 等于0,说明已经具备了抢占的条件。

我记得书上还有一种说法,preempt_count可以看做当前进程加锁的次数。当该进程准备让出cpu时需要检查这个值是否为0。不能在只有锁的情况下进程任务调度(好像也不是很准确哈!!休眠锁不就可以在加锁情况下调度嘛)

preemption disable count(低8bit):用于记录当前进程被显示禁用抢占的次数(preempt_disable调用次数)。最多嵌套调用2^8次

下面代码假设内核支持抢占。可以看到preempt_disable就是修改的最后一个字节

#define preempt_disable() \
do { \preempt_count_inc(); \barrier(); \
} while (0)#define __preempt_count_inc() __preempt_count_add(1)static __always_inline void __preempt_count_add(int val)
{*preempt_count_ptr() += val;
}static __always_inline int *preempt_count_ptr(void)
{return &current_thread_info()->preempt_count;
}

softirq_count:preempt_count中的第8到15个bit表示softirq count,它记录了进入softirq的嵌套次数。

可以看到在进入软中断时。就会先标识其已经进入了软中断上下文    __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET);其修改的就是bit8开始的内容。

smlinkage __visible void __do_softirq(void)
{
..........................__local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET);
.....................
}
#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
#define NMI_OFFSET	(1UL << NMI_SHIFT)
static __always_inline void __local_bh_disable_ip(unsigned long ip, unsigned int cnt)
{preempt_count_add(cnt);barrier();
}

在同一个cpu上,软中断是串行执行的。(同一个软中断可以在不同的cpu上同时执行,tasklet除外)。因此如果只是为了标识是不是正在处理软中断,1个bit就行了。那么其他7个bit是干什么的呢?

另外的7bit为了记录,防止进程被softirq所抢占,关闭/禁止softirq的次数,比如每使用一次local_bh_disable(),softirq count高7个bits(bit 9到bit 15)的值就会加1,使用local_bh_enable()则会让softirq count高7个bits的的值减1。

 可以看到local_bh_disable其实是修改的bit10开始的内容。因此另外7个bit可以认为是显示禁止软中断的嵌套次数

static inline void local_bh_disable(void)
{__local_bh_disable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET);
}#define SOFTIRQ_DISABLE_OFFSET	(2 * SOFTIRQ_OFFSET)

因此为了分清楚是正在处理软中断还是说进程里面显示禁止了软中断,我们只需要判断bit8就行(进入softirq是在softirq上下文,关闭softirq抢占也是在softirq上下文如何区分)

//这个能够判断是否是正在处理软中断
#define in_serving_softirq()	(softirq_count() & SOFTIRQ_OFFSET)#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)// 1 << 8#define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)// 0 + 8#define PREEMPT_BITS	8
#define PREEMPT_SHIFT	0

 hardirq count:4bit,用于表示硬件中断嵌套的次数,最多可以嵌套16层(参考的文章说现在linux不支持中断嵌套)。当进入硬件中断时,会将其+1,退出-1。

#define __irq_enter()					\do {						\account_irq_enter_time(current);	\preempt_count_add(HARDIRQ_OFFSET);	\trace_hardirq_enter();			\} while (0)

中断上下文:不管是hardirq和softirq都称为中断上下文。下图是抄自知乎。

其中正在处理软中断(进入do_softirq)或者是关闭softirq抢占(local_bh_enable)都属于软中断上下文。

正在处理中断上半部属于hardirq上下文(关闭中断属于中断上下文吗???感觉不是呢?local_irq_disable不会去修改preempt count的值呢,不理解这个是什么意思)

因此对于中断上下文的判断就是判断非bit0到bit7的值是否为非0

#define in_interrupt()		(irq_count())#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK \| NMI_MASK))//就是判断高bit8-bit20是否为非0,非0就是在中断上下文

 是否在软中断上下文和硬中断上下文,同样也是判断对应的值

#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)

进程上下文判断:我的内核代码里面没有呢?(当前的内核版本是3.16,后面下了个5.4的里面就有这个了)。

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

另外我感觉就是判断低8bit的值是否为0呢。如果我在一个进程里面显示禁用抢占,那in_task不就返回0了嘛?这个难道不是进程上下文??后面找一个支持抢占的内核试试

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

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

相关文章

阿昌教你如何优雅的数据脱敏

阿昌教你如何优雅的数据脱敏 Hi&#xff0c;我是阿昌&#xff0c;最近有一个数据脱敏的需求&#xff0c;要求用户可自定义配置数据权限&#xff0c;并对某种类型数据进行脱敏返回给前端 一、涉及知识点 SpringMVCJava反射Java自定义注解Java枚举 二、方案选择 1、需求要求…

Webpack打包图片-js-vue

文章目录 一、Webpack打包图片1.加载图片资源的准备2.认识asset module type3.asset module type的使用4.url-loader的limit效果 二、babel1.为什么需要babel2.babel命令行的使用3.babel插件的使用4.babel的预设preset5.babel-loader6.babel-preset 三、加载Vue文件1.编写App.v…

使用Ansible中的playbook

目录 1.Playbook的功能 2.YAML 3.YAML列表 4.YAML的字典 5.playbook执行命令 6.playbook的核心组件 7.vim 设定技巧 示例 1.Playbook的功能 playbook 是由一个或多个play组成的列表 Playboot 文件使用YAML来写的 2.YAML #简介# 是一种表达资料序列的格式,类似XML #特…

开关电源测试过压保护的测试标准及其方法

过压保护的原理 过压保护是电压超过预定值时降低电压的一种方式&#xff0c;原理是通过电路中的电压检测电路来检测电路中的电压是否超过了设定的阈值&#xff0c;如果超过了阈值&#xff0c;就会触发过压保护器件&#xff0c;使电源断开或使受控设备电压降低&#xff0c;保护电…

网络协议--TCP的交互数据流

19.1 引言 前一章我们介绍了TCP连接的建立与释放&#xff0c;现在来介绍使用TCP进行数据传输的有关问题。 一些有关TCP通信量的研究如[Caceres et al. 1991]发现&#xff0c;如果按照分组数量计算&#xff0c;约有一半的TCP报文段包含成块数据&#xff08;如FTP、电子邮件和U…

使用Fiddler进行Mock测试

1、接口抓包 找到要mock的接口&#xff0c;打开fiddler抓包 以某某接口为例&#xff0c;找到下面的接口 http://XXX/SYSTEMS 2、复制该接口数据到本地 在接口上进行右键点击&#xff0c;选择save -> …and Open as Local File -> 默认会保存至桌面&#xff0c;示例中的数…

uniapp的启动页、开屏广告

uniapp的启动页、开屏广告 启动页配置广告开屏 启动页配置 在manifest.json文件中找到APP启动界面配置&#xff0c;可以看到有Android和iOS的启动页面的配置 &#xff0c;选择自定义启动图即可配置 广告开屏 在pages中新建一个广告开屏文件并在pases.json的最顶部配置这个页…

开发商城系统的一些小建议

电子商务的迅猛发展&#xff0c;商城系统已经成为了企业推广产品和服务、吸引更多消费者的重要工具。然而&#xff0c;要想在竞争激烈的市场中脱颖而出&#xff0c;提升用户体验成为了至关重要的一环。下面就商城系统的开发作一些简单分享&#xff0c;以帮助企业更好地满足用户…

跨国文件传输为什么要用专业的大文件传输软件?

跨国文件传输是许多跨国企业需要的基础工作&#xff0c;对于传输的质量和速度要求也是很严格的&#xff0c;随着数据量的不断增加&#xff0c;寻常传统的传输方式肯定是不行&#xff0c;需要新的技术和方式来进行传输&#xff0c;大文件传输软件应运而出&#xff0c;那它有什么…

联想百应:构建“生态资源池”,打造中小企业转型第一服务平台

与3800多家服务商和100多家SaaS生态伙伴携手&#xff0c;累计支持超过20万中小企业智能化转型……在近日由工业和信息化部和安徽省举办的2023全国中小企业数字化转型大会上&#xff0c;联想集团首次公布供应链、平台、技术、生态与绿色赋能五大赋能能力和助力中小企业“链式”成…

sqlite3 关系型数据库语言 SQL 语言

SQL(Structured Query Language)语言是一种结构化查询语言,是一个通用的,功能强大的关系型数据库操作语言. 包含 6 个部分: 1.数据查询语言(DQL:Data Query Language) 从数据库的二维表格中查询数据,保留字 SELECT 是 DQL 中用的最多的语句 2.数据操作语言(DML) 最主要的关…

神经网络的解释方法之CAM、Grad-CAM、Grad-CAM++、LayerCAM

原理优点缺点GAP将多维特征映射降维为一个固定长度的特征向量①减少了模型的参数量&#xff1b;②保留更多的空间位置信息&#xff1b;③可并行计算&#xff0c;计算效率高&#xff1b;④具有一定程度的不变性①可能导致信息的损失&#xff1b;②忽略不同尺度的空间信息CAM利用…

前端 :用HTML , CSS ,JS 做一个秒表

1.HTML&#xff1a; <body><div id "content"><div id "top"><div id"time">00:00:000</div></div><div id "bottom"><div id "btn_start">开始</div><div …

04.Oracle的体系架构

Oracle的体系架构 一、主要组件 一、主要组件 下面是一张网图&#xff0c;大家可以了解一下oracle的体系架构 Oracle数据库的体系架构可以分为以下几个主要组件&#xff1a;实例&#xff08;Instance&#xff09;、数据库&#xff08;Database&#xff09;、表空间&#xff…

瑞数专题五

今日文案&#xff1a;焦虑&#xff0c;想象力过度发酵的产物。 网址&#xff1a;https://www.iyiou.com/ 专题五主要是分享瑞数6代。6代很少见&#xff0c;所以找理想哥要的&#xff0c;感谢感谢。 关于瑞数作者之前已经分享过4篇文章&#xff0c;全都收录在瑞数专栏中了&am…

21. 合并两个有序链表、Leetcode的Python实现

博客主页&#xff1a;&#x1f3c6;看看是李XX还是李歘歘 &#x1f3c6; &#x1f33a;每天不定期分享一些包括但不限于计算机基础、算法、后端开发相关的知识点&#xff0c;以及职场小菜鸡的生活。&#x1f33a; &#x1f497;点关注不迷路&#xff0c;总有一些&#x1f4d6;知…

正式启航!指导品牌开拓下一个增长蓝海

种草的商品总在不经意间推送到面前&#xff0c;深夜刷了会儿短视频&#xff0c;不小心又下单了一个不太熟悉的产品&#xff0c;明星达人素人全部入局直播带货&#xff0c;社交平台演变成购物场&#xff0c;无人幸免的兴趣电商时代强势来临。尤其到了每年一度的双11大促节点&…

音视频rtsp rtmp gb28181在浏览器上的按需拉流

按需拉流是从客户视角来看待音视频的产品功能&#xff0c;直观&#xff0c;好用&#xff0c;为啥hls flv大行其道也是这个原因&#xff0c;不过上述存在的问题是延迟没法降到实时毫秒级延迟&#xff0c;也不能随心所欲的控制。通过一段时间的努力&#xff0c;结合自己闭环技术栈…

Web APIs——日期对象的使用

1、日期对象 日期对象&#xff1a;用来表示时间的对象 作用&#xff1a;可以得到当前系统时间 1.1实例化 在代码中发现了new关键字时&#xff0c;一般将这个操作称为实例化 创建一个时间对象并获取时间 获得当前时间 const date new Date() <script>// 实例化 new //…

UE5 Android下载zip文件并解压缩到指定位置

一、下载是使用市场的免费插件 二、解压缩是使用市场的免费插件 三、Android路径问题 windows平台下使用该插件没有问题&#xff0c;只是在Android平台下&#xff0c;只有使用绝对路径才能进行解压缩&#xff0c;所以如何获得Android下的绝对路径&#xff1f;增加C文件获得And…