当前位置: 首页 > news >正文

关于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了嘛?这个难道不是进程上下文??后面找一个支持抢占的内核试试

相关文章:

关于preempt count的疑问

Linux中的preempt_count - 知乎 https://www.cnblogs.com/hellokitty2/p/15652312.html LWN&#xff1a;关于preempt_count()的四个小讨论&#xff01;-CSDN博客 主要是参考这些文章 之前一直认为只要是in_interrupt()返回非0值&#xff0c;那么就可以认为当前在中断上下文。即…...

Windows 开启 Kerberos 的火狐 Firefox 浏览器访问yarn、hdfs

背景&#xff1a;类型为IPA或者MIT KDC&#xff0c;windows目前只支持 firefoxMIT Kerberos客户端的形式&#xff0c;其他windows端浏览器IE、chrome、edge&#xff0c;没有办法去调用MIT Kerberos Windows客户端的GSSAPI验证方式&#xff0c;所以均无法使用 Windows 开启 Kerb…...

华为云资源搭建过程

网络搭建 EIP&#xff1a; 弹性EIP&#xff0c;支持IPv4和IPv6。 弹性公网IP&#xff08;Elastic IP&#xff09;提供独立的公网IP资源&#xff0c;包括公网IP地址与公网出口带宽服务。可以与弹性云服务器、裸金属服务器、虚拟IP、弹性负载均衡、NAT网关等资源灵活地绑定及解绑…...

突破防火墙的一种方法

当Linux防火墙阻止来自某个ip的数据时&#xff0c;它应该是根据ip数据报里“源IP地址”字段取得的对方ip吧&#xff0c;那对方就不能通过篡改“源IP地址”来绕过防火墙吗&#xff1f;NAT模式下的路由器就修改了这个字段。 但这样的话&#xff0c;攻击者是收不到服务器返回的数…...

Docker 多阶段构建的原理及构建过程展示

Docker多阶段构建是一个优秀的技术&#xff0c;可以显著减少 Docker 镜像的大小&#xff0c;从而加快镜像的构建速度&#xff0c;并减少镜像的传输时间和存储空间。本文将详细介绍 Docker 多阶段构建的原理、用途以及示例。 Docker 多阶段构建的原理 在传统的 Docker 镜像构建…...

【开题报告】基于Spring Boot的家装产品展示交易平台的设计与实现

1.研究背景和目的 随着人们对居住环境舒适度和个性化需求的不断提升&#xff0c;家装市场正逐渐发展成为一个重要的消费领域。为了满足消费者对家装产品的需求&#xff0c;建立一个高效、可靠的家装产品展示交易平台变得尤为重要。本项目旨在通过使用Spring Boot框架&#xff…...

MacOS安装git

文章目录 通过Xcode Command Lines Tool安装(推荐)终端直接运行git命令根据流程安装先安装Command Lines Tool后再安装git 官网下载二进制文件进行安装官方国外源下载二进制文件(不推荐)国内镜像下载二进制文件(推荐)安装git 通过Xcode Command Lines Tool安装(推荐) 简单来讲C…...

京东协议算法最新版

环境准备 1 com.jingdong.app.mall11.6.4 入口定位 逆向分析&#xff0c;发现 params 里面有一个 sign 以及请求头里面有一个 jdgs 首先我们发现京东的 sign 是 32 位的&#xff0c;猜测其可能是 md5 之类的 hash 算法&#xff0c;既然是 hash 算法&#xff0c;那么就大概率…...

软考系统架构设计师案例分析知识汇总

软件架构风格 △△△ 软件架构风格是描述某一类特定应用领域中软件系统组织方式和惯用方式。组织方式描述了系统的组成构件和这些构件的组织方式,惯用模式则反映众多系统共有的结构和语义。 面向对象架构风格的特征是将数据表示和基本操作封装在对象中。这种模式的构件是对象…...

MyBatis-plus 代码生成器

具体代码 application.yaml server:port: 8081 #自定义端口号spring:datasource:url: jdbc:mysql://localhost:3306/itcast?useUnicodetrue&characterEncodingutf-8&serverTimezoneGMT%2B8username: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driver…...

运维常识——网络

