Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Timer Linux内核计时器函数在什么上下文中运行?_Timer_Linux Kernel_Kernel - Fatal编程技术网

Timer Linux内核计时器函数在什么上下文中运行?

Timer Linux内核计时器函数在什么上下文中运行?,timer,linux-kernel,kernel,Timer,Linux Kernel,Kernel,当使用add\u timerAPI创建的计时器过期并且在计时器结构处分配的函数运行时,它在什么上下文中运行?它是中断上下文还是某个内核进程上下文?当然是在中断上下文中,更准确地说,在softirq上下文中,请参见下面的(kernel/timer.c): 静态内联无效运行计时器(struct tvec_base*base) { 结构定时器列表*定时器; 旋转锁定irq(&base->lock); while(时间在相等(基频、基频->定时器基频)之后){ 结构清单\首件工作清单; 结构列表头*头=

当使用
add\u timer
API创建的计时器过期并且在计时器结构处分配的函数运行时,它在什么上下文中运行?它是中断上下文还是某个内核进程上下文?

当然是在中断上下文中,更准确地说,在softirq上下文中,请参见下面的(kernel/timer.c):

静态内联无效运行计时器(struct tvec_base*base)
{
结构定时器列表*定时器;
旋转锁定irq(&base->lock);
while(时间在相等(基频、基频->定时器基频)之后){
结构清单\首件工作清单;
结构列表头*头=&工作列表;
int index=base->timer\u jiffies和TVR\u MASK;
/*
*级联定时器:
*/
如果(!索引&&
(!级联(基和基->tv2,索引(0)))&&
(!级联(基和基->tv3,索引(1)))&&
!级联(基和基->tv4,索引(2)))
级联(基和基->tv5,索引(3));
++基本->定时器;
列表替换初始化(基本->tv1.vec+索引和工作列表);
而(!list_empty(head)){
无效(*fn)(未签字的多头);
无符号长数据;
布尔伊克萨菲;
计时器=列表第一个条目(头、结构计时器列表、条目);
fn=定时器->功能;
数据=定时器->数据;
irqsafe=tbase\u get\u irqsafe(计时器->基础);
定时器\统计\账户\定时器(定时器);
基本->运行计时器=计时器;
拆下计时器(计时器,底座);
if(irqsafe){
旋转解锁(&base->lock);
调用_timer_fn(timer,fn,data);//锁);
}否则{
旋转解锁irq(&base->lock);
调用_timer_fn(timer,fn,data);//锁);
}
}
}
基本->运行计时器=NULL;
旋转解锁irq(&base->lock);
}
/*
*此函数在下半部分上下文中运行计时器和计时器tq。
*/
静态无效运行计时器软irq(结构软irq动作*h)
{
struct tvec_base*base=u this_cpu_read(tvec_base);
hrtimer_run_pending();
if(时间在均衡(基频、基频->定时器)之后)
__运行计时器(基本);
}
void\uuu init\u计时器(void)
{
INTERR;
/*确保计时器->基指针中有足够的低位用于标记*/
构建错误(uuuuuuuuuuuuuuuuuuuuuu对齐(结构tvec_uuuu基)和计时器标志掩码);
err=计时器\u cpu\u通知(&计时器\u nb,(无符号长)cpu\u启动\u准备,
(void*)(long)smp_处理器_id());
init_timer_stats();
BUG_ON(err!=通知_OK);
寄存器\u cpu\u通知程序(&计时器\u nb);

打开_softirq(TIMER _softirq,run _TIMER _softirq);//你在说什么操作系统?如果你指的是Linux及其内核计时器,那么它就是中断上下文,因为
Linux/TIMER.c
中对
add_TIMER()
的注释说明:“内核将来将在->过期点从计时器中断执行->函数(->数据)回调。”虽然在某些内核中,中断处理程序可能在进程上下文中运行,但我不建议使用它。嗨,对不起,当然是Linux内核。谢谢。
static inline void __run_timers(struct tvec_base *base)
{
        struct timer_list *timer;

        spin_lock_irq(&base->lock);
        while (time_after_eq(jiffies, base->timer_jiffies)) {
                struct list_head work_list;
                struct list_head *head = &work_list;
                int index = base->timer_jiffies & TVR_MASK;

                /*
                 * Cascade timers:
                 */
                if (!index &&
                        (!cascade(base, &base->tv2, INDEX(0))) &&
                                (!cascade(base, &base->tv3, INDEX(1))) &&
                                        !cascade(base, &base->tv4, INDEX(2)))
                        cascade(base, &base->tv5, INDEX(3));
                ++base->timer_jiffies;
                list_replace_init(base->tv1.vec + index, &work_list);
                while (!list_empty(head)) {
                        void (*fn)(unsigned long);
                        unsigned long data;
                        bool irqsafe;

                        timer = list_first_entry(head, struct timer_list,entry);
                        fn = timer->function;
                        data = timer->data;
                        irqsafe = tbase_get_irqsafe(timer->base);

                        timer_stats_account_timer(timer);

                        base->running_timer = timer;
                        detach_expired_timer(timer, base);

                        if (irqsafe) {
                                spin_unlock(&base->lock);
                                call_timer_fn(timer, fn, data); // <=========== HERE
                                spin_lock(&base->lock);
                        } else {
                                spin_unlock_irq(&base->lock);
                                call_timer_fn(timer, fn, data); // <============ HERE
                                spin_lock_irq(&base->lock);
                        }
                }
        }
        base->running_timer = NULL;
        spin_unlock_irq(&base->lock);
}


/*
 * This function runs timers and the timer-tq in bottom half context.
 */
static void run_timer_softirq(struct softirq_action *h)
{
        struct tvec_base *base = __this_cpu_read(tvec_bases);

        hrtimer_run_pending();

        if (time_after_eq(jiffies, base->timer_jiffies))
                __run_timers(base);
}

void __init init_timers(void)
{
        int err;

        /* ensure there are enough low bits for flags in timer->base pointer */
        BUILD_BUG_ON(__alignof__(struct tvec_base) & TIMER_FLAG_MASK);

        err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
                               (void *)(long)smp_processor_id());
        init_timer_stats();

        BUG_ON(err != NOTIFY_OK);
        register_cpu_notifier(&timers_nb);
        open_softirq(TIMER_SOFTIRQ, run_timer_softirq); // <============= HERE
}