Time#2

Setting the Current Time of Day

#define _SVID_SOURCE
#include 
int stime(time_t *t);

成功返回0,失败返回-1并设置errno。

//example
time_t t = 1;
int ret;
/* set time to one second after the epoch */
ret = stime(&t);
if(ret)
    perror("stime");

Setting Time with Precision

#include 
int settimeofday(const struct timeval *tv, 
                           const struct timezone *tz);

passing NULL for tz is the best practice
成功返回0, 失败返回-1。

// set the current time to a Saturday 
//in the middle of December 1979
struct timeval tv = {.tv_sec = 31415926,
                              .tv_usec = 27182818};
int ret;
ret = settimeofday(&tv, NULL);
if(ret)
    perror("settimeofday");

An Advanced Interface for Setting the Time

#include 
int clock_settime(clockid_t clock_id, 
                            const struct timespec *ts);

成功返回0,失败返回-1,并设置errno。

Playing with Time

#include 
char *asctime(const struct tm *tm);
char *asctime_r(const struct tm *tm, char *buf);

成功返回字符串, 失败返回NULL。

//转换tm结构,但它将其转换为time_t。
#include 
time_t mktime(struct tm *tm);

失败返回-1。

//将time_t转换为其ASCII表示形式
#include 
char * ctime (const time_t *timep);
char * ctime_r (const time_t *timep, char *buf);

失败返回NULL。

    t = time (NULL);
    printf ("the time a mere line ago: %s", ctime (&t));

result

线程程序应该使用ctime_r()
缓冲区的长度必须至少为26个字符。
gmtime()将给定的time_t转换为tm结构,表示为UTC时区:

#include 
struct tm * gmtime (const time_t *timep);
struct tm * gmtime_r (const time_t *timep, struct tm *result);

失败返回NULL。

#include 
struct tm * localtime (const time_t *timep);
struct tm * localtime_r (const time_t *timep, struct tm *result);

difftime()返回两个time_t值之间的秒数,强制转换为double:

#include 
double difftime (time_t time1, time_t time0);

Tuning the System Clock

#define _BSD_SOURCE
#include 
int adjtime (const struct timeval *delta,
struct timeval *olddelta);
#include 
int adjtimex (struct timex *adj);

调用adjtimex()将内核时间相关参数读取到adj指向的timex结构中。\

struct timex {
    int modes; /* mode selector */
    long offset; /* time offset (usec) */
    long freq; /* frequency offset (scaled ppm) */
    long maxerror; /* maximum error (usec) */
    long esterror; /* estimated error (usec) */
    int status; /* clock status */
    long constant; /* PLL time constant */
    long precision; /* clock precision (usec) */
    long tolerance; /* clock frequency tolerance (ppm) */
    struct timeval time; /* current time */
    long tick; /* usecs between clock ticks */
};

Sleeping and Waiting

#include 
unsigned int sleep (unsigned int seconds);

Sleeping with Microsecond Precision

/* BSD version */
#include 
void usleep (unsigned long usec);
/* SUSv2 version */
#define _XOPEN_SOURCE 500
#include 
int usleep (useconds_t usec);
errno = 0;
usleep (1000);
if (errno)
    perror ("usleep");

Sleeping with Nanosecond Resolution

#define _POSIX_C_SOURCE 199309
#include 
int nanosleep (const struct timespec *req,
                        struct timespec *rem);
struct timespec req = { .tv_sec = 0, .tv_nsec = 200 };
/* sleep for 200 ns */
ret = nanosleep (&req, NULL);
if (ret)
    perror ("nanosleep");
struct timespec req = { .tv_sec = 0, .tv_nsec = 1369 };
struct timespec rem;
int ret;
/* sleep for 1369 ns */
retry:
ret = nanosleep (&req, &rem);
if (ret) {
    if (errno == EINTR) {
        /* retry, with the provided time remaining */
        req.tv_sec = rem.tv_sec;
        req.tv_nsec = rem.tv_nsec;
        goto retry; 
      }
    perror ("nanosleep");
}
struct timespec req = { .tv_sec = 1, .tv_nsec = 0 };
struct timespec rem, *a = &req, *b = &rem;
/* sleep for 1s */
while (nanosleep (a, b) && errno == EINTR) {
    struct timespec *tmp = a; 
    a = b;
     b = tmp;
 }

An Advanced Approach to Sleep

#include 
int clock_nanosleep (clockid_t clock_id,
                                   int flags,
                                    const struct timespec *req,
                                    struct timespec *rem);
ret = nanosleep (&req, &rem); 
==
ret = clock_nanosleep (CLOCK_REALTIME, 0, &req, &rem);
struct timespec ts = { .tv_sec = 1, .tv_nsec = 500000000 };
int ret;
ret = clock_nanosleep (CLOCK_MONOTONIC, 0, &ts, NULL);
if (ret)
      perror ("clock_nanosleep");
int ret;
/* we want to sleep until one second from NOW */
ret = clock_gettime (CLOCK_MONOTONIC, &ts);
if (ret) {
    perror ("clock_gettime");
    return;
}
ts.tv_sec += 1;
printf ("We want to sleep until sec=%ld nsec=%ld\n",
ts.tv_sec, ts.tv_nsec);
ret = clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, NULL);
if (ret)
    perror ("clock_nanosleep");

A Portable Way to Sleep

#include 
int select (int n,
      fd_set *readfds,
      fd_set *writefds,
      fd_set *exceptfds,
      struct timeval *timeout);
struct timeval tv = { .tv_sec = 0, .tv_usec = 757 };
/* sleep for 757 us */
select (0, NULL, NULL, NULL, &tv);

Overruns

就是说比如系统的timer ticks 是10ms, 但请求了一个1ms的sleep, 系统是达不到这个精度的, 所以会比期待的1ms的延时长,会是10ms, 会比原来长9ms。

Alternatives to Sleeping

Timers

Simple Alarms

#include 
unsigned int alarm(unsigned int seconds);
void alarm_handler (int signum) {
    printf ("Five seconds passed!\n");
}
void func (void) {
    signal (SIGALRM, alarm_handler);
    alarm (5);
    pause ();
}
## Interval Timers
#include 
int getitimer (int which, struct itimerval *value);
int setitimer (int which, const struct itimerval *value,
                        struct itimerval *ovalue);

间隔计时器的工作方式类似于告警(),但也可以自动重新武装自己,并在以下三种不同模式中的一种模式下操作:

  • ITIMER_REAL
    实时测量。当指定的实时时间已经过去时,内核将向进程发送一个SIGALRM信号。
  • ITIMER_VIRTUAL
    只有在进程的用户空间代码正在执行时才会减少。当指定的进程时间已过时,内核将向进程发送SIGVTALRM。
  • ITIMER_PROF
    进程执行时和内核代表进程执行时(例如,完成系统调用)都会减少。当指定的时间已经过去时, 内核向进程发送SIGPROF信号。此模式通常与ITIMER_VUALUAL耦合,以便程序能够测量进程所花费的用户和内核时间。
struct itimerval {
    struct timeval it_interval; /* next value */
    struct timeval it_value; /* current value */
};
struct timeval {
    long tv_sec; /* seconds */
    long tv_usec; /* microseconds */
};
void alarm_handler (int signo) {
printf ("Timer hit!\n");
}
void foo (void) {
    struct itimerval delay;
    int ret;
    signal (SIGALRM, alarm_handler);
    delay.it_value.tv_sec = 5;
    delay.it_value.tv_usec = 0;
    delay.it_interval.tv_sec = 1;
    delay.it_interval.tv_usec = 0;
    ret = setitimer (ITIMER_REAL, &delay, NULL);
    if (ret) {
    perror ("setitimer");
    return; }
    pause ();
}

Advanced Timer

Creating a timer

#include 
#include 
int timer_create (clockid_t clockid, struct sigevent *evp, timer_t *timerid);
timer_t timer;
int ret;
ret = timer_create (CLOCK_PROCESS_CPUTIME_ID, NULL, &timer);
if (ret)
    perror ("timer_create");
#include 
struct sigevent {
    union sigval sigev_value;
    int sigev_signo;
    int sigev_notify;
    void (*sigev_notify_function)(union sigval);
    pthread_attr_t *sigev_notify_attributes;
};
union sigval {
    int sival_int;
    void *sival_ptr;
};

The following example creates a timer keyed off CLOCK_REALTIME. When the timer ex‐pires, the kernel will issue the SIGUSR1 signal and set si_value to the address storing the timer’s ID:

struct sigevent evp;
timer_t timer;
int ret;
evp.sigev_value.sival_ptr = &timer;
evp.sigev_notify = SIGEV_SIGNAL;
evp.sigev_signo = SIGUSR1;
ret = timer_create (CLOCK_REALTIME, &evp, &timer);
if (ret)
    perror ("timer_create");

Arming a timer

include

int timer_settime (timer_t timerid, int flags, const struct itimerspec *value,
struct itimerspec *ovalue);

struct itimerspec {
struct timespec it_interval; /* next value /
struct timespec it_value; /
current value */
};

Using the timer value initialized earlier by timer_create(), the following example
creates a periodic timer that expires every second:

struct itimerspec ts;
int ret;
ts.it_interval.tv_sec = 1;
ts.it_interval.tv_nsec = 0;
ts.it_value.tv_sec = 1;
ts.it_value.tv_nsec = 0;
ret = timer_settime (timer, 0, &ts, NULL);
if (ret)
perror ("timer_settime");

### Obtaining the expiration of a timer

include

int timer_gettime (timer_t timerid, struct itimerspec *value);

struct itimerspec ts;
int ret;
ret = timer_gettime (timer, &ts);
if (ret)
perror ("timer_gettime");
else {
printf ("current sec=%ld nsec=%ld\n",
ts.it_value.tv_sec, ts.it_value.tv_nsec);
printf ("next sec=%ld nsec=%ld\n",
ts.it_interval.tv_sec, ts.it_interval.tv_nsec);
}

### Obtaining the overrun of a timer

include

int timer_getoverrun (timer_t timerid);

//example
int ret;
ret = timer_getoverrun (timer);
if (ret == −1)
perror ("timer_getoverrun");
else if (ret == 0)
printf ("no overrun\n");
else
printf ("%d overrun(s)\n", ret);

### Deleting a timer

include

int timer_delete (timer_t timerid);

你可能感兴趣的:(Time#2)