第八次学习笔记

编程入门 行业动态 更新时间:2024-10-21 09:51:15

第八次<a href=https://www.elefans.com/category/jswz/34/1770117.html style=学习笔记"/>

第八次学习笔记

20211119陈俊积

一、知识点归纳和苏格拉底挑战

硬件定时器

定时器是由时钟源和可编 程计数器组成的硬件设备。时钟源 通常是一个晶体振荡器,会产生周期性电信号,以料青确的频率驱动计数器。使用一个倒计时值对计数器进行编程,每个时钟信号减1。当计 改减为0时,计数器向CPU生成一个定时器中断,将计数值重新加载到计数器中,并重复复倒计时。计数器周期称为定时器刻店度,是系统的基本计时单元。

个人计算机定时器

基于Intel x86的个人计算机有多个定时器:

实时时钟(RTC):

RTC由一个小型备用电池供电。即使在个人计算机关机时,它也能连续运行。它用于实时提供时间和日期信息。当Linux启动时,它使用RTC更新系统时间变量,以与当前时间保持一致。在所有类Unix系统中,时间变量是一个长整数,包含从1970年1月1日起经过的秒数。

可编程间隔定时器(PIT):

PIT是与CPU分离的一个硬件定时器。可对它进行编程,以提供以毫秒为单位的定时器刻度。在所有I/O设备中,PIT可以最高优先级IRQ0中断。PIT定时器中断由Linux内核的定时器中断处理程序来处理,为系统操作提供基本的定时单元,例如进程调度、进程间隔定时器和其他许多定时事件。

多核CPU中的本地定时器:

在多核CPU中,每个核都是一个独立的处理器,它有自己的本地定时器,由CPU时钟驱动。

高分辨率定时器:

大多数电脑都有一个时间戳定时器(TSC),由系统时钟驱动。它的内容可通过64位TSC寄存器读取。由于不同系统主板的时钟频率可能不同,TSC不适合作为实时设备,但它提供纳秒级的定时器分辨率。一些高端个人计算机可能还配备有专用高速定时器,以提供纳秒级定时器分辨率。

CPU操作

每个CPU都有一个程序计数器(PC),也称为指令指针(IP),以及一个标志或状态寄存器(SR)、一个堆栈指针(SP)和几个通用寄存器,当PC指向内存中要执行的下一条指令时,SR包含CPU的当前状态,如操作模式、中断掩码和条件码,SP指向当前堆栈栈顶。
以上各步骤中,由于无效地址、非法指令、越权等原因,可能会出现一个错误状态,称为异常或陷阱。当CPU遇到异常时,它会根据内存中预先安装的指针来执行软件中的异常处理程序。在每条指令执行结束时,CPU会检查挂起的中断。中断是I/O设备或协处理器发送给CPU的外部信号,请求CPU服务。如果挂起的中断请求的状态寄存器已经屏蔽了中断,CPU会忽略中断请求,继续执行下一条指令,否则直接进行中断处理,处理完后恢复指令的正常执行。中断处理和异常处理都在操作系统内核中进行,多数情况下,用户级程序无法访问。

中断处理

外部设备的中断被反馈送到中断控制器的预定义输入行,按优先级对中断输入排序,并将具有最高优先级的中断作为中断请求(IRQ)路由器到CPU。如果状态寄存器屏蔽了中断,CPU会忽略中断请求,使其处于挂起状态,否则,它将直接执行中断处理。对于每个中断,可以编程中断控制器以生成一个唯一编号,叫作中断向量,标识中断源。获取中断向量号后,CPU用它作为内存中中断向量表中的条目索引,条目包含一个指向中断处理程序入口地址的指针来实际处理中断。

时钟服务函数

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

gettimeofday-settimeofday

#include<sys/time.h>
int gettimeofday(struct timeval *tv, struct timezone *tz);
int settimeofday(const struct timeval *tv, const struct timezone *tz);

这些是对 Linux 内核的系统调用。第一个参数 tv 指向一个 timeval 结构体。

struct timeval{time_t         tv_sec;    /* seconds */suseconds_t    tv_usec;   /* microseconds */
};

第二个参数 timezone 已过期,应设置为 NULL。gettimeofday() 函数用于返回当前时间(当前秒的秒和微秒)。settimeofday() 函数用于设置当前时间。在 Unix/Linux 中,时间表示自 1970年1月1日 00:00:00 起经过的秒数。它可以通过库函数 ctime(&time) 转换为日历形式。下面给出了 gettimeofday() 函数和settimeofday() 函数的示例。

gettimeofday 系统调用
#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=%ld\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));
}

time 系统调用

Time_t time(time_t *t)

以秒为单位返回当前时间,若参数t不是NULL,则会将时间存储在t指向的内存中。time系统调用具有一定局限性,只能提供以秒为单位的分辨率,而不是以微秒为单位。

times 系统调用

times 系统调用

clock_t times(struct tms *bus);

可用于获取某进程的具体执行时间。它将进程时间存储在 struct tms buf 中,即:


struct tms{clock_t tms_utime;    // user mode timeclock_t tms_stime;    // system mode timeclock_t tms_cutime;   // user time of childrenclock_t tms_cstime;   // system time of children
}

以时钟计时单元报告所有时间。这可以为分析某个正在执行的进程提供信息,包括其子进程的时间(如有)。

time 和 date 命令

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

苏格拉底挑战


二、问题与解决思路

强制转换类型

警告说明传递给printf函数的参数不是格式化字符串,而是一个指向字符串的指针。这种写法会导致潜在的安全问题,因为如果字符串中包含格式化占位符,那么printf函数可能会按照占位符的意图解析其他参数。这可能导致栈缓冲区溢出等严重问题。

解决方法:
将printf函数的第一个参数改为格式化字符串,用%s占位符表示要输出的字符串。这样就可以避免潜在的安全问题。
在没影响的情况下可以无视。

三、实践内容与截图

gettimeofday 系统调用

#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=%ld\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));
}

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++);end=time(NULL);printf("end =%ld time=%ld\n",end,end-start);
}

更多推荐

第八次学习笔记

本文发布于:2024-03-23 23:48:47,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1744282.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:学习笔记   第八次

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!