首页 | Linux 基础 | 资讯动态 | Linux 应用 | Linux 服务器 | Linux 开发 | Linux 安全 | 专题 | 联盟论坛
  当前位置:主页>Linux 开发>linux 内核>文章内容
深入学习LINUX内核之七(图文讲解)
来源:http://www.unix5.com 作者:riechelr_hl 发布时间:2008-04-15  

为了让作业系统能自动地準确提供当前时间和日期资讯,PC/AT微机系统中提供了用电池供电的真实时钟RT(Real Time)电路支援。通常这部分电路与保存系统资讯的少量CMOS RAM集成在一个晶片上,因此这部分电路被称为RT/CMOS RAM电路。PC/AT微机或其相容机中使用了Motorola公司的MC146818晶片。

有初始化时,Linux 0.12內核透过init/main.c程式中的time_init( )函数读取这块晶片中保存的当前时间和日期资讯,并透过kernel/mktime.c程式中的kernel mktime( )函数转換成从1970年1月1日午夜0时开始计起到当前的以秒为单位的时间,我们称之为UNIX 日历时间。该时间确定了系统开始执行的日历时间,被保存在全域变数startup_time中供内核所有代码使用。用戶程式可以使用系统呼叫stime( )来读取startup_time的值,而超级用戶则可以透过系统呼叫stime()来修改这个系统时间值。


另外,再透过下面介绍的从系统啟动开始计数的系统滴答值jiffies,程式就可以唯一地确定执行时刻的当前时间值。由于每个滴答定时值是10毫秒,因此內核代码中定义了一个巨集来方便代码对当前时间的存取。这个巨集定义在include/linux/sched.h档第192行上,其形主 下:

# define CURRENT_TIME(startup_time + jiffiles/HZ)

其中,HZ = 100,是內核系统时钟频率。当前时间巨集CURRENT_TIME被定义为系统开机时间startup_time加上开机系统执行的时间jiffies/100 。在修改一个档被存取时间或其i节点被修改时间均使用了这个巨集。


5.6.2 系统定时

在Linux 0.12內核的初始化过程中,PC 机的可程式化定时晶片Intel 8253(8254)的计数器通道0被设置成执行在方式3下(方波发生器方式),並且初始计数值LATCH被设置成每隔10毫秒在通道0输出端OUT发出一个方波上升沿。由于8254晶片的时钟输入频率为1.193180MHz,因此初始计数值LATCH=1193180/100,約为11931。由於OUT接腳被连接到可程式化控制晶片的0级上,因此系统每隔10毫秒就会发出一个时钟中断请求(IRQ0)信号。这个时间节拍就是作业系统执行的脈搏,我们称之为l个系统滴答或一个系统时钟週期。因此每经过1个滴答时问,系统就会呼叫一次时钟中断处理程式(timer_interrupt)。

时钟中断处理程式timer_interrupt主要用来透过jiffies变数来累计自系统啟动以来经过的时钟滴答数。每当发生一次时钟中断jiflies值就增加1。然后呼叫C语言函数do_timer( )作进一步的处理。呼叫时所带的参数CPL是从被中断程式的段选择符(保存在堆栈中的CS段寄存器值)中取得当前代码特权级CPL。

do_timer( )函数则根据特权级对当前行程执行时间作累计。如果CPL=0,则表示行程执行在內核态时被中断,因此內核就会把行程的內核态执行时间统计值stime增1,否则把行程用戶态执行时间统计值增1。如果软碟处理程式floppy.c在操作过程中添加过计时器,则对计时器链表进行处理。若某个计时器时间到(递減后等於0),则呼叫该计时器的处理函数。然后对当前行程执行时间进行处理,把当前行程执行时间片減1。时间片是一个行程在被切換掉之前所能持续执行的CPU时间,其单位是上面定义的滴答数。如果行程时间片值递減后还大於0,表示其时间片还沒有用完,于是就退出do_timer( )继续执行当前行程。如果此时行程时间片已经递減为0,表示该行程已经用完了此次使用CPU的时间片,於是程式就会根据被中断程式的级別来确定进一步处理的方法。若被中断的当前行程是工作在用户态的(特权级別大於0),则do_timer()会呼叫调度程式schedule( )切換到其饱行程去执行。如果被中断的当前行程工作在內核态,也即在內核程式中执行时被中断,则do_timer( )会立刻退出。因此这樣的处理方式決定了Linux系统的行程在內核态执行时不会被调度程式切換。即行程在內核态程式中执行时是不可抢占的(nonpreemptive) ¹,但当处於用户程式中执行时则是可以被抢佔的(preemptive)。

