注:本分类下文章大多整理自《深入分析linux内核源代码》一书,另有参考其他一些资料如《linux内核完全剖析》、《linux c 编程一站式学习》等,只是为了更好地理清系统编程和网络编程中的一些概念性问题,并没有深入地阅读分析源码,我也是草草翻过这本书,请有兴趣的朋友自己参考相关资料。此书出版较早,分析的版本为2.4.16,故出现的一些概念可能跟最新版本内核不同。
此书已经开源,阅读地址 http://www.kerneltravel.net
一、时间系统
大部分PC 机中有两个时钟源,他们分别叫做RTC 和OS(操作系统)时钟。RTC(Real Time
Clock,实时时钟)也叫做CMOS 时钟,它是PC 主机板上的一块芯片(或者叫做时钟电路),
它靠电池供电,即使系统断电,也可以维持日期和时间。由于它独立于操作系统,所以也被
称为硬件时钟,它为整个计算机提供一个计时标准,是最原始最底层的时钟数据。
OS 时钟产生于PC 主板上的定时/计数芯片(8253/8254),由操作系统控制这个芯片的工作,OS 时钟
的基本单位就是该芯片的
计数周期
。在开机时操作系统取得RTC 中的时间数据来初始化OS
时钟,然后通过计数芯片的向下计数形成了OS 时钟,所以OS 时钟并不是本质意义上的时钟,
它更应该被称为一个计数器。OS 时钟只在开机时才有效,而且完全由操作系统控制,所以也
被称为软时钟或系统时钟。
Linux 的OS 时钟的物理产生原因是可编程定时/计数器产生的输出脉冲,
这个脉冲送入CPU,就可以引发一个中断请求信号,我们就把它叫做
时钟中断
。
Linux 中用全局变量
jiffies
表示系统自启动以来的时钟滴答数目。
每个时钟滴答,时钟中断得到执行。时钟中断执行的频率很高:100 次/秒(
Linux 设计者将一个“时钟滴答”定义为10ms
)
,时钟中断的
主要工作是处理和时间有关的所有信息、决定是否执行调度程序。和时间
有关的所有信息包括系统时间、进程的时间片、延时、使用CPU 的时间、各种定时器,进程
更新后的时间片为进程调度提供依据,然后
在时钟中断返回时决定是否要执行调度程序
。
每个时钟中断(timer interrupt)发生时,由3 个函数协同工作,共同完成进程的选
择和切换,它们是:schedule()、do_timer()及ret_form_sys_call()。我们先来解释一下
这3 个函数。
• schedule():进程调度函数,由它来完成进程的选择(调度)。
• do_timer():暂且称之为时钟函数,该函数在时钟中断服务程序中被调用,是时钟中
断服务程序的主要组成部分,该函数被调用的频率就是时钟中断的频率即每秒钟100 次(简
称100 赫兹或100Hz);
由这个函数完成系统时间的更新、进程时间片的更新等工作,更新后的进程时
间片counter 作为调度的主要依据。
• ret_from_sys_call():系统调用、异常及中断返回函数。当一个系统调用或中断完成时,该函数
被调用,用于处理一些收尾工作,例如信号处理、核心任务等。函数
检测
need_resched
标志,如果此标志为非0,那么就
调用调度程序schedule()进行进程的选择。调度程序schedule()会根据具体
的标准在运行队列中选择下一个应该运行的进程。当从调度程序返回时,如果发现又有调度
标志被设置,则又调用调度程序,直到调度标志为0,这时,从调度程序返回时由RESTORE_ALL
恢复被选定进程的环境,返回到被选定进程的用户空间,使之得到运行。
个人脚注:OS不是一直运行着的代码,而是一堆躺在内存里等着被调用的代码,中断处理在内核态,内核就是一个由 interrupt 驱动的程序。
可以是一个系统调用,x86 下很多OS的系统调用是靠 software interrupt 实现的,比如int 0x80,进入内核后就调用特定的内核函数执行。
也可以是一个用户程序产生的异常。比如执行cpu 指令违法,segment fault 什么的,操作系统一般会发送信号到进程,终止进程。
也可以是一个硬件产生的事件中断。比如由IO设备引起的可屏蔽中断,操作系统会调用特定的设备驱动程序进行服务。
一个用户程序运行的时候,Linux 进程就在内存里呆着,等着一个中断的到来。