内网&#xff0c;公网IP 内网IP为专网IP 因为网络资源&#xff08;IP地址不够&#xff0c;所以引出来了内网IP和IPv6&#xff09; 内网IP和公网IP之分是为了减缓IP地址不够使用的情况 一般设置代理服务器 设置两张网卡 一张对外一张对内 内部主机将数据转发到内网卡&#…...

《研发效能(DevOps)工程师》课程简介(一)丨IDCF

为贯彻落实《关于深化人才发展体制机制改革的意见》&#xff0c;推动实施人才强国战略&#xff0c;促进专业技术人员提升职业素养、补充新知识新技能&#xff0c;实现人力资源深度开发&#xff0c;推动经济社会全面发展&#xff0c;根据《中华人民共和国劳动法》有关规定&#…...

OMV 介绍及安装

# Time: 2023/11/02 #Author: Xiaohong # 运行电脑: Lenovo X201I (Intel(R) Core(TM) i3 CPU M 370 2.40GHz) # 功能: OMV 介绍及安装 导图 若OMV6 安装Extras 插件失败&#xff0c;可以参考 OMV6 安装Extras 插件失败的解决方法...

JAVA 实现PDF转图片(spire.pdf.free版)

1.引入jar包 导入方法1&#xff1a; 手动引入。将Free Spire.PDF for Java下载到本地&#xff0c;解压&#xff0c;找到lib文件夹下的Spire.PDF.jar文件。在IDEA中打开如下界面&#xff0c;将本地路径中的jar文件引入Java程序&#xff1a; 导入方法2&#xff1a;如果您想通过…...

高效学习工具之AnkiMobile新手入门指南(ios端,包括ipad、ihpone设备)————创建、使用、备份、设置参数、相关资料

文章目录 0 背景0.1 闭环学习0.2 什么是anki0.3 anki践行者经验分享 1 开始使用1.1 导入1.2 创建空白组1.3 创建卡片1.3.1 利用anki创建卡片的两种方法1.3.2 复习材料分类 1.4 筛选&#xff08;做减法&#xff0c;拆分学习&#xff08;做子卡牌集合&#xff09;&#xff09;&am…...

LiveMeida视频接入网关

一、产品简介 视频接入网关主要部署在视频存储节点或视频汇聚节点&#xff0c;面向不同用户&#xff0c;主要用于对接不同厂家、不同型号的摄像机设备&#xff0c;获取摄像机视频后&#xff0c;以统一标准的视频格式和传输协议&#xff0c;将视频推送至上层联网/应用平台。可广…...

我和云栖有个约会

文章目录 云栖大会体验与感受大模型的体验感受 对大会的期待 云栖大会 云栖大会是是阿里巴巴集团主办的年度技术盛会&#xff0c;是云计算、大数据、人工智能等前沿技术产业发展的见证者、参与者和推动者。2023年的云栖大会于10月31日在杭州开幕&#xff0c;吸引了全球的技术专…...

模拟官网编写自定义Grafana Dashboard

前言 我们想编写自定义的Dashboard&#xff0c;类似于官网那样下载的Dashboard&#xff0c;并且能移值到机器主机&#xff0c;如何实现了&#xff1f; ## 官网dashboard https://grafana.com/grafana/dashboards/ 编写 先在虚拟机写好Dashboard 然后下载。json文件如下: {…...

组件局部注册和全局注册

普通组件的注册使用-局部注册 1.特点&#xff1a; 只能在注册的组件内使用 2.实现效果 3.步骤&#xff1a; 创建.vue文件&#xff08;三个组成部分&#xff09;在使用的组件内先导入再注册&#xff0c;最后使用 4.使用方式&#xff1a; 当成html标签使用即可 <组件名&…...

【数据结构】模拟实现stack

namespace my_stack {//适配器模式/配接器template <class T,class Containervector<T>>class stack {public:void push(const T& val){_con.push_back(val);}void pop(){_con.pop_back();}const T& top(){return _con.back();}size_t size(){return _con.…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

【C++】纯虚函数类外可以写实现吗?

1. 答案 先说答案&#xff0c;可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...

向量几何的二元性:叉乘模长与内积投影的深层联系

在数学与物理的空间世界中&#xff0c;向量运算构成了理解几何结构的基石。叉乘&#xff08;外积&#xff09;与点积&#xff08;内积&#xff09;作为向量代数的两大支柱&#xff0c;表面上呈现出截然不同的几何意义与代数形式&#xff0c;却在深层次上揭示了向量间相互作用的…...