Linux的時鐘管理

本文轉自博客園zhenwenxian的Linux時間管理,很詳細,寫得很不錯,對初學者仍是有很大幫助的。html

 

時間管理在內核中佔有很是重要的地位。相對於事件驅動,內核中有大量的函數都是基於時間驅動的。內核必須管理系統的運行時間以及當前的日期和時間。linux

 

首先搞清楚RTC在kernel內的做用:編程

linux系統有兩個時鐘:實時時鐘和系統定時器安全

 

實時時鐘

 

    一個是由鈕釦電池供電的「Real Time Clock」也叫作RTC(實時時鐘)或者叫CMOS時鐘,硬件時鐘。當操做系統關機的時候,用這個來記錄時間,可是對於運行的系統是不用這個時間的。當系統啓動時,內核經過讀取RTC來初始化牆上時間,該時間存放在xtime變量中。所謂牆上時間也就是當前的實際時間。數據結構

 

 

系統定時器

 

另外一個時間是 「System clock」也叫內核時鐘或者軟件時或者叫系統定時器,是由軟件根據時間中斷來進行計數的,系統定時器是內核時間機制中最重要的一部分,它提供了一種週期性觸發中斷機制,即系統定時器以HZ(時鐘節拍率)爲頻率自行觸發時鐘中斷。當時鍾中斷髮生時,內核就經過時鐘中斷處理程序timer_interrupt()對其進行處理。
系統定時器徹底由操做系統管理,所以也成爲系統時鐘或者軟件時鐘。當系統啓動時,內核經過RTC初始化系統定時器,系統定時器接着由操做系統共掌管,進行固定頻率的定時。能夠看到,系統時間並非傳統意義上的那種計時時鐘,而是經過定時這種特殊的方式來表現時間。 內核時鐘在系統關機的狀況下是不存在的,因此,當操做系統啓動的時候,內核時鐘是要讀取RTC時間來進行時間同步。而且在系統關機的時候將系統時間寫回RTC中進行同步。ide

 全局變量jiffies用來記錄自系統啓動以來產生的節拍的總數。它被用來記錄系統自開機以來,已通過了多少tick每發生一次timer interrupt,Jiffies變數會被加一。啓動時,內核將該變量初始化爲0,此後,每次時鐘中斷處理程序都會增長該變量的值。由於一秒內時鐘中斷的次數等於Hz,因此jiffes一秒內增長的值也就爲Hz,系統運行時間以秒爲單位計算,就等於jiffes/Hz函數

 

jiffies轉換爲秒可採用公式:(jiffies/HZ)計算,ui

將秒轉換爲jiffies可採用公式:(seconds*HZ)計算。this

Tick是HZ的倒數,意即timer interrupt每發生一次中斷的時間。如HZ爲250時,tick爲4毫秒(millisecond)。
spa

jiffies僅是相對於系統啓動的相對時間,若是想獲取absolutetime或wall time,則須要使用RTC,

內核用變量xtime來記錄,當系統啓動時,讀取RTC並記錄在xtime中,當系統halt時,則將walltime寫回RTC,函數do_gettimeofday()來讀取wall time。

系統定時器及其中斷處理程序是內核管理機制的中樞,下面是一些利用系統定時器週期執行的工做(中斷處理程序所作的工做):

    (1) 更新系統運行時間(uptime) jiffes

    (2) 更新當前牆上時間(wall time) xtime

    (3) 在對稱多處理器系統(SMP)上,均衡調度各處理器上的運行隊列

    (4) 檢查當前進程是否用完了時間片(time slice),若是用盡,則進行從新調度


如前所述,Linux內核與RTC進行互操做的時機只有兩個:

  

  1) 內核在啓動時從RTC中讀取啓動時的時間與日期(LINUX系統時間的 初始化);

經過調用rtc_read_time(rtc, &tm);-讀出RTC時間。調用  do_settimeofday(&tv);給系統時間xtime初始化。

