Time#2

Setting the Current Time of Day

#define _SVID_SOURCE
#include <time.h>
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 <sys/time.h>
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 <time.h>
int clock_settime(clockid_t clock_id, 
                            const struct timespec *ts);

成功返回0,失敗返回-1,并設置errno褐奴。

Playing with Time

#include <time.h>
char *asctime(const struct tm *tm);
char *asctime_r(const struct tm *tm, char *buf);

成功返回字符串, 失敗返回NULL于毙。

//轉(zhuǎn)換tm結(jié)構(gòu)敦冬,但它將其轉(zhuǎn)換為time_t。
#include <time.h>
time_t mktime(struct tm *tm);

失敗返回-1唯沮。

//將time_t轉(zhuǎn)換為其ASCII表示形式
#include <time.h>
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()
緩沖區(qū)的長度必須至少為26個字符。
gmtime()將給定的time_t轉(zhuǎn)換為tm結(jié)構(gòu)介蛉,表示為UTC時區(qū):

#include <time.h>
struct tm * gmtime (const time_t *timep);
struct tm * gmtime_r (const time_t *timep, struct tm *result);

失敗返回NULL萌庆。

#include <time.h>
struct tm * localtime (const time_t *timep);
struct tm * localtime_r (const time_t *timep, struct tm *result);

difftime()返回兩個time_t值之間的秒數(shù),強制轉(zhuǎn)換為double:

#include <time.h>
double difftime (time_t time1, time_t time0);

Tuning the System Clock

#define _BSD_SOURCE
#include <sys/time.h>
int adjtime (const struct timeval *delta,
struct timeval *olddelta);
#include <sys/timex.h>
int adjtimex (struct timex *adj);

調(diào)用adjtimex()將內(nèi)核時間相關(guān)參數(shù)讀取到adj指向的timex結(jié)構(gòu)中币旧。\

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 <unistd.h>
unsigned int sleep (unsigned int seconds);

Sleeping with Microsecond Precision

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

Sleeping with Nanosecond Resolution

#define _POSIX_C_SOURCE 199309
#include <time.h>
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 <time.h>
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 <sys/select.h>
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

就是說比如系統(tǒng)的timer ticks 是10ms, 但請求了一個1ms的sleep, 系統(tǒng)是達不到這個精度的, 所以會比期待的1ms的延時長践险,會是10ms, 會比原來長9ms。

Alternatives to Sleeping

Timers

Simple Alarms

#include <unistd.h>
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 <sys/time.h>
int getitimer (int which, struct itimerval *value);
int setitimer (int which, const struct itimerval *value,
                        struct itimerval *ovalue);

間隔計時器的工作方式類似于告警()吹菱,但也可以自動重新武裝自己巍虫,并在以下三種不同模式中的一種模式下操作:

  • ITIMER_REAL
    實時測量。當指定的實時時間已經(jīng)過去時毁葱,內(nèi)核將向進程發(fā)送一個SIGALRM信號垫言。
  • ITIMER_VIRTUAL
    只有在進程的用戶空間代碼正在執(zhí)行時才會減少。當指定的進程時間已過時倾剿,內(nèi)核將向進程發(fā)送SIGVTALRM筷频。
  • ITIMER_PROF
    進程執(zhí)行時和內(nèi)核代表進程執(zhí)行時(例如,完成系統(tǒng)調(diào)用)都會減少前痘。當指定的時間已經(jīng)過去時凛捏, 內(nèi)核向進程發(fā)送SIGPROF信號。此模式通常與ITIMER_VUALUAL耦合芹缔,以便程序能夠測量進程所花費的用戶和內(nèi)核時間坯癣。
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 <signal.h>
#include <time.h>
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 <signal.h>
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 <time.h>

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 <time.h>

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 <time.h>

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 <time.h>

int timer_delete (timer_t timerid);

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市最欠,隨后出現(xiàn)的幾起案子示罗,更是在濱河造成了極大的恐慌惩猫,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蚜点,死亡現(xiàn)場離奇詭異轧房,居然都是意外死亡,警方通過查閱死者的電腦和手機绍绘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門奶镶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人陪拘,你說我怎么就攤上這事厂镇。” “怎么了左刽?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵捺信,是天一觀的道長。 經(jīng)常有香客問我悠反,道長残黑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任斋否,我火速辦了婚禮,結(jié)果婚禮上拭荤,老公的妹妹穿的比我還像新娘茵臭。我一直安慰自己,他們只是感情好舅世,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布旦委。 她就那樣靜靜地躺著,像睡著了一般雏亚。 火紅的嫁衣襯著肌膚如雪缨硝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天罢低,我揣著相機與錄音查辩,去河邊找鬼。 笑死网持,一個胖子當著我的面吹牛宜岛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播功舀,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼萍倡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了辟汰?” 一聲冷哼從身側(cè)響起列敲,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤阱佛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后戴而,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凑术,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年填硕,在試婚紗的時候發(fā)現(xiàn)自己被綠了麦萤。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡扁眯,死狀恐怖壮莹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情姻檀,我是刑警寧澤命满,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站绣版,受9級特大地震影響胶台,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜杂抽,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一诈唬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缩麸,春花似錦铸磅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至弧械,卻和暖如春八酒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背刃唐。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工羞迷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人唁桩。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓闭树,卻偏偏與公主長得像,于是被迫代替她去往敵國和親荒澡。 傳聞我的和親對象是個殘疾皇子报辱,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容