kernel 中断

2016-08-09  本文已影响0人  henry_zeng

中断#

中断分 向量中断非向量中断##

程序架构##

request & free##

flags若设置 IRQF_SHARED ,则表示多个设备共享中断

使能和屏蔽中断##

disable_irq_nosync()disable_irq() 的区别在于前者立即返回,而后者等待目前的中断处理完成。由于 disable_irq() 会等待指定的中断号被处理完,因此如果在n号中断顶半部调用 disable_irq(n) ,会引起系统死锁

底半部##

  1. tasklet
  2. 工作队列
  3. 软中断
  4. 线程化irq

tasklet###

执行上下文是软中断

void xxx_do_tasklet(unsigned long);
DECLEAR_TASKLET(xxx_tasklet, xxx_do_tasklet, NULL);

void xxx_do_tasklet(unsigned long)
{
    ...
}

irqreturn_t xxx_interrupt(int irq, void *dev_id)
{
    ...
    tasklet_schedule(&xxx_tasklet);
    ...
}

int __init xxx_init(void)
{
    ...
    result = request_irq(xxx_irq, xxx_interrupt, 0, "xxx", NULL);
    ...
    return IRQ_HANDLED;
}

void __exit xxx_exit(void)
{
    ...
    free_irq(xxx_irq, xxx_interrupt);
    ...
}

工作队列###

执行上下文是内核线程,可以调度和睡眠

struct work_struct xxx_wq;
void xxx_do_work(struct work_struct *work);

void xxx_do_work(struct work_struct *work)
{
    ...
}

irqreturn_t irqreturn_t xxx_interrupt(int irq, void *dev_id)
{
    ...
    schedule_work(&xxx_wq);
    ...
    return IRQ_HANDLED;
}

int __init xxx_init(void)
{
    ...
    result = request_irq(xxx_irq, xxx_interrupt, 0, "xxx", NULL);

    INIT_WORK(&xxx_wq, xxx_do_work);
    ...
    return IRQ_HANDLED;
}

void __exit xxx_exit(void)
{
    ...
    free_irq(xxx_irq, xxx_interrupt);
    ...
}

软中断###

硬件中断 软中断 信号 的区别
硬中断是外部设备对CPU的中断
软中断是中断底半部的一种处理机制
信号是由内核(或其他进程)对某个进程的中断

中断优先级高于软中断,软中断又高于任何一个线程。故软中断适度线程化,可以缓解高负载下系统的响应。

threaded_irq###

中断共享##

irqreturn_t xxx_interrupt(int irq, void *dev_id)
{
    int status = read_int_status();        /* 获知中断源 */
    if (!is_myint(dev_id, status))
        return IRQ_NONE;

    ...

    return IRQ_HANDLED;
}

int xxx_init(void)
{
    result = request_irq(sh_irq, xxx_interrupt, IRQF_SHARED, "xxx", xxx_dev);
    ...
}

void xxx_exit(void)
{
    free_irq(xxx_irq, xxx_interrupt);
    ...
}

内核定时器##

内核定时器

struct xxx_dev {
    struct cdev cdev;
    ...
    timer_list xxx_timer;
};

xxx_func1(...)
{
    struct xxx_dev *dev = filp->private;
    ...
    init_timer(&dev->xxx_timer);
    dev->xxx_timer.function = &xxx_do_timer;
    dev->xxx_timer.data = (unsigned long)dev;
    dev->xxx_timer.expires = jiffies + delay;

    add_timer(&dev->xxx_timer);
    ...
}

xxx_func2(...)
{
    del_timer(&dev->xxx_timer);
    ...
}

static void xxx_do_timer(unsigned long arg)
{
    struct xxx_device *dev = (struct xxx_device *)arg;

    dev->xxx_timer.expires = jiffies + delay;
    add_timer(&dev->xxx_timer);
    ...
}

内核延时##

短延时###

实现原理本质上是忙等待

引起进程睡眠,类似函数的精度受系统HZ以及进程调度的影响(实质调用 schedule_timeout()

长延时###

time_before() & time_after() 判断调用时的jiffies和传入的jiffies之前或之后

防止jiffies被编译器优化,内核将其定义为volatile,避免读合并

睡着延迟###

msleep() 实质调用 schedule_out() ,实现原理是向系统添加一个定时器,在定时器处理函数 process_timeout() 中唤醒与参数对应的进程

sleep_on_timeout() & interruptible_sleep_on_timeout() 将当前进程添加到等待队列,超时发生时,进程唤醒

上一篇 下一篇

猜你喜欢

热点阅读