Alarm.c (kernel\drivers\rtc):static int __init alarm_late_init(void)
Alarm.c (kernel\drivers\rtc):late_initcall(alarm_late_init);

static int __init alarm_late_init(void)
{
    unsigned long   flags;
    struct timespec tmp_time, system_time;

    /* this needs to run after the rtc is read at boot */
    spin_lock_irqsave(&alarm_slock, flags);
    /* We read the current rtc and system time so we can later calulate
     * elasped realtime to be (boot_systemtime + rtc - boot_rtc) ==
     * (rtc - (boot_rtc - boot_systemtime))
     */
    getnstimeofday(&tmp_time);
    ktime_get_ts(&system_time);
    alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta =
        alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta =
            timespec_to_ktime(timespec_sub(tmp_time, system_time));

    spin_unlock_irqrestore(&alarm_slock, flags);
    return 0;
}


Hctosys.c (kernel\drivers\rtc):int rtc_hctosys(void)
Hctosys.c (kernel\drivers\rtc):late_initcall(rtc_hctosys);

start_kernel()-->late_initcall(rtc_hctosys);-->

-->rtc_hctosys(void)-->err = rtc_read_time(rtc, &tm);--->    do_settimeofday(&tv);

----》xtime = *tv;

 

int rtc_hctosys(void)
{
    int err = -ENODEV;
    struct rtc_time tm;
    struct timespec tv = {
        .tv_nsec = NSEC_PER_SEC >> 1,
    };
    struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);

    if (rtc == NULL) {
        pr_err("%s: unable to open rtc device (%s)\n",
            __FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
        goto err_open;
    }

    err = rtc_read_time(rtc, &tm);
    if (err) {
        dev_err(rtc->dev.parent,
            "hctosys: unable to read the hardware clock\n");
        goto err_read;

    }

    err = rtc_valid_tm(&tm);
    if (err) {
        dev_err(rtc->dev.parent,
            "hctosys: invalid date/time\n");
        goto err_invalid;
    }

    rtc_tm_to_time(&tm, &tv.tv_sec);

    do_settimeofday(&tv);

    dev_info(rtc->dev.parent,
        "setting system clock to "
        "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n",
        tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
        tm.tm_hour, tm.tm_min, tm.tm_sec,
        (unsigned int) tv.tv_sec);

err_invalid:
err_read:
    rtc_class_close(rtc);

err_open:
    rtc_hctosys_ret = err;

    return err;
}

 

  2) 內核在須要時將時間與日期回寫到RTC中。 系統啓動時,內核經過讀取RTC來初始化內核時鐘,又叫牆上時間,該時間放在xtime變量中。

系統睡眠的時候CPU要斷電系統時鐘不工做,因此RTC的睡眠函數rtc_suspend讀出RTC和系統時鐘的時間,計算它們之間的差,而後保存到靜態變量。系統被喚醒後讀出當前RTC的時間和系統的時間,系統時間應該接近0,由於cpu剛剛恢復上電,將原來保存的RTC和系統之間的時間差加上剛剛讀到的RTC的時間就是最新的系統時間,將計算出來的時間經過rtc_resume函數調用    timekeeping_inject_sleeptime(&sleep_time);從新初始化系統時鐘xtime。若是RTC的時間和系統時間都同樣,那麼他們之間的差爲0.

可是有些系統硬件RTC時間是不能夠寫,只可以被讀,那麼他們之間的差就不爲0了。

Class.c (kernel\drivers\rtc):static int rtc_suspend(struct device *dev, pm_message_t mesg)

