当前位置: 首页 > 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.…...

Air8101:低功耗-WiFi-UI_SoC模组介绍

一、模组概述 Air8101 是高性能 WiFi SoC 模组&#xff0c;支持2.4G WiFi6与BLE 5.4双模通信&#xff0c;兼容DVP/UVC摄像头接口&#xff0c;可实现200W像素拍照、100W像素录像&#xff08;支持H.264编码及RTMP推流&#xff09;&#xff0c;搭载LuatOS&#xff0c;降低二次开发…...

MS5611高精度气压温度传感器Arduino驱动库

1. 项目概述MS5611-Mike-Refactored 是一款面向嵌入式平台&#xff08;特别是 Arduino 兼容生态&#xff09;的 MS5611 高精度气压/温度传感器驱动库。该库并非简单封装&#xff0c;而是对 Korneliusz Jarzebski 原始实现的一次系统性重构与工程化增强。其核心目标是将一个基础…...

敏捷还是瀑布?数字化项目的治理模式选择

敏捷还是瀑布&#xff1f;数字化项目的治理模式选择 项目背景&#xff1a;24年酒店PMS换系统和CRM上线。一、前言&#xff1a;当"稳定交付"遇上"快速迭代" 传统零售和酒店餐饮行业每年都要面对数十个数字化项目的治理决策。从ERP升级到会员中台建设&#x…...

Arduino压力变送器信号处理库:模拟传感器线性标定与鲁棒读取

1. 项目概述PressureTransducer 是一个面向嵌入式传感器应用的轻量级 Arduino 库&#xff0c;专为模拟式压力变送器&#xff08;Analog Pressure Transducer&#xff09;设计。其核心价值不在于提供复杂驱动或协议栈&#xff0c;而在于将硬件信号链中多级、易出错的手动计算封装…...

Vibe Coding氛围编程系列:AI 模型 服务选择之哪个模型编程能力最强?

前言 2026年&#xff0c;AI辅助编程早已告别了“单行代码补全”的初级阶段&#xff0c;正式进入了Vibe Coding&#xff08;氛围编程&#xff09; 的全新时代。所谓氛围编程&#xff0c;核心是AI能完全贴合开发者的编码思路、节奏与工作流&#xff0c;实现无断点、沉浸式的流畅…...

PHP 中字符串类型无法使用数组下标访问的错误解析与修复

...

突破模型部署瓶颈:TimesFM 2.5从500M到200M的压缩实践指南

突破模型部署瓶颈&#xff1a;TimesFM 2.5从500M到200M的压缩实践指南 【免费下载链接】timesfm TimesFM (Time Series Foundation Model) is a pretrained time-series foundation model developed by Google Research for time-series forecasting. 项目地址: https://gitc…...

2026年AI风口已至!月薪3万+岗位盘点+零基础转行指南,速收藏!

本文详细介绍了2026年转行AI的优势与机遇&#xff0c;指出行业人才缺口巨大且薪资水平高。文章全面梳理了AI行业的各类岗位&#xff0c;并针对技术、产品、运营、培训等不同转行路径&#xff0c;提供了分阶段的学习指南和推荐资源。此外&#xff0c;还针对应届毕业生、传统行业…...

利用闲置旧电脑搭建飞牛OS家庭服务器:从DDNS配置到安全外网访问全攻略

1. 为什么选择飞牛OS搭建家庭服务器 家里有台闲置的旧电脑&#xff0c;扔了可惜&#xff0c;留着又占地方&#xff1f;其实它完全可以变身为一台高性能的家庭服务器。我去年就用一台2015年的老笔记本搭建了飞牛OS服务器&#xff0c;到现在稳定运行了300多天。飞牛OS作为国产NAS…...

3个高效步骤:DriverStore Explorer解决Windows驱动管理难题

3个高效步骤&#xff1a;DriverStore Explorer解决Windows驱动管理难题 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 问题诊断&#xff1a;驱动管理中的隐形痛点 当你打开设备管理器…...