【Linux kernel】Timing

本文深入探讨了Linux内核中的定时器机制,包括低精度和高精度定时器的实现,以及它们如何在不同场景下进行切换和调度。重点介绍了tick中断处理函数、hrtimer初始化与操作,以及如何在do_nanosleep中使用hrtimer实现精确睡眠。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Droidphone: http://blog.youkuaiyun.com/droidphone/article/category/1263459


timer

/**
 * getnstimeofday - Returns the time of day in a timespec
 * @ts:		pointer to the timespec to be set
 *
 * Returns the time of day in a timespec.
 */
void getnstimeofday(struct timespec *ts)



/* Timekeeper helper functions. */
static inline s64 timekeeping_get_ns(void)


CONFIG_HZ的值?

/**
 * idle_cpu - is a given cpu idle currently?
 * @cpu: the processor in question.
 */
int idle_cpu(int cpu)

start_kernel()  //内核启动时
    ->init_timers() //注册低精度timer软中断
    {
        open_softirq(TIMER_SOFTIRQ,run_timer_softirq); 
    }
    ->hrtimers_init()  //注册高精度timer软中断
    {
        open_softirq(HRTIMER_SOFTIRQ,run_hrtimer_softirq);
    }
    ->softirq_init()
    {
         open_softirq(TASKLET_SOFTIRQ,tasklet_action);
         open_softirq(HI_SOFTIRQ, tasklet_hi_action);  
    }

arm timer中断处理函数://linux3.4
arch_timer_handler_cp15()  //在arch_timer_of_register()->arch_timer_common_register()中注册
->arch_timer_handler()
	->evt->event_handler(evt) //初始时是低精度timer的中断处理函数tick_handle_periodic(),当启用了高精度timer时,会被修改为hrtimer_interrupt()*/
	
	
tick_handle_periodic()
->tick_periodic()
	->update_process_times()
		->run_local_timers()
			->hrtimer_run_queues() //1)在低精度模式下运行高精度hrtimer的接口函数(在低精度的tick中断handler里被调用)
				->__run_hrtimer(timer, &base->softirq_time); //处理hrtimer
			->raise_softirq(TIMER_SOFTIRQ) //2)随后在run_timer_softirq()启用高精度timer,此后就由hrtimer_interrupt()接管hrtimer的处理
			
run_timer_softirq() //低分辨率timer的软中断handler
{
	struct tvec_base *base = __this_cpu_read(tvec_bases);

	hrtimer_run_pending(); //IMPORTANT
	->if (tick_check_oneshot_change(!hrtimer_is_hres_enabled())) //1)如果hrtimer_is_hres_enabled返回0,表示系统不允许高精度模式,
	 //那么在tick_check_oneshot_change函数内,通过tick_nohz_switch_to_nohz切换至NOHZ_MODE_LOWRES低精度模式
		->tick_nohz_switch_to_nohz()
			->tick_switch_to_oneshot(tick_nohz_handler) //NOHZ_MODE_LOWRES低精度模式的handler是tick_nohz_handler(),它完成的工作类似于tick_handle_periodic()
	{
		hrtimer_switch_to_hres(); //2)如果系统允许高精度模式,切换到NOHZ_MODE_HIGHRES高精度模式,此后hrtimer工作在高精度模式下
		->tick_init_highres() //令 base->hres_active = 1; 
			->tick_switch_to_oneshot(hrtimer_interrupt) 
			//tick_device所关联的clock_event_device的事件回调函数会被修改为:hrtimer_interrupt(),并且会被设置成工作于CLOCK_EVT_MODE_ONESHOT单触发模式。
		->tick_setup_sched_timer() //因为tick_device将被高精度定时器接管,它将不会再提供原有的tick事件机制,所以需要由高精度定时器系统模拟一个tick事件设备,继续为系统提供tick事件能力,这个工作由tick_setup_sched_timer函数完成
	}
	if (time_after_eq(jiffies, base->timer_jiffies))
		__run_timers(base); //处理低精度timer
}
在do_nanosleep中,请求睡眠的进程会主动schedule(),主动让出CPU。
void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task)
{
	sl->timer.function = hrtimer_wakeup;  //该hrtimer过期时调用的回调函数,该函数会唤醒task
	sl->task = task;
}

static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
{
	hrtimer_init_sleeper(t, current); //初始化一个用于当前task的timer

	do {
		set_current_state(TASK_INTERRUPTIBLE);
		hrtimer_start_expires(&t->timer, mode); //将hrtimer加到percpu的timerqueue中
		if (!hrtimer_active(&t->timer))
			t->task = NULL;

		if (likely(t->task))
			schedule();  //主动schedule()

		hrtimer_cancel(&t->timer);
		mode = HRTIMER_MODE_ABS;

	} while (t->task && !signal_pending(current));

	__set_current_state(TASK_RUNNING);

	return t->task == NULL;
}

/**
 * struct hrtimer - the basic hrtimer structure
 * @node:	timerqueue node, which also manages node.expires,
 *		the absolute expiry time in the hrtimers internal
 *		representation. The time is related to the clock on
 *		which the timer is based. Is setup by adding
 *		slack to the _softexpires value. For non range timers
 *		identical to _softexpires.
 * @_softexpires: the absolute earliest expiry time of the hrtimer.
 *		The time which was given as expiry time when the timer
 *		was armed.
 * @function:	timer expiry callback function
 * @base:	pointer to the timer base (per cpu and per clock)
 * @state:	state information (See bit values above)
 * @start_site:	timer statistics field to store the site where the timer
 *		was started
 * @start_comm: timer statistics field to store the name of the process which
 *		started the timer
 * @start_pid: timer statistics field to store the pid of the task which
 *		started the timer
 *
 * The hrtimer structure must be initialized by hrtimer_init()
 */
struct hrtimer {
	struct timerqueue_node		node;  //如果不允许该timer有slack时(比如对于RT(实时)进程),node->expires==_softexpires
	ktime_t				_softexpires; //该timer的最早的过期时间(当允许该timer有slack时,默认的slack是50000ns, 见task_struct->timer_slack_ns)
	enum hrtimer_restart		(*function)(struct hrtimer *);  //到期的callback
	struct hrtimer_clock_base	*base;
	unsigned long			state;  //见#define HRTIMER_STATE_ENQUEUED 	0x01等
#ifdef CONFIG_TIMER_STATS
	int				start_pid;     //启动该hrtimer的进程的信息,见timer_stats_hrtimer_set_start_info()
	void				*start_site;  
	char				start_comm[16];
#endif
};

struct timerqueue_node {
	struct rb_node node;
	ktime_t expires;
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值