static int rtc_suspend(struct device *dev, pm_message_t mesg)
{
    struct rtc_device    *rtc = to_rtc_device(dev);
    struct rtc_time        tm;
    struct timespec        delta, delta_delta;
    if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
        return 0;

    /* snapshot the current RTC and system time at suspend*/
    rtc_read_time(rtc, &tm);
    getnstimeofday(&old_system);
    rtc_tm_to_time(&tm, &old_rtc.tv_sec);


    /*
     * To avoid drift caused by repeated suspend/resumes,
     * which each can add ~1 second drift error,
     * try to compensate so the difference in system time
     * and rtc time stays close to constant.
     */
    delta = timespec_sub(old_system, old_rtc);
    delta_delta = timespec_sub(delta, old_delta);
    if (delta_delta.tv_sec < -2 || delta_delta.tv_sec >= 2) {
        /*
         * if delta_delta is too large, assume time correction
         * has occured and set old_delta to the current delta.
         */
        old_delta = delta;
    } else {
        /* Otherwise try to adjust old_system to compensate */
        old_system = timespec_sub(old_system, delta_delta);
    }

    return 0;
}

static int rtc_resume(struct device *dev)
{
    struct rtc_device    *rtc = to_rtc_device(dev);
    struct rtc_time        tm;
    struct timespec        new_system, new_rtc;
    struct timespec        sleep_time;

    if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
        return 0;

    /* snapshot the current rtc and system time at resume */
    getnstimeofday(&new_system);
    rtc_read_time(rtc, &tm);
    if (rtc_valid_tm(&tm) != 0) {
        pr_debug("%s:  bogus resume time\n", dev_name(&rtc->dev));
        return 0;
    }
    rtc_tm_to_time(&tm, &new_rtc.tv_sec);
    new_rtc.tv_nsec = 0;

    if (new_rtc.tv_sec < old_rtc.tv_sec) {
        pr_debug("%s:  time travel!\n", dev_name(&rtc->dev));
        return 0;
    }

    /* calculate the RTC time delta (sleep time)*/
    sleep_time = timespec_sub(new_rtc, old_rtc);

    /*
     * Since these RTC suspend/resume handlers are not called
     * at the very end of suspend or the start of resume,
     * some run-time may pass on either sides of the sleep time
     * so subtract kernel run-time between rtc_suspend to rtc_resume
     * to keep things accurate.
     */
    sleep_time = timespec_sub(sleep_time,
            timespec_sub(new_system, old_system));

    if (sleep_time.tv_sec >= 0)
        timekeeping_inject_sleeptime(&sleep_time);
    return 0;
}



     週期產生的事件都是由系統定時器驅動的。系統定時器是一種可編程硬件芯片,它已固定頻率產生中斷。該中斷就是所謂的定時器中斷,它所對應的中斷處理程序負責更新系統時間,還負責執行須要週期性運行的任務。系統定時器和時鐘中斷處理程序是Linux系統內核管理機制中的中樞。

1  內核中的時間概念

      硬件爲內核提供了一個系統定時器用以計算流逝的時間,系統定時器以某種頻率自行觸發時鐘中斷,該頻率能夠經過編程預約,稱節拍率。當時鍾中斷髮生時,內核就經過一種特殊中斷處理程序對其進行處理。內核知道連續兩次時鐘中斷的間隔時間。這個間隔時間稱爲節拍(tick),內核就是靠這種已知的時鐘中斷來計算牆上時間和系統運行時間。牆上時間即實際時間,該時間放在xtime變量中,內核提供了一組系統調用以獲取實際日期和實際時間。系統運行時間——自系統啓動開始所通過的時間——對用戶和內核都頗有用,由於許多程序都必須清楚流逝過的時間。

2節拍率

     系統定時器頻率是經過靜態預處理定義的,也就是HZ,爲一秒內時鐘中斷的次數,在系統啓動時按照Hz對硬件進行設置。體系結構不一樣,HZ的值也不一樣。內核在文件<asm/param.h>中定義了HZ的實際值,節拍率就是HZ,週期爲1/HZi386的節拍率爲1000,其它體系結構(包括ARM)的節拍率多數都等於100

