精华内容
下载资源
问答
  • 一、申请中断request_irq() Linux中使用中断需要先进行申请,申请中断的API函数如下: int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *...

    一、申请中断request_irq()

    Linux中使用中断需要先进行申请,申请中断的API函数如下:

    int request_irq(unsigned int irq,
    				irq_handler_t handler,
    				unsigned long flags,
    				const char *name,
    				void *dev)
    

    irq:要申请中断的中断号。
    handler:中断处理函数。
    name:中断名字,设置以后可以在/proc/interrupts 文件中看到对应的中断名字。
    dev: 如果将 flags 设置为 IRQF_SHARED 的话, dev 用来区分不同的中断,一般情况下将dev 设置为设备结构体, dev 会传递给中断处理函数 irq_handler_t 的第二个参数。
    flags:中断标志,可以在文件 include/linux/interrupt.h 里面查看所有的中断标志,这里我们介绍几个常用的中断标志。

    标志描述
    IRQF_SHARED多个设备共享一个中断线,共享的所有中断都必须指定此标志。如果使用共享中断的话, request_irq 函数的 dev 参数就是唯一区分他们的标志
    IRQF_ONESHOT单次中断,中断执行一次就结束
    IRQF_TRIGGER_NONE无触发
    IRQF_TRIGGER_RISING上升沿触发
    IRQF_TRIGGER_FALLING下降沿触发
    IRQF_TRIGGER_HIGH高电平触发
    IRQF_TRIGGER_LOW低电平触发

    返回值: 0 中断申请成功,其他负值 中断申请失败,如果返回-EBUSY 的话表示中断已经被申请了。

    request_irq()函数可能会导致睡眠,因此不能在中断上下文或者其他禁止睡眠的代码段中使用 。
    中断申请函数及中断处理函数的实例,可以参考Linux中断子系统—workqueue工作队列
    /面朝大海0902/

    二、中断线程化request_threaded_irq()

    中断线程化的作用与工作队列类似,先在中断处理函数中处理重要紧急的任务,然后使用线程来处理耗时复杂的任务。API函数如下:

    request_threaded_irq(unsigned int irq, 
    					irq_handler_t handler,
    		     		irq_handler_t thread_fn,
    		     		unsigned long flags, 
    		     		const char *name, 
    		     		void *dev);
    

    request_irq() 函数相比request_threaded_irq() 函数仅多了一个入参thread_fn ,thread_fn()为在线程中运行的函数。
    /面朝大海0902/

    三、中断线程化与工作队列的差异

    这里引用韦东山老师的总结:work 来线程化地处理中断,一个 worker 线程只能由一个 CPU 执行,多个中断的 work 都由同一个 worker 线程来处理,在单 CPU 系统中也只能忍着了。但是在 SMP 系统中,多个 CPU 空着,偏偏让多个中断挤在一个 CPU 上进行处理,效率不高。
    新技术 threaded irq,为每一个中断都创建一个内核线程;多个中断的内核线程可以分配到多个 CPU上执行,这提高了效率。

    四、其他中断相关函数

    中断使能与禁止函数:
    void enable_irq(unsigned int irq)
    void disable_irq(unsigned int irq)
    注意事项:disable_irq()函数要等到当前正在执行的中断处理函数执行完才返回,因此使用者需要保证不会产生新的中
    断,并且确保所有已经开始执行的中断处理程序已经全部退出。

    void disable_irq_nosync(unsigned int irq)
    disable_irq_nosync 函数调用以后立即返回,不会等待当前中断处理程序执行完毕。
    /面朝大海0902/

    使能或禁止系统中断函数:
    local_irq_enable()
    local_irq_disable()
    简单粗暴的使能或禁止系统中断。

    local_irq_save(flags)
    local_irq_restore(flags)
    local_irq_save 函数用于禁止中断,并且将中断状态保存在 flags 中。local_irq_restore 用于恢复中断,将中断到 flags 状态。

    展开全文
  • 背景有一个项目对实时性要求比较高,于是在linux内核上打了RT_PREEMPT补丁。最终碰到的一个问题是,芯片本身性能不强,CPU资源...原来这是一个被线程化了的中断服务程序,负责处理i2c中断的。这个项目i2c总线上挂...

    背景

    有一个项目对实时性要求比较高,于是在linux内核上打了RT_PREEMPT补丁。

    最终碰到的一个问题是,芯片本身性能不强,CPU资源不足,急需优化。

    初步分析

    看了下cpu占用率,除了主应用之外,有一个名为irq/38-twi0的进程引起了我们的注意,因为它竟然占据了10%的cpu。

    这个irq开头的进程是做什么的呢?原来这是一个被线程化了的中断服务程序,负责处理i2c中断的。这个项目i2c总线上挂载了多个设备,压力是比较大的。

    第一个想法是能否减少设备数量或者减低采集频率,但这会影响到应用的算法表现,暂时不考虑。

    第二个想法是优化代码,但打开中断服务程序的源码一看,其实现非常简单,基本就只是从硬件寄存器中把接收到的数据取出来而已,看来从这里入手也希望不大。

    再仔细想想,这个进程执行的操作这么简单,CPU占用率却这么高,那么主要就是因为其执行的频率过高,每次执行其实都会伴随着进程调度/上下文切换带来的开销,这部分是否可以进行优化呢。

    中断线程化回顾

    让我们来回顾下中断线程化的知识。

    在Linux上,中断的优先级比进程高,一旦中断过来普通进程实时进程通通都要让路,让CPU先运行对应的中断处理程序,这就会对实时性造成很大的影响。

    为了解决这个由中断带来的实时性问题,或者说由不确定运行时长的中断服务程序带来的实时性问题,RT_PREEMPT补丁引入了中断线程化的机制。

    中断线程化之后,中断来了虽然还是会打断实时进程,但所执行的操作只是唤醒中断线程,原本的中断服务程序被放到了一个内核线程中,延迟执行。

    这样中断执行的速度就很快也很有确定性,实时进程被打断后可以迅速再次运行,至于中断服务程序,就在优先满足实时进程的情况下,再被调度执行。

    从中断线程化的初衷看,当前这种情况根本就不适用。

    1.这个中断服务程序非常简单,没必要线程化。强行线程化对实时性的改善不大,反而会带来不必要的开销。

    2.这个中断服务程序非常关键,其中采集的数据的实时性也非常重要,不应该被延迟执行。中断切换回实时进程后,实时进程依赖这些数据,还是要等这个进程把数据取出。

    解决

    解决方式很简单,对于这个具体的中断,取消线程化,让它变回一个朴素的中断。中断线程化的机制虽好,也要分情况来使用,不然反而会造成系统的巨大负担。

    代码改动是在request_irq时,传入IRQF_NO_THREAD标志,即可避免这个中断被线程化。

    实际做改动还要注意,RT_PREEMPT使用rt_mutex代替传统的禁用抢占的spin_lock,因此如果需要用真正的spin_lock,需要使用raw_spin_lock_t

    在这个具体的例子中,中断大概为一万两千次/秒,取消线程化之后,CPU占用率下降了约10%,效果显著。

    展开全文
  • linux 中断线程化

    2021-05-11 09:22:05
    因此内核的目标就是让中断尽可能快的处理完,尽其所能把更多的处理工作向推迟。为此Linux把中断的处理分成上半部分和下半部分。上半部分立即执行,下半部分将 唤醒相应的和中断处理相关的进程稍后执行。固然这种...

    一、原理

    中断处理是由内核执行的最敏感的任务之一,当内核正打算往做一些别的事情时,中断随时会到来,中断当前的任务进而执行中断处理程序。因此内核的目标就是让中断尽可能快的处理完,尽其所能把更多的处理工作向后推迟。为此Linux把中断的处理分成上半部分和下半部分。上半部分立即执行,下半部分将 唤醒相应的和中断处理相关的进程稍后执行。固然这种机制使得中断处理变得更加高效和易于维护,但是对于系统假如有严重的网络负载或其他I/O负载时,中断将非常频繁,内核当前的实时任务会被不停中断,这对于Linux的实时应用来说是不可接受的。

    另外,Linux为了使内核同步而采用了关中断,在内核的关中断区域,中断是被屏蔽的。即使此时有通过中断驱动的实时任务也得不到响应,增加了实时任务的中断延迟。实时化后的Linux中,自旋锁被互斥锁取代,而中断处理代码中大量运用了自旋锁,中断处理代码就有可能由于得不到锁而需要被挂到该锁的等待队列上。但是只有可调度的进程才可这么做,假如中断处理代码仍然使用原来的自旋锁,那么互斥锁取代自旋锁改进内核实时性的努力将大打折扣。

    线程化的中断可以有效的解决这些问题。中断线程化后,中断将作为内核线程运行而且赋予不同的实时优先级,实时任务可以有比中断线程更高的优先级,这样,实时任务就可以作为最高优先级的执行单元来运行,即使在严重负载下仍有实时性保证。另一方面中断处理线程也可以由于在内核同步中得不到锁而挂载到锁的等待队列中。很多关中断就不必真正的禁止硬件中断了,而是禁止内核进程抢占,这样就可以减小中断延迟。

    中断线程化的基本原理就是尽量减少IRQ的操作,在RT patch中,IRQ所做的工作就是屏蔽中断线以及唤醒中断服务线程。剩余的工作由中断线程完成

    二、测试

    1、测试环境搭建

    我们采用两台主机来完成测试工作,其中一台主机(p1)充当客户端,运行另一个主机(p2)充当服务器。

    客户端的主机安装的是linux-3.6.1,并且打过实时补丁的内核。在客户端的主机上运行test测试程序,该测试程序创建一个实时优先级为50,实时调度策略为FIFO的实时进程。

    服务器主机上运行netperf想客户端发送数据包,来测试网络吞吐量。

    在进行上述测试之前,还需要进行一些初始化工作:

    a、将两台计算机直连

    b、启动netserver

    c、关闭防火墙

    d、两台主机都运行于单核模式(确保中断处理线程和网络处理的相关程序都运行于同一个cpu上)

    2、测试步骤

    a、创建实时进程#include

    #include

    #include

    #include

    #include

    #include

    #include

    #define __USE_GNU

    #include

    #include

    #include

    int main(int argc,char* argv[])

    {

    int i;

    struct sched_param param;

    int ret = 0;

    if(argc != 3)

    {

    fprintf(stderr,"usage:./test sched_method sched_priority\n");

    return -1;

    }

    int sched_method = atoi(argv[1]);//设置实时进程调度策略

    int sched_priority = atoi(argv[2]);//设置实时进程优先级

    if(sched_method > 2 || sched_method 

    {

    fprintf(stderr,"sched_method scope [0,2]\n");

    return -2;

    }

    if(sched_priority > 99 || sched_priority 

    {

    fprintf(stderr,"sched_priority scope [1,99]\n");

    return -3;

    }

    if(sched_method == 1 || sched_method == 2)

    {

    param.sched_priority = sched_priority;

    ret = sched_setscheduler(getpid(),sched_method,&param);

    if(ret)

    {

    fprintf(stderr,"set scheduler to %d %d failed %m\n");

    return -4;

    }

    }

    int scheduler = sched_getscheduler(getpid());

    fprintf(stderr,"the scheduler of PID(%ld) is %d, priority (%d),BEGIN !\n",

    getpid(),scheduler,sched_priority);

    while (1);

    return 0;

    }

    对源文件进行编译:

    #gcc test.c  -o test

    #test 1 50

    b、通过chrt命令修改网卡中断的优先级

    c、在服务器上使用netperf测试网络吞吐量

    3、测试结果

    当网卡中断的优先级小于等于50时,吞吐量为0

    当网卡中断的优先级高于50时,吞吐量约为13.5

    当网卡中断的优先级高于50时,此时将服务器和客户端的netserver进程的优先级都设置为50以上,吞吐量约为93,与不运行实时进程test时的吞吐量(94)接近。

    3、测试分析

    通过对上面的程序进行分析,我们得到:test使用的是FIFO的调度策略,实时优先级为50,在此处将test的优先级设置为50是因为在系统中,中断线程的实时优先级默认为50。我们发现,将中断线程的优先级设置为50以下时,系统无法响应网络中断,此时吞吐量为0。当中断线程的优先级设置的高于50时,此时系统可以响应网络中断,但是吞吐量仅为13M/s左右。因为中断线程只是做了一下简单的操作,比如屏蔽中断线以及唤醒中断服务程序等,正在的数据处理的工作还是要netserver来处理的。所以,当我们将netserver的优先级设置为50以上时,网络的吞吐量就几乎不受test实时进程的影响了。

    4、结论

    通过上面的分析我们可以看出,中断线程化可以是我们通过简单的操作修改中断的优先级,从而使系统可以优先处理某些我们希望及时处理的进程,从而提高这些进程的实时性。

    展开全文
  • 之前使用的用内核线程去处理中断(任务队列),对于单CPU系统来说,是很高效的一种方式,但是随着CPU越来越多,这种方法就显得不是很高效。因为,一个CPU只能创建一个内核线程Kworker。多个中断的work都是由一个...

    前言

    之前使用的用内核线程去处理中断(任务队列),对于单CPU系统来说,是很高效的一种方式,但是随着CPU越来越多,这种方法就显得不是很高效。因为,一个CPU只能创建一个内核线程Kworker。多个中断的work都是由一个worker线程来处理。这会导致内核线程kworker对CPU的占用率过高,而其他CPU却空着。这对于多CPU系统来说,显然不能被接收!!

    1 改进

    改进的地方在于:我们不用再自己定义work结构体,也无需再使用函数schedule_work(&work)。
    我们可以使用request_threaded_irq()函数来指定我们为某个中断分配何种中断处理函数:

    request_threaded_irq(哪个中断,上半部函数(可以为空),中断处理函数)

    他会给每个中断单独创建一个内核线程。这样,当中断发生的时候,上半部函数就会执行,上半部执行结束以后,他会唤醒内核线程。在内核线程中,执行中断处理函数。
    这样,对于每个中断,都有机会被创建成一个独立的线程,每个线程,都可以在任意一个CPU上执行。对于多CPU(SMP)系统来说,是非常有意义的。

    2 request_irq 和request_threaded_irq的区别:

    request_irq()这个函数用于为申请一个中断,是request_threaded_irq的一个包装(request_threaded_irq中的参数thread_fn(在线程中运行的函数)
    在request_irq()中为NULL)。所以,没有办法通过request_irq 来实现中断线程化,要申请支持中断线程化的只能使用request_threaded_irq。
    在这里插入图片描述
    我们可以值提供thread_fn()函数,系统就会为我们创建一个内核线程。当中断发生的时候们就会执行上半部的函数,在上半部中,唤醒某个内核线程,这个线程就会执行thread_fn()函数。

    3 内核机制

    在这里插入图片描述

    4 总结:

    下半部要做的事情不是很长,且不复杂:tasklet
    下半部要做的事情很长,且复杂:工作队列
    对于多CPU ,可以为每个中断分配一个线程,这样,每个中断都可以在任意一个CPU得到响应。

    展开全文
  • Java线程中断机制

    2021-03-15 20:57:50
    1. 引言对Java中断没有一个全面的了解,可能会误以为被中断线程将立马退出运行,但事实并非如此。中断机制是如何工作的?捕获或检测到中断后,是抛出InterruptedException还是重设中断状态以及在方法中吞掉中断...
  • 阻塞和非阻塞、中断线程化一、阻塞和非阻塞1、应用层2、驱动层二、中断线程化1、创建线程化中断 request_threaded_irq2、卸载中断 free_irq 一、阻塞和非阻塞 所谓阻塞,就是等待某件事情发生。比如调用 read ...
  • 很多情况下,使用信号来终止一个长时间运行的线程是合理的。这种线程的存在,可能是因为工作线程所在的线程池被销毁,或是用户...C11标准没有提供这样的机制(草案上有积极的建议,说不定中断线程会在以后的C标准中添加
  • 在线程阻塞时中断线程的4中状态:(1) 新建(new):线程被创建时,它只会短暂的处于这种状态.此时线程已经分配了必须的系统资源,并执行了初始.此刻线程已经有资格获取CPU时间,之后调度器将把这个线程转变为可运行状态或...
  • 结果如下:.....Number 81701 is PrimeNumber 81703 is PrimeNumber 81707 is PrimeNumber 81727 is PrimeNumber 81737 is PrimeNumber 81749 is PrimeThe Prime Generator has been Interrupted线程类有一个布尔型...
  • linux 中断机制浅析

    2021-05-15 03:53:07
    广义上的中断可以分为外部中断和内部中断(异常)中断是由外部事件引起的,一般分为可屏蔽的中断与非可屏蔽的中断,所谓可屏蔽就是可以通过设置CPU的IF标志位进行屏蔽,而非可屏蔽的是一些非常紧急的事件,往往IF对其...
  • 中断在驱动中是非常常用的,无论是外部的 GPIO 中断,还是 SPI,I2C 等发送或接收中断,都是必不可少的。所以今天来看看 Linux 中的中断处理。 上面我们根据中断来源,屏蔽方式和中断入口对中断进行了简单的分类...
  • 底半部:线程化IRQ线程化中断的支持在2009年已经进入Linux官方内核,详见Thomas Gleixner的patch:http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=3aa551c9b4c40018f0e261a178e3d...
  • 如何中断JAVA线程

    2021-03-02 10:59:28
    尽管,其名称似乎在暗示着什么,然而,这种方法并不会中断一个正在运行的线程(待会将进一步说明),正如ListingA中描述的那样。它创建了一个线程,并且试图使用Thread.interrupt方法停止该线程。Thread.sleep()方法的...
  • 生产者与消费者问题本质是:解决线程间互斥关系和同步关系问题 由于缓冲区是临界资源,它一个时刻只允许一个生产者放入消息,或者一个消费者从中取出消息,所以需要解决互斥访问的问题。 同时生产者和消费者又是一...
  • java 线程 中断标志位

    2021-03-16 17:56:10
    课程素材来自 http://enjoy.ke.qq.com/ 版权所有java线程中,线程中断方法详解:线程自然终止:自然执行完...java线程是协作式,而非抢占式调用一个线程的interrupt() 方法中断一个线程,并不是强行关闭这个线程,只...
  • @[toc]并发中断上半部、下半部的概念设备的中断会打断内核进程中的正常调度和运行,系统对更高吞吐率的追求势必要求中断服务程序尽可能短小精悍。可是,这个良好的愿望每每与现实并不吻合。在大多数真实的系统中,当...
  • 1. 引言当我们点击某个杀毒软件的取消按钮来停止查杀病毒时,当我们在控制台敲入quit命令以结束某个后台服务时……都需要通过一个线程去取消另一个线程正在执行的任务。...捕获或检测到中断后,是抛出Interrup...
  • 线程中断

    2021-03-08 19:40:28
    Java中实现线程中断有如下几种常用方法: public void stop() 在新版JDK中已不推荐使用 public void interrupt() public boolean isInterrupted() public void interrupt() { if (this != Thread.current...
  • 通过实现Runnable接口创建,开启,休眠和中断线程。 ** 1.创建线程 在Android中,提供了两种创建线程的方法,一种是通过Thread类的构造方法创建线程对象,并重写run()方法实现,另一种是通过Runnable接口实现。 (1)....
  • 前文从任务到线程:Java结构并发应用程序中介绍了如何安排任务启动线程线程在启动之后,正常的情况下会运行到任务完成,但是有的情况下会需要提前结束任务,如用户取消操作等。可是,让线程安全、快速和可靠地...
  • 线程中断方法

    2021-03-20 13:50:48
    1. 无法停止的线程 ... interrupt方法并不会中断当前正在运行的线程。 2. 只是在这个线程状态上打上中断标记。 3. interrupt会抛出InterruptedException异常。 */ class MyThread extends Thread{ @Override
  • KVM中断虚拟(一)

    千次阅读 2021-12-01 09:57:43
    因此,在本章中,我们简单介绍硬件中断的基本原理,然后结合中断的基本原理讨论如何虚拟化中断芯片。我们从起初IBM PC为单核系统设计的PIC(8259A)机制开始,讨论到为多核系统设计的APIC,一直到绕开I/O APIC、从设备...
  • 一、了解多线程的创建从这里开始,我们来了解线程的创建,一般有以下多种方式等创建方式继承Thread类实现Runnable接口继承Thread类和实现Runnable接口,这两种方式可以说是中规中矩的,也是我们用的比较多的创建线程...
  • C#多线程的一些操作,Sleep、Join、Interupt、暂停与恢复(重点)、终止
  • 1.线程可以被sleep()中断,但这种中断属于阻塞线程线程仍然可以获得cpu的执行权,如果睡眠中的线程不是后台进程且当主线程执行完时jvm不会停止还会等到睡眠中的线程。当然如果睡眠中被interrupted中断会抛出异常...
  • Java NIO中InterruptibleChannel接口表示通道IO阻塞时可被异步的关闭和中断。public interface InterruptibleChannel extends Channel{/*** Closes this channel.** Any thread currently blocked in an I/O ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 173,923
精华内容 69,569
关键字:

中断线程化后如何查看