`
totoxian
  • 浏览: 1034003 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

linux的中断线程化实现

 
阅读更多

2.6.25.8内核实现了中断线程化,内核为每一个中断向量建立了一个中断线程,具体就是在结构irq_desc中增加了一个task_struct来代表这个线程:

struct irq_desc {

irq_flow_handler_t handle_irq;

struct irq_chip *chip;

struct msi_desc *msi_desc;

void *handler_data;

void *chip_data;

struct irqaction *action; /* IRQ action list */

unsigned int status; /* IRQ status */

unsigned int depth; /* nested irq disables */

unsigned int wake_depth; /* nested wake enables */

unsigned int irq_count; /* For detecting broken IRQs */

unsigned int irqs_unhandled;

unsigned long last_unhandled; /* Aging timer for unhandled count */

struct task_struct *thread; //中断线程

wait_queue_head_t wait_for_handler;

cycles_t timestamp;

raw_spinlock_t lock;

const char *name;

}

在 中断产生的时候,还是和往常一样进入do_IRQ,这个函数几乎没有什么变化,在do_IRQ中调用了irq_desc的handle_irq函数,这个 handle_irq是向量相关的,比如有边缘触发等等,这个方式涉及到了硬件规程,故不深入讨论,实际上,每个总线邦定到一个中断向量,而总线的中断方式是总线相关的所以中断向量的方式也就和硬件相关了,这里就以Level type为例来说明,Level type的handle_irq是handle_level_irq:

void handle_level_irq(unsigned int irq, struct irq_desc *desc)

{

unsigned int cpu = smp_processor_id();

struct irqaction *action;

irqreturn_t action_ret;

spin_lock(&desc->lock);

mask_ack_irq(desc, irq); //屏蔽该中断,以防重入

if (unlikely(desc->status & IRQ_INPROGRESS))//如果正在处理则返回

goto out_unlock;

desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);

kstat_cpu(cpu).irqs[irq]++;

action = desc->action;

if (unlikely(!action || (desc->status & IRQ_DISABLED)))//禁用则返回

goto out_unlock;

desc->status |= IRQ_INPROGRESS; //标记为正在处理

if (redirect_hardirq(desc)) //检测是否为线程化中断,若是则唤醒中断线程

goto out_unlock;

spin_unlock(&desc->lock);

action_ret = handle_IRQ_event(irq, action); //非线程化中断,处理之

if (!noirqdebug)

note_interrupt(irq, desc, action_ret);

spin_lock(&desc->lock);

desc->status &= ~IRQ_INPROGRESS;

if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)

desc->chip->unmask(irq);

out_unlock:

spin_unlock(&desc->lock);

}

我们看看每个中断向量的中断线程是怎么初始化的,初始化的细节可以带给我们一大部分必要的信息,在实际开发中一定注意这一点,一个好的初始化带来的是将来操作的方便与清晰:

void __init init_hardirqs(void)

{

int i;

ok_to_create_irq_threads = 1;

for (i = 0; i

irq_desc_t *desc = irq_desc + i;

if (desc->action && !(desc->status & IRQ_NODELAY)) //有IRQ_NODELAY标志的中断不允许线程化

start_irq_thread(i, desc);//实际建立线程

}

}

static int start_irq_thread(int irq, struct irq_desc *desc)

{

if (desc->thread || !ok_to_create_irq_threads)

return 0;

desc->thread = kthread_create(do_irqd, desc, "IRQ-%d", irq);//建立一个内核线程,赋值给desc->thread。

if (!desc->thread) {

return -ENOMEM;

}

smp_mb();

wake_up_process(desc->thread); //一切就绪之前即desc->thread被赋值之前可能已经有了中断,故唤醒该中断线程处理之。

return 0;

}

static int do_irqd(void * __desc)

{

struct sched_param param = { 0, };

struct irq_desc *desc = __desc;

current->flags |= PF_NOFREEZE | PF_HARDIRQ;

param.sched_priority = MAX_USER_RT_PRIO/2;

sys_sched_setscheduler(current->pid, SCHED_FIFO, &param); //设置实时优先级

while (!kthread_should_stop()) {

local_irq_disable_nort();

do {

set_current_state(TASK_INTERRUPTIBLE);//一定设置这个标志,否则很少有进程可以抢占中断线程,毕竟它是实时线程,如果不设这个标志,即使下面它自己schedule了,那么很大的可能性还是会选中它的

do_hardirq(desc); //处理中断请求

} while (current->state == TASK_RUNNING);

local_irq_enable_nort();

schedule(); //一轮处理完毕后切换到别的进程,实际上除了实时进程可能抢占中断线程,中断线程被强占的可能性极小,因此要主动切出。

}

__set_current_state(TASK_RUNNING);

return 0;

}

static void do_hardirq(struct irq_desc *desc)

{

unsigned long flags;

spin_lock_irqsave(&desc->lock, flags);

if (!(desc->status & IRQ_INPROGRESS))

goto out;

...

else if (desc->handle_irq == handle_level_irq)

thread_level_irq(desc);

...

else if (desc->handle_irq == handle_edge_irq)

thread_edge_irq(desc);

else

thread_do_irq(desc);

out:

spin_unlock_irqrestore(&desc->lock, flags);

if (waitqueue_active(&desc->wait_for_handler))

wake_up(&desc->wait_for_handler);

}

最终在thread_XX_irq中调用handle_IRQ_event来实际处理中断请求。当该中断向量上没有中断要处理的时候,对应的中断线程就主动切出了,而中断来临的时候redirect_hardirq会wakeup对应向量上的中断线程。
现在我们来看看linux中断线程化的意义,传统的linux内核上,中断都是作为最高优先级的执行绪存在的,它实际上并没有什么软件优先级的概念,而是 硬件架构决定了硬件中断到来的时候在该中断没有被屏蔽的条件下必须处理,即便是linux中最高优先级的实时进程也要向中断让路,这就大大削弱了 linux的实时性能,一个实时任务正在运行,将一直被中断打断,特别是在网络负载大的时候,虽然linux将耗时的操作都置于软中断,但是毕竟哪怕很小 延时的硬件中断也要延时,多个小的延时积累起来可能会有很大的延时,这不是实时操作所希望的,于是就有了一种想法,能否让中断也参与到优先级排队,于是中断线程化就是必然结果了。可是即便大操作放到了线程中,但是毕竟像common_interrupt和do_IRQ还是没有在线程中进行,因此还是会有中 断打断实时任务,linux的这种中断线程化实现仅仅将实时任务被硬件打断的延时降低到了很低的程度,实时任务被中断打断本身并没有得到改善,改善这个境地的一个方案就是引入硬件中断优先级并和线程优先级联系,在处理实时任务时非使能屏蔽掉不相关的任何硬件中断,使它们不再发生,就像solaris那样,当然这可以利用硬件的特性,引入“cpu当前优先级”的概念,当cpu处于优先级p时,任何低于p的中断都不能发生,cpu当前优先级和线程优先级以及中 断优先级直接关联,关于这个方案的实现可以参考windows的IRQL或者solaris的IPL。

分享到:
评论

相关推荐

    linux的中断线程化实现[借鉴].pdf

    linux的中断线程化实现[借鉴].pdf

    Linux 中的各种栈:进程栈 线程栈 内核栈 中断栈

    ---------------------------------------------------Linux 中的各种栈:进程栈 线程栈 内核栈 中断栈

    linux软中断源码

    linux软中断,软中断是linux系统原“底半处理”的升级,在原有的基础上发展的新的处理方式,以适应多cpu 、多线程的软中断处理。

    spi.rar_linux 多线程_spi

    这是一个spi模块的程序,对于深入了解linux驱动编程非常有益。其中涉及了中断、调度、多线程编程等

    linux 系统性能相关1.rar

     Linux Virtual Server (LVS)之ksoftirqd进程耗尽单核100%si处理软中断导致性能瓶颈; Linux 线程库性能测试与分析; 网卡软中断不能分发到CPU多核 问题的说明; Linux的实时性能测试.pdf  多核处理器上,怎样将...

    深入分析Linux内核源码.chm

    3.2中断描述符表的初始化 3.3异常处理 3.4 中断处理 3.5中断的后半部分处理机制 第四章 进程描述 4.1 进程和程序(Process and Program) 4.2 Linux中的进程概述 4.3 task_struct结构描述 4.4 task_struct结构在内存...

    基于Linux的嵌入式心电监护仪

    在心电监护系统中引入嵌入式Linux操作系统,将操作系统作为嵌入式系统软硬件协同开发的核心,合理管理和调度资源,为智能化应用提供软件应用平台,针对通用Linux在实时性能方面的不足,提出以中断线程化、改进实时...

    linux操作系统大全

    13.中断和中断处理 14.设备驱动程序 15.文件系统 16.网络系统 17.系统内核机制 18.linux内核编程模块 19.有关进程通信的编程 20.高级线程编程 21.linux网络编程 22.linux IO编程 23.linux系统管理员安全 24.linux...

    嵌入式中断总结

    在 Linux 中,中断具有最高的优先级。不论在任何时刻,只要产生中断事件,内核将立即执行相应的中断 处理程序,等到所有挂起的...中断线程化之后,中断将作为内核线程运行而且被赋予不同的实时优先级,实时任务可以。

    清华大学Linux操作系统原理与应用

    8.6.1 Linux文件系统的实现要素 189 8.6.2 什么是romfs文件系统 191 8.6.3 romfs文件系统的布局与文件结构 191 8.6.4 具体实现的对象 192 习题8 195 第9章 设备驱动 196 9.1 概述 196 9.2 设备驱动程序基础 198 ...

    Linux2.6内核标准教程(共计8-- 第1个)

    Linux内核是Linux操作系统中最核心的部分,用于实现对硬件部件的编程控制和接口操作。《Linux2.6内核标准教程》深入、系统地讲解了 Linux内核的工作原理,对Linux内核的核心组件逐一进行深入讲解。 全书共8章,首先...

    操作系统课件

    中央处理器 2.2 中断技术 2.3 进程及其实现 2.4 线程及其实现 2.5 Linux进程和线程 2.6 Windows 2003进程和线程 2.7 处理器调度 2.8 处理器调度算法 2.9 Linux调度算法 2.10 Windows 2003调度算法

    Linux2.6内核标准教程(共计8--第6个)

    Linux内核是Linux操作系统中最核心的部分,用于实现对硬件部件的编程控制和接口操作。《Linux2.6内核标准教程》深入、系统地讲解了 Linux内核的工作原理,对Linux内核的核心组件逐一进行深入讲解。 全书共8章,首先...

    嵌人式Linux实时性研究 (2011年)

    在该方案中包含了一种新的中断线程化方法,并将其在1386测试结果表明平台上实现。开发了专用的测试模块,并使用Linux内核保留的中断号测试中断线程化效果。该方案能很好地解决中断对实时任务的干扰问题,对提高Linux...

    深入分析Linux内核源码

    5.2.2.Linux实现时钟中断的全过程 5.3 Linux的调度程序-Schedule( ) 5.3.1 基本原理 5.3.2 Linux进程调度时机 5.3.3 进程调度的依据 5.3.4 进程可运行程度的衡量 5.3.5 进程调度的实现 5.4 进程切换 ...

    linux操作系统内核技术-uestc课件

     5熟悉在x86体系结构上Linux中断和异常的处理原理,中断注册、共享、控制,和中断上下文的意义,中断和设备驱动程序的关系,以及设备驱动程序结构和用户接口。(4小时)  6中断处理程序被分解为top half和bottom ...

    Linux2.6内核标准教程(共计8--第8个)

    Linux内核是Linux操作系统中最核心的部分,用于实现对硬件部件的编程控制和接口操作。《Linux2.6内核标准教程》深入、系统地讲解了 Linux内核的工作原理,对Linux内核的核心组件逐一进行深入讲解。 全书共8章,首先...

    Linux高级编程(无加密版)

    第13章 中断和中断处理 第14章 设备驱动程序 第15章 文件系统 第16章 网络系统 第17章 系统内核机制 第四篇 Linux系统高级编程 第18章 Linux内核模块编程 第19章 有关进程通信的编程 第20章 高级线程编程 第21章 ...

    Linux2.6内核标准教程(共计8--第3个)

    Linux内核是Linux操作系统中最核心的部分,用于实现对硬件部件的编程控制和接口操作。《Linux2.6内核标准教程》深入、系统地讲解了 Linux内核的工作原理,对Linux内核的核心组件逐一进行深入讲解。 全书共8章,首先...

    Linux2.6内核标准教程(共计8--第7个)

    Linux内核是Linux操作系统中最核心的部分,用于实现对硬件部件的编程控制和接口操作。《Linux2.6内核标准教程》深入、系统地讲解了 Linux内核的工作原理,对Linux内核的核心组件逐一进行深入讲解。 全书共8章,首先...

Global site tag (gtag.js) - Google Analytics