3   jiffies

     全局變量jiffies用來記錄自系統啓動以來產生的節拍的總數。啓動時,內核將該變量初始化爲0,此後,每次時鐘中斷處理程序都會增長該變量的值。由於一秒內時鐘中斷的次數等於Hz,因此jiffes一秒內增長的值也就爲Hz,系統運行時間以秒爲單位計算,就等於jiffes/HzJiffes=seconds*HZ

Jiffs定義在文件linux/jiffs.h

Extern unsigned long volatile jiffies

關鍵字volatile指示編譯器在每次訪問變量時都從新從主內存中得到,而不是經過寄存器中的變量別名訪問,從而確保前面的循環能按預期的方式執行。

3.1 jiffies的內部表示

       jiffies變量老是無符號長整數(unsigned long),所以,在32位體系結構上是32位,在時鐘頻率爲100的狀況下,497天后會溢出,若是頻率是100049.7天后會溢出

3.2用戶空間和HZ

     2.6之前的內核中,若是改變內核中HZ的值會給用戶空間中某些程序形成異常結果。這是由於內核是以節拍數/秒的形式給用戶空間導出這個值的,在這個接口穩定了很長一段時間後應用程序便逐漸依賴於這個特定的HZ值了。因此若是在內核中更改了HZ的定義值,就打破了用戶空間的常量關係——用戶空間並不知道新的HZ值。

     要想避免上面的錯誤,內核必須更改全部導出的jiffies值。於是內核定義了USER_HZ來表明用戶空間看到的值。對於ARM體系結構,HZ = USR_HZ

4硬實鍾和定時器

      體系結構提供了兩種設備進行計時——一種是咱們前面討論過的系統定時器,另外一種是實時時鐘。實時時鐘(RTC)是用來持久存放系統時間的設備,即使系統關閉後,它能夠靠主板上的微型電池提供的電力保持系統的計時。當系統啓動時,內核經過讀取RTC來初始化牆上時間,該時間存放在xtime變量中。

系統定時器是內核定時機制中最爲重要的角色。儘管不一樣體系結構中的定時器實現不盡相同,可是系統定時器的根本思想沒有區別——提供一種週期性觸發中斷機制。

5時鐘中斷處理程序

      下面咱們看一下時鐘中斷處理程序是如何實現的。時鐘中斷處理程序能夠劃分爲兩個部分:體系結構相關部分和體系結構無關部分。

與體系結構相關的例程做爲系統定時器的中斷處理程序而註冊到內核中,以便在產生時鐘中斷時,它可以相應的運行。雖然處理程序的具體工做依賴於特定的體系結構,可是絕大多數處理程序至少要執行以下工做:

1)得到xtime_lock鎖,以便對訪問jiffies_64和牆上時間xtime進行保護。

2)須要時應答或從新設置系統時鐘。

3)週期性的使用牆上時間更新實時時鐘。

4)調用體系結構無關的例程:do_timer

中斷服務程序主要經過調用與體系結構無關的例程do_timer執行下面的工做:

jiffies_64變量增長1

更新資源消耗的統計值,好比當前進程所消耗的系統時間和用戶時間。

執行已經到期的動態定時器。

執行scheduler_tick()函數。

更新牆上時間,該時間存放在xtime變量中。

Do_timer()函數執行完畢後返回與體系結構相關的中斷處理程序,繼續執行後面的工做,釋放xtime_lock鎖,而後退出。

以上所有工做每1/HZ秒都要發生一次,也就是說在你的PC機上時鐘中斷處理程序每秒執行1000次。

6實際時間

      當前實際時間(牆上時間)定義在文件kernel/timer.c中:

struct timespec xtime;

timespec數據結構定義在文件<linux/time.h>中,形式以下:

struct timespec{      time_t   tv_sec;           /* */

                                long tv_nsec;            /*納秒 */

}

其中,xtime.tv_sec以秒爲單位,存放着自197071以來通過的時間。xtime.tv_nsec記錄了自上一秒開始通過的納秒數。讀寫xtime變量須要使用xtime_lock鎖,它是一個seq鎖。讀取xtime時要使用read_seqbegin()read_seqretry()函數:



SYSCALL_DEFINE2(gettimeofday, struct timeval __user *, tv,
        struct timezone __user *, tz)---》

do_gettimeofday(&ktv);----》

 

Time.c (kernel\kernel):SYSCALL_DEFINE2(gettimeofday, struct timeval __user *, tv,

SYSCALL_DEFINE2(gettimeofday, struct timeval __user *, tv,
        struct timezone __user *, tz)
{
    if (likely(tv != NULL)) {
        struct timeval ktv;
        do_gettimeofday(&ktv);
        if (copy_to_user(tv, &ktv, sizeof(ktv)))
            return -EFAULT;
    }
    if (unlikely(tz != NULL)) {
        if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
            return -EFAULT;
    }
    return 0;
}

 

Timekeeping.c (kernel\kernel\time):void do_gettimeofday(struct timeval *tv)

void do_gettimeofday(struct timeval *tv)
{
    struct timespec now;

    getnstimeofday(&now);
    tv->tv_sec = now.tv_sec;
    tv->tv_usec = now.tv_nsec/1000;
}

 

Timekeeping.c (kernel\kernel\time):void getnstimeofday(struct timespec *ts)

void getnstimeofday(struct timespec *ts)
{
    unsigned long seq;
    s64 nsecs;

    WARN_ON(timekeeping_suspended);

    do {
        seq = read_seqbegin(&xtime_lock);

        *ts = xtime;
        nsecs = timekeeping_get_ns();

        /* If arch requires, add in gettimeoffset() */
        nsecs += arch_gettimeoffset();

    } while (read_seqretry(&xtime_lock, seq));

    timespec_add_ns(ts, nsecs);
}

EXPORT_SYMBOL(getnstimeofday);

 

該循環不斷重複,直到讀者確認讀取數據時沒有寫操做介入。若是發現循環期間有時鐘中斷處理程序更新xtime,那麼read_seqretry()函數就返回無效序列號,繼續循環等待。從用戶空間取得牆上時間的主要接口是gettimeofday()

7  定時器

      定時器,有時也稱爲動態定時器或內核定時器——是管理內核時間的基礎。定時器的使用很簡單。只須要執行一些初始化工做,設置一個超時時間,指定超時發生後執行的函數,而後激活定時器就能夠了。指定的函數將在定時器到期時自動執行。定時器並不週期運行,它在超時後就自行銷燬,這也正是這種定時器被稱爲動態定時器的一個緣由。

7.1使用定時器

     定時器由結構timer_list表示,定義在文件<linux/timer.h>中。

struct timer_list {

               struct list_head entry;         /*定時器鏈表的入口 */

                 unsigned long expiers;       /*jiffies爲單位的定時器 */

               spinlock_t   lock;                   /*保護定時器的鎖 */

               void   ( * function)(unsigned long);      /*定時器處理函數 */

              unsigned   long   data;            /*傳給處理函數的長整形參數 */

             struct tvec_t_base_s   *base;     /*定時器內部值,用戶不要使用 */

}

      內核提供了一組與定時器相關的接口用來簡化管理定時器的操做。全部這些接口都聲明在文件<linux/timer.h>中,大多數接口都在kernel/timer.c中得到實現。

    建立定時器時須要先定義它: struct   timer_list   my_timer;

     初始化定時器數據結構,初始化必須在使用其它定時器管理函數對定時器進行操做以前完成。

     init_timer(&my_timer);   而後就能夠填充結構中須要的值了。

    my_timer.expires = jiffies + delay;          /*定時器超時時的節拍數 */

    my_timer.data = 0;                                /*給定時器處理函數傳入0 */

    my_timer.function = my_function;          /*定時器超時時調用的函數 */

     my_timer.expires表示超時時間,它是以節拍爲單位的絕對計數值。若是當前jiffies計數等於或大於它,處理函數開始執行。處理函數必須符合下面的函數原形:

void   my_timer_function(unsigned long   data);

data參數使咱們能夠利用一個處理函數註冊多個定時器,只需經過該參數就能區別它們。

激活定時器:add_timer(&my_timer);

     有時可能須要更改已經激活的定時器超時時間,因此內核經過函數mod_timer()來實現該功能,該函數能夠改變指定的定時器超時時間:

mod_timer(&my_timer, jiffies+new_delay);

mod_timer()函數也能夠操做那些已經初始化,但尚未被激活的定時器,它會同時激活它。一旦從mod_timer()函數返回,定時器都將被激活並且設置了新的定時值。

若是須要在定時器超時前中止定時器,可使用del_timer()函數:

del_timer(&my_timer);        del_timer_sync()(不能在中斷上下文中使用)

8延遲執行

8.1忙等待

     最簡單的延遲方法是忙等待(或者說是忙循環)。但這種方法僅僅適用於延遲的時間是節拍的整數倍,或者精確度要求不高時。更好的方法是在代碼等待時,容許內核從新調度執行其餘任務:

unsigned long   delay = jiffies + 5*HZ;

while(time_before(jiffies, delay))           cond_resched();

cond_resched()函數將調度一個新程序投入運行,但它只有在設置完need_resched標誌後,才能生效。延遲執行無論在哪一種狀況下都不該該在持有鎖或禁止中斷時發生。

8.2  短延遲

       有時內核代碼(一般也是驅動程序)不但須要很短暫的延遲(比時鐘節拍還短)並且還要求延遲的時間按很精確。這種狀況多發生在和硬件同步時,內核提供了兩個能夠處理微秒和毫秒級別的延遲函數,它們都定義在<linux/delay.h>中,能夠看到它們並不使用jiffies:

void udelay(unsigned long usecs)

void mdelay(unsigned long msecs)

經驗證實,不要使用udelay()函數處理超過1毫秒的延遲。此時使用mdelay()更爲安全。

 

納秒,微妙,毫 秒延遲,必須是短延遲,時間過長會報錯

頭文件: delay.h

void ndelay(unsigned long nesec);

void udelay(unsigned long usecs);

void mdelay(unsigned long msecs);

void msleep(unsigned int millisecs);

void ssleep(unsigned int seconds);

 

 

 

 

長延遲

 

頭文件:jeffies.h / time.h

while(time_before(jiffies,jiffies+msecs_to_jiffies(delay_time)){

              schedule();

}

 

8.3   schedule_timeout()

      更理想的延遲執行方法是使用schedule_timeout()函數,用法以下:

set_current_state(TASK_INTERRUPTIBLE);      /*將任務設置爲可中斷睡眠狀態   */

schedule_timeout(s *HZ);        /*小睡一會,s秒後喚醒   */

惟一的參數是延遲的相對時間,單位爲jiffies。上例中將相應的任務推入可中斷睡眠隊列(注意了,這裏的進入睡眠隊列,就意味着能夠去執行其餘任務了),睡眠s秒。在調用schedule_timeout()函數前必須首先將任務設置成TASK_INTERRUPTILETASK_UNINTERRUPTIBLE面兩種狀態之一,不然任務不會睡眠。調用代碼絕對不能持有鎖(由於持有鎖的任務是不能睡眠的)。

      當任務被從新調度時,將返回代碼進入睡眠前的位置繼續執行。

 

時間相關的命令:

date顯示或設置系統時間與日期

date命令並不從RTC獲取時間,它獲取的是內核xtime時間,一樣它設置的也是內核xtime時間,而非RTC。

 

語法:   date [-d <字符串>] [-u] [+格式參數]
        date [-s <字符串>] [-u] [+格式參數] 
補充說明:
第一種語法可用來顯示系統日期或時間,以%爲開頭的參數爲格式參數,可指定日期或時間的顯示格式。
第二種語法可用來設置系統日期與時間。只有管理員纔有設置日期與時間的權限。
若不加任何參數,data會顯示目前的日期與時間。

該命令的各選項含義以下:

 -d<字符串>  顯示字符串所指的日期與時間。字符串先後必須加上雙引號。 
 -s<字符串>  根據字符串來設置日期與時間。字符串先後必須加上雙引號。 
 -u  顯示GMT。 
 --help  在線幫助。 
 --version  顯示版本信息。

該命令可用的格式參數以下:

 

命令中各選項的含義分別爲: 
  -d datestr, --date datestr 顯示由datestr描述的日期 
  -s datestr, --set datestr 設置datestr 描述的日期 
  -u, --universal 顯示或設置通用時間 時間域 
  % H 小時(00..23) 
  % I 小時(01..12) 
  % k 小時(0..23) 
  % l 小時(1..12) 
  % M 分(00..59) 
  % p 顯示出AM或PM 
  % r 時間(hh:mm:ss AM或PM),12小時 
  % s 從1970年1月1日00:00:00到目前經歷的秒數 
  % S 秒(00..59) 
  % T 時間(24小時制)(hh:mm:ss) 
  % X 顯示時間的格式(%H:%M:%S) 
  % Z 時區 日期域 
  % a 星期幾的簡稱( Sun..Sat) 
  % A 星期幾的全稱( Sunday..Saturday) 
  % b 月的簡稱(Jan..Dec) 
  % B 月的全稱(January..December) 
  % c 日期和時間( Mon Nov 8 14:12:46 CST 1999) 
  % d 一個月的第幾天(01..31) 
  % D 日期(mm/dd/yy) 
  % h 和%b選項相同 
  % j 一年的第幾天(001..366) 
  % m 月(01..12) 
  % w 一個星期的第幾天(0表明星期天) 
  % W 一年的第幾個星期(00..53,星期一爲第一天) 
  % x 顯示日期的格式(mm/dd/yy) 
  % y 年的最後兩個數字( 1999則是99) 
  % Y 年(例如:1970,1996等) 
  須要特別說明的是,只有超級用戶才能用date命令設置時間,通常用戶只能用date命令顯示時間。date是對系統時鐘的設置和讀,不是對RTC的操做。

 

使用示例一:

格式:

date 月/日/時間/年.秒

也能夠採用 date -s 月/日/年

date -s 時/分/秒

#date //查看系統時間

#date -s //設置當前時間,只有root權限才能設置,其餘只能查看。

#date -s 20120608//設置成20120608,這樣會把具體時間設置成空00:00:00

#date -s 12:23:23 //設置具體時間,不會對日期作更改

#date -s 「12:12:23 2006-10-10″ //這樣能夠設置所有時間

#date 060812232012(月日時分年)(完整書寫) //這樣能夠設置時間和日期

CST:中國標準時間(China Standard Time),這個解釋多是針對RedHat Linux。

UTC:協調世界時,又稱世界標準時間,簡稱UTC,從英文國際時間/法文協調時間」Universal Time/Temps Cordonn&eacute;」而來。中國大陸、香港、澳門、臺灣、蒙古國、新加坡、馬來西亞、菲律賓、澳洲西部的時間與UTC的時差均爲+8,也就是UTC+8。

GMT:格林尼治標準時間(舊譯格林威治平均時間或格林威治標準時間;英語:Greenwich Mean Time,GMT)是指位於英國倫敦郊區的皇家格林尼治天文臺的標準時間,由於本初子午線被定義在經過那裏的經線。

設置完系統時間後,還須要同步到硬件時鐘上

 

查看RTC時間:hwclock -r把系統時間更新至RTChwclock -w把RTC時間更新至系統hwclock -s設置後能夠以下查看RTC信息:cat /proc/driver/rtcrtc_time        : 09:32:13rtc_date        : 2011-03-24alrm_time        : **:**:**alrm_date        : 2063-**-31alarm_IRQ        : noalrm_pending        : no24hr                : yes

相關文章
相關標籤/搜索