iis服务器助手广告
返回顶部
首页 > 资讯 > 操作系统 >Linux中时钟中断的方法
  • 592
分享到

Linux中时钟中断的方法

2023-06-09 14:06:11 592人浏览 独家记忆
摘要

这篇文章将为大家详细讲解有关linux中时钟中断的方法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。在Linux的0号中断是一个定时器中断。在固定的时间间隔都发生一次中断,也是说每秒发生该中断的频率都是固

这篇文章将为大家详细讲解有关linux中时钟中断的方法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

在Linux的0号中断是一个定时器中断。在固定的时间间隔都发生一次中断,也是说每秒发生该中断的频率都是固定的。该频率是常量HZ,该值一般是在100 ~ 1000之间。该中断的作用是为了定时更新系统日期和时间,使系统时间不断地得到跳转。另外该中断的中断处理函数除了更新系统时间外,还需要更新本地CPU统计数。指的是调用scheduler_tick递减进程的时间片,若进程的时间片递减到0,进程则被调度出去而放弃CPU使用权。

时钟中断的产生

Linux的OS时钟的物理产生原因是可编程定时/计数器产生的输出脉冲,这个脉冲送入CPU,就可以引发一个中断请求信号,我们就把它叫做时钟中断。

“时钟中断”是特别重要的一个中断,因为整个操作系统的活动都受到它的激励。系统利用时钟中断维持系统时间、促使环境的切换,以保证所有进程共享CPU;利用时钟中断进行记帐、监督系统工作以及确定未来的调度优先级等工作。可以说,“时钟中断”是整个操作系统的脉搏。

时钟中断的物理产生如图所示:

Linux中时钟中断的方法

操作系统对可编程定时/计数器进行有关初始化,然后定时/计数器就对输入脉冲进行计数(分频),产生的三个输出脉冲Out0、Out1、Out2各有用途,很多接口书都介绍了这个问题,我们只看Out0上的输出脉冲,这个脉冲信号接到中断控制器8259A_1的0号管脚,触发一个周期性的中断,我们就把这个中断叫做时钟中断,时钟中断的周期,也就是脉冲信号的周期,我们叫做“滴答”或“时标”(tick)。从本质上说,时钟中断只是一个周期性的信号,完全是硬件行为,该信号触发CPU去执行一个中断服务程序,但是为了方便,我们就把这个服务程序叫做时钟中断。

Linux实现时钟中断的全过程

1.可编程定时/计数器的初始化

IBM PC中使用的是8253或8254芯片。有关该芯片的详细知识我们不再详述,只大体介绍以下它的组成和作用,如下表5.1所示:

表 8253/8254的组成及作用

名称

端口地址

工作方式

产生的输出脉冲的用途

计数器0

0x40

方式3

时钟中断,也叫系统时钟

计数器1

0x41

方式2

动态存储器刷新

计数器2

0x42

方式3

扬声器发声

控制寄存器

0x43

/

用于8253的初始化,接收控制字

计数器0的输出就是图中的Out0,它的频率由操作系统的设计者确定,Linux对8253的初始化程序段如下(在/arch/i386/kernel/i8259.c的init_IRQ()函数中):

set_intr_gate(ox20, interrupt[0]);  /*在IDT的第0x20个表项中插入一个中断门。这个门中的段选择符设置成内核代码段的选择符,偏移域设置成0号中断处理程序的入口地址。*/  outb_p(0x34,0x43);    outb_p(LATCH & 0xff , 0x40);   outb(LATCH >> 8 , 0x40);   LATCH(英文意思为:存器,即其中锁存了计数器0的初值)为计数器0的计数初值,在/include/linux/timex.h中定义如下:  #define CLOCK_TICK_RATE 1193180   #define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) 

CLOCK_TICK_RATE是整个8253的输入脉冲,如图5.3中所示为1.193180MHz,是近似为1MHz的方波信号,8253内部的三个计数器都对这个时钟进行计数,进而产生不同的输出信号,用于不同的用途。

HZ表示计数器0的频率,也就是时钟中断或系统时钟的频率,在/include/asm/param.h中定义如下:

#define HZ 100

2.与时钟中断相关的函数

下面我们看时钟中断触发的服务程序,该程序代码比较复杂,分布在不同的源文件中,主要包括如下函数:

时钟中断程序:timer_interrupt( );

中断服务通用例程do_timer_interrupt();

时钟函数:do_timer( );

中断安装程序:setup_irq( );

中断返回函数:ret_from_intr( );

(1) timer_interrupt( )

这个函数大约每10ms被调用一次,实际上, timer_interrupt( )函数是一个封装例程,它真正做的事情并不多,但是,作为一个中断程序,它必须在关中断的情况下执行。如果只考虑单处理机的情况,该函数主要语句就是调用do_timer_interrupt()函数。

