博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OK6410A 开发板 (八) 65 linux-5.11 OK6410A linux tick与schedule
阅读量:4284 次
发布时间:2019-05-27

本文共 5170 字,大约阅读时间需要 17 分钟。

摘抄并整理 http://www.wowotech.net/timer_subsystem/time_subsystem_index.html
  • tick的概念
时间子系统1.0	1. 生产者		在每个architecture相关的代码中要有实现clock event和clock source模块。			clock event				就是通过timer硬件的中断处理函数完成的,在此基础上可以构建tick模块,tick模块维护了系统的tick				例如系统存在10ms的tick,每次tick到来的时候,timekeeping模块就增加系统时间				如果timekeeping完全是tick驱动,那么它精度只能是10ms			clock source				为了更高精度,clock source模块就是一个提供tick之间的offset时间信息的接口函数。				但是实际上并没有提供高精度	2.内核消费者		最初的linux kernel中只支持低精度的timer,也就是基于tick的timer。			如果内核采用10ms的tick,那么低精度的timer的最高的精度也只有10ms,想要取得us甚至ns级别的精度是不可能的。			各个内核的驱动模块都可以使用低精度timer实现自己的定时功能。			各个进程的时间统计也是基于tick的,内核的调度器根据这些信息进行调度。			System Load和Kernel Profiling模块也是基于tick的,用于计算系统负荷和进行内核性能剖析。	3.用户消费者		从用户空间空间来看,有两种需求			一种是获取或者设定当前的系统时间的接口函数:例如time,stime,gettimeofday等。			另外一种是timer相关的接口函数:例如setitimer、alarm等,当timer到期后会向该进程发送signal。	问题:		1. 嵌入式设备需要较好的电源管理策略 , 但是当前系统 周期性时钟会导致从低功耗(idle)状态进入高功耗,不符合电源管理的需求		2. 多媒体的应用程序需要非常精确的timer(ns),但是当前系统 不能提供足够精度的timer(ms)时间子系统2.0	改变:		A. 新增内核配置 CONFIG_NO_HZ_IDLE  // 在系统idle的时候,停掉周期性tick		B. 新增 高精度 timer ,同时 保留 低精度 timer		C. 其实 A B 的更改都是在 生产者 这块改动的,内核消费者与用户消费者都没变化	1.时间子系统2.0的选择		CONFIG_GENERIC_CLOCKEVENTS	2.时间子系统2.0下,针对A的配置,三种情况		a. 非idle,	  周期性tick idle,    周期性tick : CONFIG_HZ_PERIODIC		b. 非idle,	  周期性tick idle,停掉周期性tick : CONFIG_NO_HZ_IDLE		c. 非idle,停掉周期性tick idle,停掉周期性tick : CONFIG_NO_HZ_FULL	3.时间子系统2.0下,针对B的配置,两种情况		a. 无高精度timer : CONFIG_HIGH_RES_TIMERS=n		b. 有高精度timer : CONFIG_HIGH_RES_TIMERS CONFIG_TICK_ONESHOT// 在 时间子系统上封装出了// 1. tick device 	: 负责调度(周期性调度和非周期性调用)// 2. timer			: 负责定时器(高精度定时器和低精度定时器)
  • tick device 的类型
每一个cpu 有一个 tick device (clock event device) // SMP下 ,多个cpu对应的 tick device 中有一个被选择做global tick device,该device负责维护整个系统的jiffies以及更新哪些基于jiffies进行的全系统统计信息。tick device 根据 类型 分为两种	periodic tick device		可以按照固定的时间间隔产生tick event		event handler是 tick_handle_periodic (没有配置高精度timer)或 hrtimer_interrupt(配置了高精度timer)	one-shot tick device		设定后只能产生一次tick event,如果要连续产生tick event,那么需要每次都进行设定		event handler是 tick_nohz_handler(没有配置高精度timer)或 hrtimer_interrupt(配置了高精度timer)
  • tick device 的实例
