《Unix&Linux系统编程》第五章学习笔记

第5章 定时器及时钟服务

5.1 硬件定时器

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

  • 时钟源:晶体振荡器,会产生周期性电信号。使用倒计时值对计数器进行编程,每个时钟信号间1,当计数减为0时,计数器向CPU生成一个定时器中断
  • 计数器周期称为定时器刻度,是系统的基本计时单元。

5.2 个人计算机定时器

  • 实时时钟(RTC):个人计算机关机时,也能连续运行,用于试试提供时间和日期信息。
  • 可编程间隔定时器(PIT):是与CPU分离的硬件定时器,可编程,提供以毫秒位单位的定时器刻度。
  • 多核CPU中的本地定时器:多核CPU的每个核都有自己的本地计时器,由CPU时钟驱动。
  • 高分辨率定时器:时间戳定时器(TSC)由系统时钟驱动,可提供纳秒级的定时器分辨率。

5.3 CPU操作

每个CPU都有一个程序计数器(PC),也称为指令指针(IP),以及一个标志或状态寄存器(SR)、一个堆栈指针(SP)和几个通用寄存器。

PC-->下一条要执行的命令
SR-->CPU当前状态(操作模式、中断掩码、条件码)
SP-->堆栈栈顶

  • 异常(陷阱):无效地址、非法指令、越权等原因。
  • 中断:I/O设备或协处理器方的状态。

5.4 中断处理

  • 外部设备(如定时器)的中断被馈送到中断控制器的预定义输入行,按优先级对中断输入排序,并将具有最高优先级的中的作为中断请求(IRQ)路由到CPU。
  • 对于每个中断,可以编程中断控制器以生成一个唯一编号——中断向量

5.5 时钟服务函数

时钟服务可通过系统调用、库函数和用户级命令调用。

(1)gettimeofday-settimeofday

gettimeofday系统调用:

在Unix/Linux系统中,时间表示自1970年1月1日00:00:00起经过的秒数,可通过库函数ctime(&time)转换为日历形式。

代码:
#include <stdio.h>
#include <stdlib. h>
#include <sys/time. h>
#include <time.h>

struct timeval t;

int main()
{
    gettimeofday(&t, NULL) ;
    printf("sec=%ld usec=%d\n", t.tv_ sec, t.tv_ usec) ;
    printf((char *)ctime(&t.tv_sec)) ;
}
实践截图:


程序以秒、微秒显示当前时间,并以日历形式显示当前日期和时间。

settimeofday系统调用

代码:
#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 = settimeofday(&t, NULL);
    if(!r){
        printf("settimeofday() failed\n");
        exit (1) ;
    }
    gettimeofday(&t, NULL) ;
    printf("sec=%ld usec=%ld\n", t.tv_sec, t.tv_usec);
    printf("%s", ctime(&t.tv_sec));  //show time in calendar form
}

实践截图:

(2)time系统调用

代码:
#include <stdio.h>
#include <time.h>

time_t start, end;

int main()
{
    int i;
    start = time (NULL) ;
    printf ("start=%ld\n", start) ;
    for (i=0; i<123456789; i++) ; // delay to simulate computation
    end = time (NULL) ;
    printf ("end=%ld time=%ld\n", end, end-start) ;
}
实践截图:


输出打印开始时间、结束时间以及从开始到结束的秒数。

(3)times系统调用

可用于获取某进程的具体执行时间。

(4)time和date命令

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

5.6 间隔定时器

  • 代码:
#include <signal.h>
#include <stdio.h>
#include <sys/time.h>
int count = 0;
struct itimerval t;

void timer_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 i timer
    setitimer(ITIMER_VIRTUAL, &timer, NULL) ;
    printf("looping: enter Control-C to terminate\n");
    while(1);
}

  • 实践截图:

5.7 REAL模式间隔定时器

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

posted @ 2022-10-22 11:47  少管我  阅读(36)  评论(0编辑  收藏  举报