¹从Linux2.4内核起,Robert Love开发出了可抢占式的内核升级套件。这使得在内核空间低优先顺序的行程也能被高优先顺序行程抢占,从而能使系统回应效能最大提高200%。参见Robert Love编著的《Linux内核开发》一书。

注意 上述计时器专门用於软碟马达开啟和关闭定时操作。这种计时器类似现代Linux系统中的动态计时器(Dynamic Timer),仅供內核使用。这种计时器可以在非要时动态地建立,而在定时到期时动态地撤销。在Linux 0.12內核中计时器同时最多可以有64个。计时器的处理代码在sched.c程式283- -368行。


5.7 Linux行程控制

程式是一个可执行的档案,而行程(process)是一个执行中的程式实例。利用分时技术,在Linux作业系统上同时可以执行多个行程。分时技术的基本原理是把CPU的执行时间划分成一个个规定长度的时间片(time slice),让每个行程在一个时间片內执行。当行程的时间片用完时系统就利用调度程式切換到另一个行程去执行。因此实际上对於具有单个CPU的机器来說某一时刻只能执行一个行程。但由於每个行程执行的时间片很短(例如15个系统滴答=150毫秒) ,所以表面看来好象所有行程在同时执行著。

对於Linux 0.12內核来讲,系统最多可有64个行程同时存在,除了第一个行程用“手工”建立以外,其余的都是现有行程使用系统呼叫fork建立的新行程,被建立的行程称为子行程(child process),建立者,则称为父行程(parent process)。內核程式使用行程标识号(process ID,pid)来标识每个行程。行程由可执行的指令代码、资料和堆栈区。行程中的代码和资料部分分別对应一个执行档中的代码段、资料段。每个行程只能执行自己的代码和存取自己的资料及堆栈区。行程之间的通信需要透过系统呼叫来进行。对於只有一个CPU的系统,在某一时刻只能有一个行程正在执行。內核透过调度程式分时调度各个行程执行。

我们已经知道,Linux系统中一个行程可以在內核态(kernel mode)或用户态(user mode)下执行,並且分別使用各自独立的內核态堆栈和用戶态堆栈。用戶堆疊用於行程在用戶态下临时保存 呼叫函数的参数、区域变数等资料;內核堆栈则含有內核程式执行函数呼叫时的信息。

另外在Linux內核中,行程通常被称作任务(task) ,而把执行在用戶空间的程式称作行程。本文将在尽量遵守这个预设规则的同时混用这两个术语。
共12页: 上一页 [1] 2 [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] 下一页
 
如果您对本文有任何疑问或者建议,请到论坛讨论区发表您的意见: >> 论坛入口
[收藏] [推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
  热点文章
·使用 Linux 系统调用的内核命令
·Linux 2.6.11内核文件IO系统调用
·Linux操作系统的源代码目录树结
·Linux用户态与内核态的交互讲解
·Linux内核对I/O端口的管理实现(
·深入分析 Linux操作系统的内核链
·Linux内核可装载模块对设备驱动
·概述Linux系统的驱动框架及驱动
·详解Linux 2.6内核新文件系统变
·Linux系统可卸载内核模块完全指
·FreeBSD手册讲解(一)--配置FreeB
·编译Linux操作系统的内核讲解
  相关文章
·深入学习LINUX内核之六(图文讲解
·深入学习LINUX内核之五(图文讲解
·深入学习LINUX内核之四(图文讲解
·Linux系统内核漏洞分析
·深入学习LINUX内核之三(图文讲解
·如何在Linux内核中的实现SYN Coo
·深入学习LINUX内核之二(图文讲解
·简析Linux与FreeBSD的syscall
·深入学习Linux内核文档一(图文讲
·Linux操作系统“警惕”内核汉化
·Linux操作系统核心的汉字显示机
·如何利用异常表处理Linux内核态

本站信息源至:互联网络,均为学习,交流所用,如有版权问题,请联系我们.
站长QQ:397422079 E_mail:riechelr_hl@unix5.com
转载本站内容请注明原作者名.谢谢!