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

聊城网站改版江苏天矗建设集团网站

聊城网站改版,江苏天矗建设集团网站,wordpress 删除超文本,家居装修风格图片大全Linux中的preempt_count - 知乎 https://www.cnblogs.com/hellokitty2/p/15652312.html LWN:关于preempt_count()的四个小讨论!-CSDN博客 主要是参考这些文章 之前一直认为只要是in_interrupt()返回非0值,那么就可以认为当前在中断上下文。即…

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.yayakq.cn/news/719881/

相关文章:

  • 网站图片的像素网站怎样建设才叫人性化
  • 获取网站全站代码域名备案查询系统
  • 爱情动做网站推荐外链平台
  • php 网站 教程淄博网站建设常见问题
  • 网站建设最新模板下载招聘网站预算怎么做
  • 网站空间可以转移吗怎么开网店淘宝
  • 软件公司网站系统集成建设新闻资讯app开发
  • 面包屑 网站企业网站建设应该怎么做
  • 淘宝客导购网站源码现在的网站建设用什么语言
  • 网站建设需要些什么东西自己做的网站很卡
  • 美团网网站建设分析设计师网站
  • 百度站长网站文件验证微信网页游戏大全
  • 做网站找哪个部门咸宁做网站公司
  • 开发网站要注意什么问题邯郸做移动网站多少钱
  • 自适应企业网站模板杭州软件开发公司网站
  • 网站建设校长信箱设计方案织梦做音乐网站
  • 网站开发的难点电商网站首页
  • 深圳专业网站建设制作价格公司设计网站费用
  • 长沙企业网站建设报价wordpress自定义参数查询
  • 大型美容网站建设域名备案要多久
  • 福永做网站的公司wordpress主题电影
  • 网站流量用完了福田网站的建设
  • 房屋装修在线设计网站网站统计开放平台
  • 单网页网站制作网站做跳转对排名有影响吗
  • 普陀做网站价格静态网站建设要学什么
  • 03173软件开发工具大连网站seo顾问
  • 加强网站信息建设管理网站图片像素
  • 外包公司企业网站中英文网站切换
  • 网站开发 制作公司网站制作新手教程
  • 如何在网站上做qq群链接网站建设得多钱