(2) do_timer_interrupt()

do_timer_interrupt()函数有两个主要任务,一个是调用do_timer( ),另一个是维持实时时钟(RTC,每隔一定时间段要回写),其实现代码在/arch/i386/kernel/time.c中, 为了突出主题,笔者对以下函数作了改写,以便于读者理解:

static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) {  do_timer(regs);   if(xtime.tv_sec > last_rtc_update + 660)  update_RTC();               }

其中,xtime是前面所提到的timeval类型,这是一个全局变量。

(3) 时钟函数do_timer() (在/kernel/sched.c中)

void do_timer(struct pt_regs * regs) {  (*(unsigned long *)&jiffies)++;   update_process_times();  ++lost_ticks;  if( ! user_mode ( regs ) )   ++lost_ticks_system;   mark_bh(TIMER_BH);     if (tq_timer)        mark_bh(TQUEUE_BH); }

其中,update_process_times()函数与进程调度有关,从函数的名子可以看出,它处理的是与当前进程与时间有关的变量,例如,要更新当前进程的时间片计数器counter,如果counter<=0,则要调用调度程序,要处理进程的所有定时器:实时、虚拟、概况,另外还要做一些统计工作。

与时间有关的事情很多,不能全都让这个函数去完成,这是因为这个函数是在关中断的情况下执行,必须处理完最重要的时间信息后退出,以处理其他事情。那么,与时间相关的其他信息谁去处理,何时处理?这就是由第三章讨论的后半部分去去处理。 上面timer_interrupt()(包括它所调用的函数)所做的事情就是上半部分。

在该函数中还有两个变量lost_ticks和lost_ticks_system,这是用来记录timer_bh()执行前时钟中断发生的次数。因为时钟中断发生的频率很高(每10ms一次),所以在timer_bh()执行之前,可能已经有时钟中断发生了,而timer_bh()要提供定时、记费等重要操作,所以为了保证时间计量的准确性,使用了这两个变量。lost_ticks用来记录timer_bh()执行前时钟中断发生的次数,如果时钟中断发生时当前进程运行于内核态,则lost_ticks_system用来记录timer_bh()执行前在内核态发生时钟中断的次数,这样可以对当前进程精确记费。

Linux中时钟中断的方法

(4)中断安装程序

从上面的介绍可以看出,时钟中断与进程调度密不可分,因此,一旦开始有时钟中断就可能要进行调度,在系统进行初始化时,所做的大量工作之一就是对时钟进行初始化,其函数time_init ()的代码在/arch/i386/kernel/time.c中,对其简写如下:

 void __init time_init(void)  { xtime.tv_sec=get_cmos_time(); xtime.tv_usec=0; setup_irq(0,&irq0); }

其中的get_cmos_time()函数就是把当时的实际时间从CMOS时钟芯片读入变量xtime中,时间精度为秒。而setup_irq(0,&irq0)就是时钟中断安装函数,那么irq0指的是什么呢,它是一个结构类型irqaction,其定义及初值如下:

static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};

setup_irq(0, &irq0)的代码在/arch/i386/kernel/irq.c中,其主要功能就是将中断程序连入相应的中断请求队列,以等待中断到来时相应的中断程序被执行。

