Linux内核学习日记补充1:时钟中断

参考资料

  • 《Linux内核完全注释》
  • linux 0.11源码
  • B站视频
  • CSDN博客
    !!以下图片来自《Linux内核完全注释 修正版V3.0》!!

硬件时钟

'''
一般PC机都会有以下两个时钟:
一:RTC实时时钟(又称CMOS时钟)
二:OS时钟,产生于PC主板上的定时/计数芯片(又称软时钟、系统时钟)————重点要了解的是这个
'''
  • 典型的定时/计数芯片:8253、8254,它们可编程

时钟中断

Linux初始化过程包括了对OS时钟的初始化,使OS时钟成为整个OS工作的心脏。
(8253芯片)OS时钟会每10ms产生一个中断信号,由IRQ接收处理后传递于CPU,触发相应的中断服务。
(也即是10ms为一个时间片,每过一个时间片对进程持有的时间片数进行一次检查调整)

  • 时钟中断C函数处理程序do_timer(),位于sched.c文件,在system_call.s中被调用。
  • do_timer()主要判断当前进程时间片是否用完,并根据不同情况做出相应的处理。
struct task_struct {//该结构体定义在sched.h中,以下只是部分代码
/* these are hardcoded - don't touch */
	long state;	//程序运行的状态/* -1 unrunnable, 0 runnable, >0 stopped */
	long counter; //时间片
	//counter的计算不是单纯的累加,需要下面这个优先级这个参数参与
	long priority;//优先级
	......
	long utime,stime,cutime,cstime,start_time;//运行时间
	//utime是用户态运行时间 cutime是内核态运行时间
	......
};
void do_timer(long cpl)
{
	/*!!!!为了方便说明,我省略了部分代码!!!!*/
	/***
	*current为进程指针
	* %eax is CPL (0 or 3, 0=supervisor)
	*cpl为特权级.cpl=0为最高级,表示内核态;cpl>0表示用户态.
	***/
	if (cpl)
		current->utime++;//给用户程序运行时间+1
	else
		current->stime++;//内核程序运行时间+1
	/*定时器处理*/
	if (next_timer) {// next_timer 是连接jiffies变量的所有定时器的事件链表
	// 可以这样想象,jiffies是一个时间轴,然后这个时间轴上每个绳结上绑了一个事件,运行到该绳结就触发对应的事件
		next_timer->jiffies--;
		while (next_timer && next_timer->jiffies <= 0) {
			void (*fn)(void);//插入一个函数指针
			
			fn = next_timer->fn;
			next_timer->fn = NULL;
			next_timer = next_timer->next;
			(fn)();//调用处理函数
		}
	}
	/*时间片检测*/
	if ((--current->counter)>0) return;//如果进程时间片还没用完,则退出
	current->counter=0;//否则,重置进程时间片为0
	if (!cpl) return;//如果时间片用完且在内核态下运行,则直接退出
	schedule();//如果时间片用完且在用户态下,执行调度函数(分配时间片,执行另一个进程)
}
  • 在system_call.s中_timer_interrupt时钟中断处理中,执行完do_timer()后,会跳转到ret_from_sys_call对信号进行处理。
  • 在ret_from_sys_call中,首先会检测当前任务,如果是任务0(内核态),则不作信号量方面的处理,直接返回,退出中断;如果是非任务0(用户态),则对任务进行信号量的识别处理。
    信号处理程序调用方式
    图1 P303
  • do_signal()是信号量识别处理的主要操作,定义在signal.c中。
  • do_signal()把信号对应的处理函数插入到内核堆栈eip处,并修改用户堆栈,使其中断返回后(用户进程)执行信号处理函数。
    do_signal()具体过程
    图片2 P304
//发送信号的函数,这些参数全部都是寄存器的名字
//进程间通信,无非是A进程传递一些信息给当前的进程
//这个信号传递函数是触发中断,然后接管当前进程的堆栈寄存器等句柄
//再然后可以往里面写入一些东西,其实就是传递了信息给当前运行的进程
void do_signal(long signr,long eax, long ebx, long ecx, long edx,
	long fs, long es, long ds,
	long eip, long cs, long eflags,
	unsigned long * esp, long ss)
{
	......
}
  • 信号处理函数返回后执行一个sa_restorer,恢复用户堆栈为正常中断退出之后的状态。
  • 因为时钟中断、系统调用以及最频繁调用的schedule()里面都会处理信号,所以信号总能及时地得到"触发"。

————————————————————————————————————————————

结束
👍👍👍👍👍👍👍👍
继续加油!! 👍👍👍
👍👍👍👍👍👍👍👍

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值