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

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...