struct irqaction {   irq_handler_t handler;  //中断处理函数,注册时提供    unsigned long flags;   //中断标志,注册时提供    cpumask_t mask;    //中断掩码    const char *name;   //中断名称   void *dev_id;      //设备id,本文后面部分介绍中断共享时会详细说明这个参数的作用   struct irqaction *next;  //如果有中断共享,则继续执行,    int irq;        //中断号,注册时提供   struct proc_dir_entry *dir; //指向IRQn相关的/proc/irq/n目录的描述符 };

这个结构体包含了处理一种中断所需要的各种信息,它代表了内核接受到特定IRQ之后应该采取的操作。

handler:该指针所指向的函数就是在中断服务程序,当中断发生时内核便会调用这个指针指向的函数。

flags:该标志位可以是0,也可以是:

SA_INTERRUPT:表示此中断处理程序是一个快速中断处理程序,在2.6中默认情况下没有这个标志;设置该标志位,中断处理程序禁止任何中断运行,没有该标志,仅屏蔽正在运行的IRQ线;

SA_SAMPLE_RANDOM:表示这个中断对内核池有贡献,在中断时产生一些随机数;

SA_SHIRQ:此标志位表示允许多个中断服务程序共享一个中断号,如不设则一个程序对应一个中断线;

mask:在x86上不会用到。

name:产生中断的硬件的名字.

dev_id:该标志位主要在共享中断号时使用,即你设置flags=SA_SHIRQ时,有多个中断服务程序共享一个中断号时,内核就需要知道在用完中断程序后该删除那个中断服务程序。不共享时此成员为null。

next:如果flags=SA_SHIRQ,那么这就是指向对列中下一个struct irqaction结构体的指针,否则为空。

irq:不用说这就是中断号了。

到现在为止,我们仅仅是把时钟中断程序挂入中断请求队列,什么时候执行,怎样执行,这是一个复杂的过程(参见第三章),为了让读者对时钟中断有一个完整的认识,我们忽略中间过程,而给出一个整体描述。我们将有关函数改写如下,体现时钟中断的大意:

do_timer_interrupt( )   /*这是一个伪函数 */ {             SAVE_ALL     /*保存处理机现场 */  intr_count += 1;    /* 这段操作不允许被中断 */  timer_interrupt()    /* 调用时钟中断程序 */  intr_count -= 1;     jmp ret_from_intr    /* 中断返回函数 */ }

其中,jmp ret_from_intr 是一段汇编代码,也是一个较为复杂的过程,它最终要调用jmp ret_from_sys_call,即系统调用返回函数,而这个函数与进程的调度又密切相关,,因此,我们重点分析 jmp ret_from_sys_call。

3.系统调用返回函数:

系统调用返回函数的源代码在/arch/i386/kernel/entry.S中

ENTRY(ret_from_sys_call)    cli     # need_resched and signals atomic test    cmpl $0,need_resched(%ebx)    jne reschedule    cmpl $0,sigpending(%ebx)    jne signal_return  restore_all:    RESTORE_ALL    ALIGN  signal_return:    sti    # we can get here from an interrupt handler    testl $(VM_MASK),EFLAGS(%esp)    movl %esp,%eax    jne v86_signal_return    xorl %edx,%edx    call SYMBOL_NAME(do_signal)    jmp restore_all    ALIGN   v86_signal_return:    call SYMBOL_NAME(save_v86_state)    movl %eax,%esp    xorl %edx,%edx    call SYMBOL_NAME(do_signal)    jmp restore_all  ….  reschedule:    call SYMBOL_NAME(schedule) # test   jmp ret_from_sys_call

这一段汇编代码就是前面我们所说的“从系统调用返回函数”ret_from_sys_call,它是从中断、异常及系统调用返回时的通用接口。这段代码主体就是ret_from_sys_call函数,其执行过程中要调用其它一些函数(实际上是一段代码,不是真正的函数),在此我们列出相关的几个函数:

(1)ret_from_sys_call:主体

(2)reschedule:检测是否需要重新调度

(3)signal_return:处理当前进程接收到的信号

(4)v86_signal_return:处理虚拟86模式下当前进程接收到的信号

(5)RESTORE_ALL:我们把这个函数叫做彻底返回函数,因为执行该函数之后,就返回到当前进程的地址空间中去了。

可以看到ret_from_sys_call的主要作用有:

检测调度标志need_resched,决定是否要执行调度程序;处理当前进程的信号;恢复当前进程的环境使之继续执行。

最后我们再次从总体上浏览一下时钟中断:

每个时钟滴答,时钟中断得到执行。时钟中断执行的频率很高:100次/秒,时钟中断的主要工作是处理和时间有关的所有信息、决定是否执行调度程序以及处理下半部分。和时间有关的所有信息包括系统时间、进程的时间片、延时、使用CPU的时间、各种定时器,进程更新后的时间片为进程调度提供依据,然后在时钟中断返回时决定是否要执行调度程序。下半部分处理程序是Linux提供的一种机制,它使一部分工作推迟执行。时钟中断要绝对保证维持系统时间的准确性,而下半部分这种机制的提供不但保证了这种准确性,还大幅提高了系统性能。

关于“Linux中时钟中断的方法”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

--结束END--

本文标题: Linux中时钟中断的方法

本文链接: https://www.lsjlt.com/news/256438.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Linux中时钟中断的方法
    这篇文章将为大家详细讲解有关Linux中时钟中断的方法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。在Linux的0号中断是一个定时器中断。在固定的时间间隔都发生一次中断,也是说每秒发生该中断的频率都是固...
    99+
    2023-06-09
  • C#绘制时钟的方法
    本文实例为大家分享了使用C#写一个时钟,供大家参考,具体内容如下 时钟是这样的 一共使用四个控件即可: WinFrom窗体应用程序代码: using SpeechLib; us...
    99+
    2024-04-02
  • 在Windows8中根据需要添加不同时区时钟的方法
      1、点击桌面右下角的时间,然后选择更改日期和时间设置;   2、点击附加时钟,然后勾选显示此时钟;   3、选择需要添加其他时区的位置; 之后,回桌面再次点击时间区域 ...
    99+
    2023-06-06
    Windows8 时区 时钟 方法
  • FreeRTOS软件定时器apollo中断状态判断的方法
    本篇内容主要讲解“FreeRTOS软件定时器apollo中断状态判断的方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“FreeRTOS软件定时器apollo中断状态判断的方法”吧!问题场景开发...
    99+
    2023-06-29
  • linux如何罗列实时中断
    ...
    99+
    2024-04-02
  • Linux时钟的示例分析
    这篇文章主要为大家展示了“Linux时钟的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Linux时钟的示例分析”这篇文章吧。Linux时钟分类 Windows时钟大家可能十分熟悉了,L...
    99+
    2023-06-16
  • JavaScript循环中断的方法
    今天小编给大家分享一下JavaScript循环中断的方法的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。break<sc...
    99+
    2023-06-27
  • Win7设置多个地区时钟的方法
    很多时候,咱们关注win7 64位旗舰版iso中的操作技巧和故障解决方法,但是却忽略了其中最为基本,最为简单的东西,在win7旗舰版中,其实有很多简单的小工具,可以帮助咱们让操作变得更加的简单,可以让咱们的操作变得更加的...
    99+
    2023-06-13
    Win7设置 多个地区时钟 方法 Win7 时钟 地区
  • 在Linux系统中的时间转化方法
    本篇内容介绍了“在Linux系统中的时间转化方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!  Linux时间转化方法:  (1)date...
    99+
    2023-06-13
  • Android怎么实现简单时钟View的方法
    这篇文章给大家分享的是有关Android怎么实现简单时钟View的方法的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。通过Canvas的平移与旋转简化绘图逻辑是一个非常有用的技巧,下面的时钟view就是利用这个方法...
    99+
    2023-05-30
    android view
  • linux中makefile检测到有时钟错误怎么解决
    在Linux中,如果在Makefile中检测到时钟错误,可以尝试以下解决方法:1. 更新系统: 确保系统中的所有软件包都是最新的,包...
    99+
    2023-09-22
    linux
  • 如何配置Linux的时钟同步
    这篇文章给大家分享的是有关如何配置Linux的时钟同步的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。安装一般timesync是预装的。如果没有,可以使用以下命令手动安装。sudo apt install syst...
    99+
    2023-06-28
  • Win8系统添加不同时区的时钟方法介绍
    在新版本的 Windows 8系统中,你其实是可以为系统添加最多到 3 个不同时区的时钟,可以方便不少有跨国联系的朋友,下面小编说说方法。  具体的方法是,点击托盘里的时间显示,然后点击「更改日期和时间设置」...
    99+
    2023-06-06
    Win8 时区 时钟 系统 添加
  • Linux 中实时查看日志的3种方法
    Linux 中实时查看日志的3种方法 最近我从cnaaa.com购买了云服务器。 我们大家应该都知道如何在 Linux 中查看文件,比如可以使用 cat 或者 less 命令。 这对于查看静态文件来说是可以的。日志文件是动态的,其内容随时会...
    99+
    2023-08-18
    linux 服务器 运维
  • Go 中中断 if 语句的简洁方法
    哈喽!大家好,很高兴又见面了,我是编程网的一名作者,今天由我给大家带来一篇《Go 中中断 if 语句的简洁方法》,本文主要会讲到等等知识点,希望大家一起学习进步,也欢迎大家关注、点赞、收藏、转发! ...
    99+
    2024-04-04
  • java中wait调用中断的解决方法
    这篇文章主要介绍java中wait调用中断的解决方法,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Java的优点是什么1. 简单,只需理解基本的概念,就可以编写适合于各种情况的应用程序;2. 面向对象;3. 分布性,...
    99+
    2023-06-14
  • Java中的线程中断方法怎么用
    本篇内容介绍了“Java中的线程中断方法怎么用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Java中的线程中断1 线程中断相关方法介绍Ja...
    99+
    2023-07-04
  • JAVA多线程之中断机制及处理中断的方法
    目录一,介绍二,中断及如何响应中断?一,介绍 这篇文章主要记录使用 interrupt() 方法中断线程,以及如何对InterruptedException进行处理。感觉对Inter...
    99+
    2023-02-13
    java多线程中断机制 java多线程中断
  • Python中利用pyqt5制作指针钟表显示实时时间(指针时钟)
    文末附完整源代码实现过程... 想实现这样一个功能,然后pyqt5中又没有现成的组件可以使用,于是就想着只能通过绘图的方式来实现。说到绘图的话,turtle框架无疑是最常见的选择,...
    99+
    2024-04-02
  • Python中unittest的断言方法详解
    目录断言方法:方法有: 下面是做的例子,后边是运行结果:总结断言方法:         是unitte...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作