- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
本文介绍实时linux方案PREEMPT-RT提升系统实时性的机制之一--中断线程化,以及中断线程优先级配置,希望能为感兴趣的读者提供些许参考.
中断是一种异步事件处理机制,用于响应硬件请求,它会打断进程的正常调度和执行,然后调用内核中断处理程序来响应设备的请求.
由于中断处理程序会打断其他进程的运行,所以,为了减少对正常进程运行调度的影响,中断处理程序就需要尽可能快地运行。如果中断本身要做的事情不多,那么处理起来也不会有太大问题;但如果中断要处理的事情很多,中断服务程序就有可能要运行很长时间。特别是,中断处理程序在响应中断时,还会临时关闭中断。若中断任务繁重,这就会导致上一次中断处理完成之前,其他中断都不能响应,甚至丢失中断.
所以Linux 将中断处理过程分成了两个阶段,也就是上半部和下半部:
硬中断处理程序(ISR)迅速响应硬件事件,执行最少工作,大部分任务推迟至软中断SoftIRQ或任务队列workqueue.
软中断是一种机制,用于在稍后执行较耗时的中断处理任务。一般以内核线程的方式执行,并且每个 CPU 都对应一个软中断内核线程,名字为 “ksoftirqd/CPU 编号”,如0 号 CPU 对应的软中断内核线程的名字就是 ksoftirqd/0。软中断在软中断上下文运行,执行时机有2个,一个是硬件中断返回后立即执行,这时和硬件中断一样,完全抢占进程上下文,不允许被调度和抢占,其执行时间为不超过2ms,如果执行的软中断超过了2ms会将软中断延迟到软中断线程 “ksoftirqd/CPU 编号”中执行.
系统中软硬件中断通过proc 文件系统来查看:
/proc/softirqs 提供了软中断的运行情况; 。
/proc/interrupts 提供了硬中断的运行情况.
传统的中断处理方式虽然提升了系统的吞吐量,但从实时任务响应实时性方面来看存在以下不足:
这些不足使得普通linux中断处理方式难以满足高实时性要求的应用场景.
为了解决上述问题,PREEMPT-RT补丁引入了中断线程化机制,于2009年合入linux主线版本2.6.30。顾名思义就是将原来硬件中断上下文的中断处理的部分也通过一个内核线程来处理,除了代码中明确指明非中断线程化的中断和系统硬件timer中断外的中断均通过中断线程来处理,中断线程默认是一个实时线程,调度类为SCHED_FIFO,实时优先级为50。同时将SoftIRQ全部放到ksoftirqd/CPU线程中执行,ksoftirqd/CPU为普通非实时任务不变。通过ps命令可以看到中断线程.
ubuntu@work-host:~$ ps -ef | grep irq
root 14 2 0 12月10 ? 00:02:44 [ksoftirqd/0]
root 19 2 0 12月10 ? 00:00:08 [irq_work/0]
root 25 2 0 12月10 ? 00:00:00 [irq_work/1]
root 28 2 0 12月10 ? 00:00:00 [ksoftirqd/1]
root 33 2 0 12月10 ? 00:00:04 [irq_work/2]
root 36 2 0 12月10 ? 00:02:47 [ksoftirqd/2]
root 41 2 0 12月10 ? 00:00:01 [irq_work/3]
root 44 2 0 12月10 ? 00:03:09 [ksoftirqd/3]
root 49 2 0 12月10 ? 00:00:04 [irq_work/4]
root 52 2 0 12月10 ? 00:02:42 [ksoftirqd/4]
root 57 2 0 12月10 ? 00:00:02 [irq_work/5]
root 60 2 0 12月10 ? 00:02:28 [ksoftirqd/5]
root 121 2 0 12月10 ? 00:00:00 [irq/9-acpi]
root 136 2 0 12月10 ? 00:00:00 [irq/120-PCIe PM]
root 137 2 0 12月10 ? 00:00:00 [irq/121-PCIe PM]
root 138 2 0 12月10 ? 00:00:00 [irq/121-aerdrv]
root 139 2 0 12月10 ? 00:00:00 [irq/121-s-aerdr]
root 140 2 0 12月10 ? 00:00:00 [irq/122-PCIe PM]
root 141 2 0 12月10 ? 00:00:00 [irq/122-aerdrv]
root 142 2 0 12月10 ? 00:00:00 [irq/122-s-aerdr]
root 143 2 0 12月10 ? 00:00:00 [irq/123-PCIe PM]
root 144 2 0 12月10 ? 00:00:00 [irq/123-aerdrv]
root 145 2 0 12月10 ? 00:00:00 [irq/123-s-aerdr]
root 149 2 0 12月10 ? 00:00:00 [vfio-irqfd-clea]
root 150 2 0 12月10 ? 00:00:00 [irq/8-rtc0]
root 229 2 0 12月10 ? 00:13:52 [irq/124-xhci_hc]
root 230 2 0 12月10 ? 00:00:00 [irq/16-i801_smb]
root 281 2 0 12月10 ? 00:00:00 [irq/126-ahci[00]
root 746 2 0 12月10 ? 00:00:00 [irq/142-mei_me]
root 1089 2 0 12月10 ? 00:00:05 [irq/143-i915]
root 1105 2 0 12月10 ? 00:00:00 [irq/144-snd_hda]
root 1465 1 0 12月10 ? 00:01:24 /usr/sbin/irqbalance --foreground
root 1731 2 0 12月10 ? 00:00:20 [irq/125-eno1]
root 1734 2 0 12月10 ? 00:00:00 [irq/127-enp2s0]
root 1735 2 0 12月10 ? 00:00:04 [irq/128-enp2s0-]
....
中断线程化通过以下方式提升了Linux系统的实时性:
通过这些改进,PREEMPT-RT的中断线程化机制有效地解决了传统中断处理方式在实时性上的不足,使Linux系统能够更好地满足高实时性应用的需求.
所有外设的中断线程默认一个实时线程,调度类为SCHED_FIFO,实时优先级为50,对于实时性要求高的外设应该设置更高的优先级,如何才能修改中断线程的优先级?方式有两种,第一种最直接的办法,驱动代码中添加代码修改,但这样不灵活。另外一种是通过chrt工具来修改.
例如,要将PID为1234的线程的实时优先级设置为50,可以执行以下命令:
chrt -f -p 50 1234
这里,-f表示设置实时优先级,-p表示操作对象是进程。同样,只有root用户才能修改线程的实时优先级.
注意:在使用这些命令时,请确保已正确指定PID,以免对其他进程造成不必要的影响。 但直接使用chrt还是太原始,下面我给大家推荐一个工具--rtirq.
如果你使用的是debian衍生发行版,还可以通过rtirq这个工具来修改中断线程优先级,直接从github拉取 。
git clone https://github.com/rncbc/rtirq
或者通过apt软件包管理器安装 。
sudo apt install rtirq-init
注意:rtirq工具依赖完整功能的ps和chrt,所以在一些使用busybox嵌入式系统中由于ps功能简单,rtirq运行不了.
我们来看看rtirq-init是如何工作的,rtirq是一个脚本,位于/etc/init.d/rtirq,位于/etc/init.d目录下的的脚本系统启动后会自动执行,首先读取解析配置文件,然后根据配置文件来修改中断线程的优先级和调度策,最终执行的也是chrt命令,只不过它通过配置文件的方式提供了更多的灵活性配置,你可以自行分析脚本源码。 脚本/etc/init.d/rtirq接收的参数有start、stop、reset、restart(或)force-reload、status。 rtirq脚本执行时使用的配置文件依次为为/etc/sysconfig/rtirq、/etc/default/rtirq、/etc/rtirq.conf,前一个存在后面的就不生效。其中/etc/default/rtirq是安装后自动生成的模板文件,你可以直接修改它或者基于它重新新建一个.
/etc/default/rtirq内容如下:
# 我们要修改的IRQ线程服务名称,按下面的优先级及步长依次配置
# (从优先级高到低,以空格分隔列表)。
# RTIRQ_NAME_LIST="rtc snd usb i8042" #旧版本
RTIRQ_NAME_LIST="snd usb i8042"
# 最高的优先级。
RTIRQ_PRIO_HIGH=90
# 优先级递减步长。
RTIRQ_PRIO_DECR=5
# 最低的优先级。
RTIRQ_PRIO_LOW=51
# 是否将所有 IRQ 线程重置为 SCHED_OTHER。
RTIRQ_RESET_ALL=0
# 当内核支持时,
# 哪些服务不应被线程化(以空格分隔列表)。
RTIRQ_NON_THREADED="rtc snd"
# 将被强制到最高实时优先级范围内的进程名(99-91)(从高到低,以空格分隔列表)
# RTIRQ_HIGH_LIST="timer"
ubuntu@work-host:~$ /etc/init.d/rtirq status
PID CLS RTPRIO NI PRI %CPU STAT COMMAND
1105 FF 90 - 130 0.0 S irq/144-snd_hda
229 FF 85 - 125 0.1 S irq/124-xhci_hc
121 FF 50 - 90 0.0 S irq/9-acpi
136 FF 50 - 90 0.0 S irq/120-PCIe PM
137 FF 50 - 90 0.0 S irq/121-PCIe PM
138 FF 50 - 90 0.0 S irq/121-aerdrv
150 FF 50 - 90 0.0 S irq/8-rtc0
230 FF 50 - 90 0.0 S irq/16-i801_smb
281 FF 50 - 90 0.0 S irq/126-ahci[00
746 FF 50 - 90 0.0 S irq/142-mei_me
1089 FF 50 - 90 0.0 S irq/143-i915
1731 FF 50 - 90 0.0 S irq/125-eno1
....
1757 FF 50 - 90 0.0 S irq/141-enp4s0-
14 RR 1 - 41 0.0 S ksoftirqd/0
28 TS - 0 19 0.0 S ksoftirqd/1
36 TS - 0 19 0.0 S ksoftirqd/2
44 TS - 0 19 0.0 S ksoftirqd/3
52 TS - 0 19 0.0 S ksoftirqd/4
60 TS - 0 19 0.0 S ksoftirqd/5
....
示例 。
....
# Whether to reset all IRQ threads to SCHED_OTHER.
RTIRQ_RESET_ALL=1
...
执行:
ubuntu@work-host:~$ sudo /etc/init.d/rtirq reset
ubuntu@work-host:~$ sudo /etc/init.d/rtirq status
PID CLS RTPRIO NI PRI %CPU STAT COMMAND
14 TS - 0 19 0.0 S ksoftirqd/0
28 TS - 0 19 0.0 S ksoftirqd/1
36 TS - 0 19 0.0 S ksoftirqd/2
44 TS - 0 19 0.0 S ksoftirqd/3
52 TS - 0 19 0.0 S ksoftirqd/4
60 TS - 0 19 0.0 S ksoftirqd/5
121 TS - 0 19 0.0 S irq/9-acpi
137 TS - 0 19 0.0 S irq/120-PCIe PM
138 TS - 0 19 0.0 S irq/121-PCIe PM
139 TS - 0 19 0.0 S irq/121-aerdrv
140 TS - 0 19 0.0 S irq/121-s-aerdr
141 TS - 0 19 0.0 S irq/122-PCIe PM
142 TS - 0 19 0.0 S irq/122-aerdrv
143 TS - 0 19 0.0 S irq/122-s-aerdr
144 TS - 0 19 0.0 S irq/123-PCIe PM
145 TS - 0 19 0.0 S irq/123-aerdrv
146 TS - 0 19 0.0 S irq/123-s-aerdr
151 TS - 0 19 0.0 S irq/8-rtc0
251 TS - 0 19 0.0 S irq/125-xhci_hc
252 TS - 0 19 0.0 S irq/16-i801_smb
299 TS - 0 19 0.0 S irq/126-ahci[00
776 TS - 0 19 0.0 S irq/142-mei_me
1121 TS - 0 19 0.0 S irq/143-i915
1136 TS - 0 19 0.0 S irq/144-snd_hda
1798 TS - 0 19 0.0 S irq/124-eno1
1799 TS - 0 19 0.0 S irq/127-enp2s0
1800 TS - 0 19 0.0 S irq/128-enp2s0-
1801 TS - 0 19 0.0 S irq/129-enp2s0-
1802 TS - 0 19 0.0 S irq/130-enp2s0-
1803 TS - 0 19 0.0 S irq/131-enp2s0-
1808 TS - 0 19 0.0 S irq/132-enp3s0
1809 TS - 0 19 0.0 S irq/133-enp3s0-
1810 TS - 0 19 0.0 S irq/134-enp3s0-
1811 TS - 0 19 0.0 S irq/135-enp3s0-
1812 TS - 0 19 0.0 S irq/136-enp3s0-
1822 TS - 0 19 0.0 S irq/137-enp4s0
1823 TS - 0 19 0.0 S irq/138-enp4s0-
1824 TS - 0 19 0.0 S irq/139-enp4s0-
1825 TS - 0 19 0.0 S irq/140-enp4s0-
1826 TS - 0 19 0.0 S irq/141-enp4s0-
# IRQ thread service names
# (space separated list, from higher to lower priority).
# RTIRQ_NAME_LIST="rtc snd usb i8042" # old
RTIRQ_NAME_LIST="rtc enp4s0"
# Highest priority.
RTIRQ_PRIO_HIGH=90
# Priority decrease step.
RTIRQ_PRIO_DECR=5
# Lowest priority.
RTIRQ_PRIO_LOW=51
# Whether to reset all IRQ threads to SCHED_OTHER.
RTIRQ_RESET_ALL=0
# On kernel configurations that support it,
# which services should be NOT threaded
# (space separated list).
#RTIRQ_NON_THREADED="rtc snd"
# Process names which will be forced to the
# highest realtime priority range (99-91)
# (space separated list, from highest to lower priority).
# RTIRQ_HIGH_LIST="timer"
执行 。
ubuntu@work-host:~$ sudo /etc/init.d/rtirq start
Setting IRQ priorities: stop [rtc] irq=8 pid=151: OK.
Setting IRQ priorities: stop [enp4s0] irq=137 pid=1822: OK.
Setting IRQ priorities: stop [enp4s0] irq=138 pid=1823: OK.
Setting IRQ priorities: stop [enp4s0] irq=139 pid=1824: OK.
Setting IRQ priorities: stop [enp4s0] irq=140 pid=1825: OK.
Setting IRQ priorities: stop [enp4s0] irq=141 pid=1826: OK.
ubuntu@work-host:~$ sudo /etc/init.d/rtirq status
PID CLS RTPRIO NI PRI %CPU STAT COMMAND
151 FF 90 - 130 0.0 S irq/8-rtc0
1822 FF 85 - 125 0.0 S irq/137-enp4s0
1823 FF 84 - 124 0.0 S irq/138-enp4s0-
1824 FF 83 - 123 0.0 S irq/139-enp4s0-
1825 FF 82 - 122 0.0 S irq/140-enp4s0-
1826 FF 81 - 121 0.0 S irq/141-enp4s0-
14 TS - 0 19 0.0 S ksoftirqd/0
28 TS - 0 19 0.0 S ksoftirqd/1
36 TS - 0 19 0.0 S ksoftirqd/2
44 TS - 0 19 0.0 S ksoftirqd/3
52 TS - 0 19 0.0 S ksoftirqd/4
60 TS - 0 19 0.0 S ksoftirqd/5
121 TS - 0 19 0.0 S irq/9-acpi
137 TS - 0 19 0.0 S irq/120-PCIe PM
138 TS - 0 19 0.0 S irq/121-PCIe PM
139 TS - 0 19 0.0 S irq/121-aerdrv
140 TS - 0 19 0.0 S irq/121-s-aerdr
141 TS - 0 19 0.0 S irq/122-PCIe PM
142 TS - 0 19 0.0 S irq/122-aerdrv
143 TS - 0 19 0.0 S irq/122-s-aerdr
144 TS - 0 19 0.0 S irq/123-PCIe PM
145 TS - 0 19 0.0 S irq/123-aerdrv
146 TS - 0 19 0.0 S irq/123-s-aerdr
251 TS - 0 19 0.0 S irq/125-xhci_hc
252 TS - 0 19 0.0 S irq/16-i801_smb
299 TS - 0 19 0.0 S irq/126-ahci[00
776 TS - 0 19 0.0 S irq/142-mei_me
1121 TS - 0 19 0.0 S irq/143-i915
1136 TS - 0 19 0.0 S irq/144-snd_hda
1798 TS - 0 19 0.0 S irq/124-eno1
1799 TS - 0 19 0.0 S irq/127-enp2s0
1800 TS - 0 19 0.0 S irq/128-enp2s0-
1801 TS - 0 19 0.0 S irq/129-enp2s0-
1802 TS - 0 19 0.0 S irq/130-enp2s0-
1803 TS - 0 19 0.0 S irq/131-enp2s0-
1808 TS - 0 19 0.0 S irq/132-enp3s0
1809 TS - 0 19 0.0 S irq/133-enp3s0-
1810 TS - 0 19 0.0 S irq/134-enp3s0-
1811 TS - 0 19 0.0 S irq/135-enp3s0-
1812 TS - 0 19 0.0 S irq/136-enp3s0-
可以看到,irq/8-rtc0实时优先级为90,irq/137-enp4s0实时优先级为85,修改成功.
本文主要介绍了中断线程化这一提高linux系统实时性的机制。通过将外设中断处理从屏蔽全局中断的硬件中断上下转移到线程上下文程执行,可以更好地控制中断处理的优先级和响应时间,但牺牲了部分系统的吞吐量。此外,文章还详细讨论了如何配置不同外设的中断线程优先级,以确保关键任务的实时性。这些配置方法对系统设计者在规划和优化实时应用的优先级时具有重要意义.
最后此篇关于【原创】PREEMPT-RT中断线程化原理与中断线程优先级设置的文章就讲到这里了,如果你想了解更多关于【原创】PREEMPT-RT中断线程化原理与中断线程优先级设置的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
#include int main() { int i; for( i = 0; i< 10 ; i++ ) { printf("test1 &d", i);
我有一个连接到远程服务器以查询数据的 C# 程序。数据很大,所以查询大约需要 2 分钟才能完成。在这 2 分钟的时间内,互联网中断了。这导致作业无法完成,程序卡在获取数据例程中。 它建立了连接,但在选
语句 1: [2,4,6,7,8].each do |i| (i % 2 == 0) || (puts "Not even" && break) puts i end 声明 2: [2
我想知道 C++ 是否有任何处理中断的方法。我希望一个程序将信息存储在文本文件中,而另一个程序根据文本文件中的内容打印一条语句。由于我希望它尽可能准确,因此我需要在更新程序更新文件时中断打印程序。 最
我正在尝试终止一个线程,但它不会中断或停止。所有这些都是名为 Webots 的软件 Controller 的一部分。我用它来模拟多机器人系统。在每个机器人的 Controller 中,我启动了一个线程
中断10h可以使用的服务有很多, 我想问一下关于其中两个我很困惑的问题 首先是, AH = 06H SCROLL UP WINDOW AH = 07H SCROLL DOWN WINDOW 在 D
我有一个基本的 SQL 问题,如果有两个事件连接,"A"和 "B"到 SQL 服务器,假设两者之间发生死锁,那么为了避免死锁,SQL 服务器将回滚其中一个连接“A”或“B”的交易。假设 SQL Ser
我有一个 mapkit/ View ,它工作正常 - 但我滚动并在 2 - 10 次移动后我的应用程序崩溃了......而且这只是一个“中断”。 这是我的代码的一部分。我认为这是后台线程和数组释放/覆
有什么办法可以做到,比如 C/C# ? 例如(C#风格) for (int i = 0; i Seq.tryFind (fun i -> printfn "%d" i i=66) 在实践中,
我的问题是Haskell如何与系统交互。 例如,IO如何发生? 我对IO monad不感兴趣。或者如何使Haskell打印字符串或读取文件。 我对Haskell和底层操作系统之间的层(如果是这样的话)
你能确认下一个break是否取消了内部for循环吗? for (out in 1:n_old){ id_velho <- old_table_df$id[out] for
我有一个程序可以进行一些数据分析,并且有几百行长。 在程序的早期,我想做一些质量控制,如果没有足够的数据,我希望程序终止并返回到 R 控制台。否则,我希望执行其余代码。 我尝试过break、brows
我有一个 if 语句,用于检查我的对象(向导)是否命中了项目。如果他这样做了,巫师的大小将会改变,他应该能够在与障碍物的 1 次碰撞中幸存。 现在我陷入了“在 1 个障碍物碰撞中幸存”,因为在我的碰撞
我正在尝试使用迭代器来显示很多内容。我不断收到“break;”错误线。它说这是一个无法访问的声明。如有任何帮助,我们将不胜感激。 public Lot getLot(int number) {
我正在创建一个应用程序,我需要在其中处理可能非常庞大且可能需要一些时间的数据。 现在我阅读了很多关于 IntentService 的资料,实际上我已经将它实现为处理 REST 调用的通信类,但现在我试
我有一个自定义的 UITableViewCell。该单元具有三个标签。最左边的“金额”标签具有以下约束。 在单元格的右侧,我有另一个标签,“Label Dollar Amount”。它具有以下约束:
我有以下不和谐嵌入: message.reply({ content: '', embed: { color: 11416728, author
JavaScript 不是我最擅长的技能,但我会尽力解释,所以就这样吧。我有人在我的网站上创建了一个幻灯片菜单,我也使用 jplayer 音乐播放器。 现在一切正常,直到我在顶部添加此脚本。由于某种原
我已经在 Ubuntu 上安装了 android studio,有一个带有损坏图像的 API,我也尝试过重新安装。我应该怎么做才能克服这个问题。 删除它后,它没有在 sdk 管理器中显示 提前致谢。
假设我的站点上有大约 10 个 css 文件。我想把它们合二为一。但是当我组合它们时(只是“连接”文件,以便将它们包含到 html 中),我的样式/布局中断了。这不是路径问题或其他问题,只是选择器无法
我是一名优秀的程序员,十分优秀!