linux-5.11 ok6410a 采用 了 	时间子系统2.0	无高精度timer	非idle,	  周期性tick idle,    周期性tick : CONFIG_HZ_PERIODIC
每当底层有新的 clockevent device 加入到系统中的时候	1.会调用 clockevents_register_device 或者clockevents_config_and_register 向通用clockevent layer注册一个新的clockevent设备	2.会调用 tick_check_new_device 通知 tick device layer有新货到来。	3.如果tick device和clockevent device你情我愿,那么就会调用tick_setup_device函数setup这个tick device了。		a.一般而言,刚系统初始化的时候,所有cpu的tick device都没有匹配clock event device		b.因此,该cpu的local tick device也就是global tick device了。		c.而且,如果tick device是新婚(匹配之前,tick device的clock event device等于NULL),那么tick device的模式将被设定为 TICKDEV_MODE_PERIODIC ,即便clock event有one shot能力,即便系统配置了NO HZ。	4. 对应 TICKDEV_MODE_PERIODIC , setup函数 是 tick_setup_periodic // tick_setup_periodic 函数用来设定一个periodic tick device。	5. setup第一部分:设定 event handler 为 tick_handle_periodic // 对于周期性tick device,其clock event device的handler被设定为 tick_handle_periodic。	6. setup第二部分:调用 clockevent device layer 的接口函数 kick off底层的硬件,让其周期性的产生clock event,
time_init	machine_desc->init_time/s3c64xx_timer_init		samsung_pwm_clocksource_init(S3C_VA_TIMER, timer_irqs, &s3c64xx_pwm_variant);			pwm.base = base;			...			pwm.timerclk = clk_get(NULL, "timers");			_samsung_pwm_clocksource_init				samsung_timer_resources				samsung_clockevent_init					clockevents_config_and_register						clockevents_register_device							tick_check_new_device								tick_setup_device									void (*handler)(struct clock_event_device *) = NULL;									tick_setup_periodic(newdev, 0);										tick_set_periodic_handler											dev->event_handler = tick_handle_periodic;											clockevents_program_event									tick_setup_oneshot(newdev, handler, next_event);					request_irq(irq_number, samsung_clock_event_isr, IRQF_TIMER | IRQF_IRQPOLL, "samsung_time_irq", &time_event_device)				samsung_clocksource_init					sched_clock_register
  • 什么时候开始有tick?
time_init		boot cpu ,在其初始化过程中会调用 time_init		这里会启动clocksource的初始化过程。这时候,周期性的tick就会开始了。	smp_init		其他的processor会启动,然后会注册其自己的local timer,这样,各个cpu上的tick就都启动了。

tick 的发生

// tick 发生时,走的是中断// 这里面主要设置的 是 need_resched irq_usr	...		...			samsung_clock_event_isr				evt->event_handler/tick_handle_periodic					tick_periodic(cpu);						update_process_times // 根据task_struct 里面时间片相关的成员  做 set_tsk_need_resched							scheduler_tick								sched_clock_tick								curr->sched_class->task_tick(rq, curr, 0);					if (!clockevent_state_oneshot(dev)) return;					next = ktime_add_ns(next, TICK_NSEC);

tick 与 schedule

调用 调度 的 途径有很多	1. 直接调用		进程主动放弃cpu执行调度	2. 系统调用(通过检查 need_resched )		中断返回		系统调用返回用户空间		信号处理完成后返回内核空间设置 need_resched 的途径还有很多// tick 是 设置 need_resched 的 一个途径	1.	2.

tick 时的 schedule

返回用户空间时调度	need_reschedtick 属于 第一种__irq_usr	irq_handler	b   ret_to_user_from_irq				// 从任务的TI_FLAGS标志判断是否需要处理抢占或者信号		ldr r1, [tsk, #TI_FLAGS]		movs    r1, r1, lsl #16		// 处理抢占或者信号		bne slow_work_pending			mov r0, sp              @ 'regs'			mov r2, why             @ 'syscall'			bl  do_work_pending				// 该函数内会调用 schedule				// 此时 表示 没有抢占或者信号要处理		// 或者 抢占或者信号 已经处理完毕		no_work_pending:		...		restore_user_regs fast = 0, offset = 0__irq_svc	irq_handler	#ifdef CONFIG_PREEMPTION	blne    svc_preempt		bl  preempt_schedule_irq			__schedule	#endif	svc_exit r5, irq = 1

转载地址:http://knigi.baihongyu.com/

你可能感兴趣的文章
朴素贝叶斯分类器
查看>>
贝叶斯学习举例--学习分类文本
查看>>
hadoop HDFS原理基础知识
查看>>
数据挖掘十大算法----EM算法(最大期望算法)
查看>>
android StrictMode应用
查看>>
TabHost的两种使用方法
查看>>
Android---TextView属性详解
查看>>
K近邻算法基础:KD树的操作
查看>>
数据挖掘十大算法--K近邻算法
查看>>
android对话框(Dialog)的用法
查看>>
Android使用Application总结
查看>>
android启动第一个界面时即闪屏的核心代码(两种方式)
查看>>
数据挖掘十大经典算法(详解)
查看>>
数据挖掘十大算法--K-均值聚类算法
查看>>
java中常用的日期格式化(全)
查看>>
POI操作Excel导入和导出
查看>>
java的md5加密算法代码
查看>>
jdbc连接数据库
查看>>
Android开发四大组件概述
查看>>
Hadoop主要子项目介绍(Pig Zookeeper Hbase Hive Sqoop Avro Chukwa Cassandra )
查看>>