定时器及时钟服务

Ch5 定时器及时钟服务

代码链接:https://gitee.com/xin_yu_liu/unix-linux-code

本章概要:

  • 定时器和定时器服务
  • 硬件定时器的原理
  • CPU操作和中断处理
  • Linux中与定时器相关的系统调用、库 函数和定时器服务命令
  • 进程冋隔定时器、定时器生成的信号

5.1 硬件定时器

定时器是由时钟源和可编程计数器组成的硬件设备。

  • 时钟源通常是一个晶体振荡 器,会产生周期性电信号,以精确的频率驱动计数器

5.2 个人计算机定时器

5.3 CPU操作

中断处理和异常处理都在操作系统内核中进行。在大多数情况下,用户级程序无法访问它们,但它们是 理解操作系统(如Linux)定时器服务和信号的关键。

5.4 中断处理

  • 外部设备(如定时器)的中断被馈送到中断控制器的预定义输入行(Intel 1990 ; Wang 2015),按优先级对中断输入排序,并将具有最高优先级的中断作为中断请求(IRQ)路由 到CPU。

  • 在每条指令执行结束时,如果CPU未处于接受中断的状态,即在CPU的状态寄 存器中屏蔽了中断.它将忽略中断请求.使其处于挂起状态,并继续执行下-条指令。

  • 如果 CPU处于接受中断状态,即中断未被屏蔽.那么CPU将会转移它正常的执行顺序来进行中 断处理对于每个中断,可以编程中断控制器以生成一个唯一编号,叫作中断向量,标识中 断源。在获取中断向量号后,CPU用它作为内存中中断向量表(AMD64 2011 )中的条目索 引,条目包含一个指向中断处理程序入口地址的指针来实际处理中断。

  • 当中断处理结束时, CPU恢复指令的正常执行

5.5 时钟服务函数

在几乎所有的操作系统(os)中,操作系统内核都会提供与时钟相关的各种服务,时钟 服务可通过系统调用、库函数和用户级命令调用。

  1. 通过gettimeofday()获取系统时间

    /********* gettimeofday.c £ile***/
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/time.h>
    stiruct timeval t;
    int main()
    {
    gettimeofday(&tff NULL);
    printf("sec=%ld usec=%d\n", t.tv_sec, t.tv_usec);
    printf((char *)ctime(&t.tv_sec));
    )
    
    
  2. 通过settimeofday()设置系统时间。

    /********* settimeofday.c file***/
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/time.h>
    #include <time.h>
    struct timeval t;
    int main()
    int r;
    t.tv_sec = 123456789;
    t.tv_usec= 0;
    r = set t: imeof day (&t, NULL);
    if (!r){
    printf (''settimeofday () failed\nz,);
    exit(1);
    }
    gettimeofday(&t, NULL);
    printf("sec=%ld usec=%ld\n"z t.tv_sec, t.tv_usec);
    printf	ctime (&t.tv_sec)) ; // show time in calendar form
    }
    
    
  3. time系统调用。

    /************ time.c file ***********/
    #include <stdio.h>
    #include <time.h>
    time_t start, end;
    int main()
    (
    int i;
    start = time(NULL);
    printf (''start=%ld\nw , start);
    for (i=0; i<123456789; i++); // delay to simulate computation
    end = time (NULL);
    printf (''end =%ld time=%ld\nw , end, end-start);
    
    
  4. time 和 date 命令

    • date:打印或设置系统日期和时间。
    • time:报告进程在用户模式和系统模式下的执行时间和总时间。
    • hwclock:查询并设置硬件时钟(RTC),也可以通过BIOS来完成。

5.6 时间间隔器

Linux为每个进程提供了三种不同类型的间隔计时器,可用作进程计时的虚拟时钟。

间隔定时器由setitimer()系统调用创建。

getitimer()系统调用返回间隔定时器的状态。

int getitimer(int which, struct itimerval *curr_value);
int setitimer(int which, const struct itimeirval *new_value,
struct itimerval *old_value);
/*********** setitimer.c file *********/
#include <signal.h>
#include <Btdia.h>
#include <sys/time.h>
int count = 0;
struct it interval t;
void tizner_handler(int sig) 
printf("timer_handler: signal=%d count=%d\n", sig, ++count); if (count>=8)(
printf(■cancel timer\n");
t.it_value.tv_sec = 0;
t.it_value.tv_usec = 0;
setitimer(ITIMER_VIRTUAL, &t, NULL);
int main()
(
struct itimerval timer;
// Install timer_handler as SIGVTALRM signal handler signal(SIGVTALRM, timer_handler);
// Configure the timer to expire after 100 msec
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 100000; // 100000 nsec
// and every 1 sec afterward
timer.it_interval.tv_sec = 1;
timer.it_interval.tv_usec = 0;
// Start a VIRTUAL itimer
setitimer(ITIMER_VIRTUALr	NULL);
printf("looping: enter Control-C to terminate\n"); while(1);

5.7 REAL模式间隔定时器

VIRTUAL和PROF模式下的间隔计时器仅在执行进程时才有效。

  • REAL模式冋隔定时器各不相同,因为无论进程是否正在执行,它们都必须由定时器中断处理程序来更新一因此,操作系统内核必须使用额外的数 据结构来处理进程的REAL模式定时器,并在定时器到期或被取消时采取措施。

5.8 编程项目

posted @ 2021-11-07 20:37  PuTa0  阅读(49)  评论(0编辑  收藏  举报