时间子系统¶
Linux采用了1970年1月1日0点0分0秒作为基准点(epoch)。
不同精度的时间¶
基于秒的时间定义:typedef long time_t
。
基于微秒的时间定义:
基于纳秒的时间定义:
软件架构¶
如图所示,timer的功能被分成了两块:
- Global Counter:全局计数器,不属于任何一个CPU
- CPU Local Timer:CPU本地计数器
文件列表¶
文件名 | 描述 |
---|---|
time.c | 用户空间的接口 |
timer.c | 低精度timer模块 |
hrtimer.c | 高精度timer模块 |
itimer.c | 周期性timer模块 |
posix-timer.c | POSIX timer模块 |
posix-clock.c | POSIX clock模块 |
alarmtimer.c | alarm timer模块 |
用户空间接口¶
从应用程序的角度来看,对于时间相关的服务要求主要有三种:
- 获取系统时间
- 进程睡眠操作
- 设置定时器事件
系统时间¶
1.秒级别的时间函数
time()
函数返回当前时间点到epoch的秒数,stime()
设定当前时间点到epoch的秒数。
2.微妙级别的时间函数
#include <sys/time.h>
int gettimeofday(struct timeval *tv, struct timezone *tz);
int settimeofday(const struct timeval *tv, const struct timezone *tz);
这两个函数与上面类似,只不过精度可以达到微妙级别。
3.纳秒级别的时间函数
#include <time.h>
int clock_getres(clockid_t clk_id, struct timespec *res);
int clock_gettime(clockid_t clk_id, struct timespec *tp);
int clock_settime(clockid_t clk_id, const struct timespec *tp);
clock ID为系统时钟的参数,它主要有以下几种类型:
- CLOCK_REALTIME:墙上时间(WALL TIME),用户可以对其设定。系统启动时,读取RTC的时间作为REALTIME时间
- CLOCK_MONOTONIC:系统启动到当前所经历的非休眠时间,可以由NTP调整
- CLOCK_MONOTONIC_RAW:同上,但是不受NTP影响
- CLOCK_BOOTTIME:系统启动到当前的时间,会统计休眠时间
进程睡眠¶
1.秒级别的睡眠函数
该函数返回没有睡眠的时间。
2.微秒级别的睡眠函数
该函数已被废弃。
3.纳秒级别的睡眠函数
nanosleep()
取代了usleep()
,在req中设定你要睡眠的秒数和纳秒数。rem表示还有多少时间没有睡完。
4.更高级的睡眠函数
#include <time.h>
int clock_nanosleep(clockid_t clk_id, int flags, const struct timespec *request, struct timespec *remain);
clk_id:指明是种类型
flag:0或者1,表示相对时间或绝对时间
定时器¶
1.alarm函数
该函数在制定秒数(基于CLOCK_REALTIME)过去后,向该进程发送SIGALRM信号。
2.POSIX timer
创建timer:
#include <signal.h>
#include <time.h>
int timer_create(clockid_t clockid, struct sigevent *sevp, timer_t *timerid)
struct sigevent
的定义如下:
union sigval
{
int sival_int;
void *sival_ptr;
};
typedef struct sigevent
{
__sigval_t sigev_value;
int sigev_signo;
int sigev_notify;
union
{
int _pad[__SIGEV_PAD_SIZE];
/* When SIGEV_SIGNAL and SIGEV_THREAD_ID set, LWP ID of the
thread to receive the signal. */
__pid_t _tid;
struct
{
void (*_function) (__sigval_t); /* Function to start. */
pthread_attr_t *_attribute; /* Thread attributes. */
} _sigev_thread;
} _sigev_un;
} sigevent_t;
成员sigev_notify定义了当定时器超时后,如何通知该进程:
- SIGEV_NONE:不需要异步通知,程序自己调用
timer_gettime()
来轮询定时器状态 - SIGEV_SIGNAL:使用signal异步通知,信号由成员sigev_signo定义
- SIGEV_THREAD:创建一个线程执行定时器超时回调函数
- SIGEV_THREAD_ID:行为和SIGEV_SIGNAL类似,但是信号被送至进程的一个指定线程中
设定定时器:
#include <time.h>
int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue);
int timer_gettime(timer_t timerid, struct itimerspec *curr_value);
struct itimerspec
的定义如下:
struct itimerspec
{
struct timespec it_interval; /* Interval for periodic timer */
struct timespec it_value; /* Time until next expiration */
};
it_value用来设置第一次超时时间,it_interval用来设置周期超时时间。
删除定时器: