进程调度之tick_init

本文详细介绍了Linux内核中时钟源(clocksource)机制的实现原理与配置过程,特别是针对2.6.23版本内核的具体实现细节。通过解析时钟源对象结构及其配置方法,展示了如何计算时钟频率,并深入探讨了tick初始化流程。

clocksource 时钟源对象,一个例子是

static struct clocksource clocksource_hpet = {
        .name           = "hpet",
        .rating         = 250,
        .read           = read_hpet,
        .mask           = CLOCKSOURCE_MASK(64),
	.mult		= 0, /* to be calculated */
        .shift          = 10,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
};

计算时钟源的频率

static int __init calibrate_APIC_clock(void)

static unsigned long pit_calibrate_tsc(u32 latch, unsigned long ms, int loopmin)

 

如下是2.6.23的内核的实现

 

void __init tick_init(void)
	=>clockevents_register_notifier(&tick_notifier);
		=>ret = raw_notifier_chain_register(&clockevents_chain, nb);
			=>static struct notifier_block tick_notifier = {
				.notifier_call = tick_notify,
			};
				=>tick_notify
					=>switch (reason) {
						case CLOCK_EVT_NOTIFY_ADD:
							return tick_check_new_device(dev);
							=>tick_setup_device(td, newdev, cpu, cpumask);
								=>if (td->mode == TICKDEV_MODE_PERIODIC)
									tick_setup_periodic(newdev, 0);
										=>tick_set_periodic_handler(dev, broadcast);
											=>if (!broadcast)
												dev->event_handler = tick_handle_periodic;
													=>clockevents_program_event
														=>return dev->set_next_event((unsigned long) clc, dev);
													=>tick_periodic(cpu);
														=>update_process_times(user_mode(get_irq_regs()));
															=>scheduler_tick();
																=>__update_rq_clock(rq);
																=>if (curr != rq->idle) /* FIXME: needed? */
																	curr->sched_class->task_tick(rq, curr);//Sched_fair.c (c:\linux\linux-2.6.23\kernel):	.task_tick		= task_tick_fair,
																		=>task_tick_fair
																			=>entity_tick(cfs_rq, se);
																				=>dequeue_entity(cfs_rq, curr, 0);
																				=>enqueue_entity(cfs_rq, curr, 0);
																				=>next = __pick_next_entity(cfs_rq);
																				=>__check_preempt_curr_fair(cfs_rq, next, curr, sched_granularity(cfs_rq));
											else
												dev->event_handler = tick_handle_periodic_broadcast;
										=>clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
											=>dev->set_mode(mode, dev);
											=>dev->mode = mode;

 

由于Linux操作系统是开源的,因此其进程调度算法的代码可以在其代码库中找到。具体来说,Linux使用完全公平调度算法(CFS)作为其默认的进程调度算法,其代码实现可以在内核源代码中的sched目录中找到。以下是一些示例代码: 1. CFS调度器代码: /* * Completely Fair Scheduler * * This file contains the code for the Completely Fair Scheduler, a * process scheduler based on a red-black tree. It implements a * proportional-share scheduling algorithm with low latency for * interactive tasks and high throughput for compute-bound tasks. * * Copyright (C) 2002-2007 Ingo Molnar <mingo@elte.hu> * Copyright (C) 2007-2011 Con Kolivas <kernel@kolivas.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ 2. 调度策略代码: /* Define a scheduling class */ static const struct sched_class fair_sched_class = { .next = &idle_sched_class, .enqueue_task = enqueue_task_fair, .dequeue_task = dequeue_task_fair, .yield_task = yield_task_fair, .check_preempt_curr = check_preempt_wakeup, .pick_next_task = pick_next_task_fair, .put_prev_task = put_prev_task_fair, #ifdef CONFIG_SMP .select_task_rq = select_task_rq_fair, .migrate_task_rq = migrate_task_rq_fair, .task_waking = task_waking_fair, .task_woken = task_woken_fair, #endif .set_curr_task = set_curr_task_fair, .task_tick = task_tick_fair, .task_fork = task_fork_fair, .task_dead = task_dead_fair, #ifdef CONFIG_FAIR_GROUP_SCHED .task_move_group = task_move_group_fair, #endif }; 3. 调度器初始化代码: void __init sched_init(void) { int i; /* Initialize the active and expired arrays for CFS */ for_each_possible_cpu(i) { struct rq *rq = cpu_rq(i); int j; /* Initialize the red-black tree for CFS */ for (j = 0; j < MAX_NICE; j++) { INIT_LIST_HEAD(&rq->cfs_rq[j].tasks); INIT_LIST_HEAD(&rq->cfs_rq[j].runnable); rb_init_node(&rq->cfs_rq[j].rb_node); } rq->cfs_rq[0].exec_clock = rq_clock(rq); rq->cfs_rq[1].exec_clock = rq_clock(rq); rq->cfs_rq[2].exec_clock = rq_clock(rq); rq->cfs_rq[3].exec_clock = rq_clock(rq); rq->cfs_rq[4].exec_clock = rq_clock(rq); rq->cfs_rq[5].exec_clock = rq_clock(rq); rq->cfs_rq[6].exec_clock = rq_clock(rq); rq->cfs_rq[7].exec_clock = rq_clock(rq); rq->cfs_rq[8].exec_clock = rq_clock(rq); rq->cfs_rq[9].exec_clock = rq_clock(rq); rq->cfs_rq[10].exec_clock = rq_clock(rq); rq->cfs_rq[11].exec_clock = rq_clock(rq); rq->cfs_rq[12].exec_clock = rq_clock(rq); rq->cfs_rq[13].exec_clock = rq_clock(rq); rq->cfs_rq[14].exec_clock = rq_clock(rq); rq->cfs_rq[15].exec_clock = rq_clock(rq); rq->nr_running = 0; rq->nr_uninterruptible = 0; rq->curr = NULL; INIT_LIST_HEAD(&rq->migration_queue); INIT_LIST_HEAD(&rq->expired); INIT_LIST_HEAD(&rq->active); rq->expired_timestamp = 0; rq->next_balance = jiffies + HZ; rq->skip_clock_update = 0; rq->idle_stamp = rq_clock(rq); rq->last_moved = jiffies; spin_lock_init(&rq->lock); spin_lock_init(&rq->task_lock); } /* Initialize the idle class */ init_idle(&init_task); init_idle(&ksoftirqd_task); init_idle(&migration_thread); /* Initialize the fair class */ sched_register_scheduler(&fair_sched_class); }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值