• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            colorful

            zc qq:1337220912

             

            Linux中時間度量

            Linux中時間度量

            一)ANSI clock函數


            1)概述:
            clock 函數的返回值類型是clock_t,它除以CLOCKS_PER_SEC來得出時間,一般用兩次clock函數來計算進程自身運行的時間.

            ANSI clock有三個問題:
            1)如果超過一個小時,將要導致溢出.
            2)函數clock沒有考慮CPU被子進程使用的情況.
            3)也不能區分用戶空間和內核空間.

            所以clock函數在linux系統上變得沒有意義.

            2)測試
            編寫test1.c程序,測試采用clock函數的輸出與time程序的區別.

            vi test1.c
            #include <stdio.h>
            #include <stdlib.h>
            #include <time.h>

            int main( void )
            {
               long i=1000L;
               clock_t start, finish;
               double  duration;
               printf( "Time to do %ld empty loops is ", i );
               start = clock();
               while (--i){
                system("cd");
               }
               finish = clock();
               duration = (double)(finish - start) / CLOCKS_PER_SEC;
               printf( "%f seconds\n", duration );
               return 0;
            }

            gcc test1.c -o test1

            time ./test1
            Time to do 1000 empty loops is 0.180000 seconds

            real    0m3.492s
            user    0m0.512s
            sys     0m2.972s

            3)總結:
            (1)程序調用 system("cd");,這里主要是系統模式子進程的消耗,test1程序不能體現這一點.
            (2)0.180000 seconds秒的消耗是兩次clock()函數調用除以CLOCKS_PER_SEC.
            (3)clock()函數返回值是一個相對時間,而不是絕對時間.
            (4)CLOCKS_PER_SEC是系統定義的宏,由GNU標準庫定義為1000000.

             


            二)times()時間函數

            1)概述:

            原型如下:
            clock_t times(struct tms *buf);

            tms結構體如下:
            strace tms{
             clock_t tms_utime;
             clock_t tms_stime;
             clock_t tms_cutime;
             clock_t tms_cstime;
            }

            注釋:
            tms_utime記錄的是進程執行用戶代碼的時間.
            tms_stime記錄的是進程執行內核代碼的時間.
            tms_cutime記錄的是子進程執行用戶代碼的時間.
            tms_cstime記錄的是子進程執行內核代碼的時間.


            2)測試:

            vi test2.c
            #include <sys/times.h>
            #include <stdio.h>
            #include <stdlib.h>
            #include <sys/types.h>
            #include <unistd.h>

            static void do_cmd(char *);
            static void pr_times(clock_t, struct tms *, struct tms *);

            int main(int argc, char *argv[]){
                    int i;
                    for(i=1; argv[i]!=NULL; i++){
                            do_cmd(argv[i]);
                    }
                    exit(1);
            }
            static void do_cmd(char *cmd){
                    struct tms tmsstart, tmsend;
                    clock_t start, end;
                    int status;
                    if((start=times(&tmsstart))== -1)
                            puts("times error");
                    if((status=system(cmd))<0)
                            puts("system error");
                    if((end=times(&tmsend))== -1)
                            puts("times error");
                    pr_times(end-start, &tmsstart, &tmsend);
                    exit(0);
            }
            static void pr_times(clock_t real, struct tms *tmsstart, struct tms *tmsend){
                    static long clktck=0;
                    if(0 == clktck)
                            if((clktck=sysconf(_SC_CLK_TCK))<0)
                                       puts("sysconf err");
                    printf("real:%7.2f\n", real/(double)clktck);
                    printf("user-cpu:%7.2f\n", (tmsend->tms_utime - tmsstart->tms_utime)/(double)clktck);
                    printf("system-cpu:%7.2f\n", (tmsend->tms_stime - tmsstart->tms_stime)/(double)clktck);
                    printf("child-user-cpu:%7.2f\n", (tmsend->tms_cutime - tmsstart->tms_cutime)/(double)clktck);
                    printf("child-system-cpu:%7.2f\n", (tmsend->tms_cstime - tmsstart->tms_cstime)/(double)clktck);
            }

            編譯:
            gcc test2.c -o test2

            測試這個程序:
            time ./test2 "dd if=/dev/zero f=/dev/null bs=1M count=10000"
            10000+0 records in
            10000+0 records out
            10485760000 bytes (10 GB) copied, 4.93028 s, 2.1 GB/s
            real:   4.94
            user-cpu:   0.00
            system-cpu:   0.00
            child-user-cpu:   0.01
            child-system-cpu:   4.82

            real    0m4.943s
            user    0m0.016s
            sys     0m4.828s


            3)總結:
            (1)通過這個測試,系統的time程序與test2程序輸出基本一致了.
            (2)(double)clktck是通過clktck=sysconf(_SC_CLK_TCK)來取的,也就是要得到user-cpu所占用的時間, 就要用
            (tmsend->tms_utime - tmsstart->tms_utime)/(double)clktck);
            (3)clock_t times(struct tms *buf);返回值是過去一段時間內時鐘嘀嗒的次數.
            (4)times()函數返回值也是一個相對時間.

             

            三)實時函數clock_gettime

            在POSIX1003.1中增添了這個函數,它的原型如下:
            int clock_gettime(clockid_t clk_id, struct timespec *tp);

            它有以下的特點:
            1)它也有一個時間結構體:timespec ,timespec計算時間次數的單位是十億分之一秒.
            strace timespec{
             time_t tv_sec;
             long tv_nsec;
            }

            2)clockid_t是確定哪個時鐘類型.

            CLOCK_REALTIME: 標準POSIX實時時鐘
            CLOCK_MONOTONIC: POSIX時鐘,以恒定速率運行;不會復位和調整,它的取值和CLOCK_REALTIME是一樣的.
            CLOCK_PROCESS_CPUTIME_ID和CLOCK_THREAD_CPUTIME_ID是CPU中的硬件計時器中實現的.


            3)測試:
            #include<time.h>
            #include<stdio.h>
            #include<stdlib.h>

            #define MILLION 1000000


            int main(void)
            {
                    long int loop = 1000;
                    struct timespec tpstart;
                    struct timespec tpend;
                    long timedif;

                    clock_gettime(CLOCK_MONOTONIC, &tpstart);

                    while (--loop){
                            system("cd");
                    }

                    clock_gettime(CLOCK_MONOTONIC, &tpend);
                    timedif = MILLION*(tpend.tv_sec-tpstart.tv_sec)+(tpend.tv_nsec-tpstart.tv_nsec)/1000;
                    fprintf(stdout, "it took %ld microseconds\n", timedif);

                    return 0;
            }

            編譯:
            gcc test3.c -lrt -o test3

            計算時間:
            time ./test3
            it took 3463843 microseconds

            real    0m3.467s
            user    0m0.512s
            sys     0m2.936s

             


            四)時間函數gettimeofday()

            1)概述:
            gettimeofday()可以獲得當前系統的時間,是一個絕對值

            原型如下:
            int gettimeofday ( struct timeval * tv , struct timezone * tz )

            timeval結型體的原型如下:
            struct timeval {
                           time_t      tv_sec;    
                           suseconds_t tv_usec;   
                       };

            所以它可以精確到微秒


            測試:
            #include <sys/time.h>
            #include <stdio.h>
            #include <unistd.h>
            int
            main(){
                    int i=10000000;
                    struct timeval tvs,tve;
                    gettimeofday(&tvs,NULL);
                    while (--i);
                    gettimeofday(&tve,NULL);
                    double span = tve.tv_sec-tvs.tv_sec + (tve.tv_usec-tvs.tv_usec)/1000000.0;
                    printf("time: %.12f\n",span);
                    return 0;
            }

            gcc test5.c
            ./a.out
            time: 0.041239000000

             

            五)四種時間函數的比較

            1)精確度比較:

            以下是各種精確度的類型轉換:
            1秒=1000毫秒(ms), 1毫秒=1/1000秒(s);
            1秒=1000000 微秒(μs), 1微秒=1/1000000秒(s);
            1秒=1000000000 納秒(ns),1納秒=1/1000000000秒(s);


            2)
            clock()函數的精確度是10毫秒(ms)
            times()函數的精確度是10毫秒(ms)
            gettimofday()函數的精確度是微秒(μs)
            clock_gettime()函數的計量單位為十億分之一,也就是納秒(ns)


            3)測試4種函數的精確度:

            vi test4.c


            #include    <stdio.h>
            #include    <stdlib.h>
            #include    <unistd.h>
            #include    <time.h>
            #include    <sys/times.h>
            #include    <sys/time.h>
            #define WAIT for(i=0;i<298765432;i++);
            #define MILLION    1000000
                int
            main ( int argc, char *argv[] )
            {
                int i;
                long ttt;
                clock_t s,e;
                struct tms aaa;



                s=clock();
                WAIT;
                e=clock();
                printf("clock time : %.12f\n",(e-s)/(double)CLOCKS_PER_SEC);


                long tps = sysconf(_SC_CLK_TCK);
                s=times(&aaa);
                WAIT;
                e=times(&aaa);
                printf("times time : %.12f\n",(e-s)/(double)tps);


                struct timeval tvs,tve;
                gettimeofday(&tvs,NULL);
                WAIT;
                gettimeofday(&tve,NULL);
                double span = tve.tv_sec-tvs.tv_sec + (tve.tv_usec-tvs.tv_usec)/1000000.0;
                printf("gettimeofday time: %.12f\n",span);


                struct timespec tpstart;
                struct timespec tpend;

                clock_gettime(CLOCK_REALTIME, &tpstart);
                WAIT;
                clock_gettime(CLOCK_REALTIME, &tpend);
                double timedif = (tpend.tv_sec-tpstart.tv_sec)+(tpend.tv_nsec-tpstart.tv_nsec)/1000000000.0;
                printf("clock_gettime time: %.12f\n", timedif);

                return EXIT_SUCCESS;
            }

            gcc -lrt test4.c -o test4
            debian:/tmp# ./test4
            clock time : 1.190000000000
            times time : 1.180000000000
            gettimeofday time: 1.186477000000
            clock_gettime time: 1.179271718000

             

            六)內核時鐘

            默認的Linux時鐘周期是100HZ,而現在最新的內核時鐘周期默認為250HZ.
            如何得到內核的時鐘周期呢?
            grep ^CONFIG_HZ /boot/config-2.6.26-1-xen-amd64

            CONFIG_HZ_250=y
            CONFIG_HZ=250

            結果就是250HZ.

            而用sysconf(_SC_CLK_TCK);得到的卻是100HZ
            例如:

            #include    <stdio.h>
            #include    <stdlib.h>
            #include    <unistd.h>
            #include    <time.h>
            #include    <sys/times.h>
            #include    <sys/time.h>

            int
            main ( int argc, char *argv[] )
            {

                long tps = sysconf(_SC_CLK_TCK);
                printf("%ld\n", tps);
               
                return EXIT_SUCCESS;
            }

            為什么得到的是不同的值呢?
            因為sysconf(_SC_CLK_TCK)和CONFIG_HZ所代表的意義是不同的.
            sysconf(_SC_CLK_TCK)是GNU標準庫的clock_t頻率.
            它的定義位置在:/usr/include/asm/param.h

            例如:
            #ifndef HZ
            #define HZ 100
            #endif

            最后總結一下內核時間:
            內核的標準時間是jiffy,一個jiffy就是一個內部時鐘周期,而內部時鐘周期是由250HZ的頻率所產生中的,也就是一個時鐘滴答,間隔時間是4毫 秒(ms).

            也就是說:
            1個jiffy=1個內部時鐘周期=250HZ=1個時鐘滴答=4毫秒

            每經過一個時鐘滴答就會調用一次時鐘中斷處理程序,處理程序用jiffy來累計時鐘滴答數,每發生一次時鐘中斷就增1.
            而每個中斷之后,系統通過調度程序跟據時間片選擇是否要進程繼續運行,或讓進程進入就緒狀態.

            最后需要說明的是每個操作系統的時鐘滴答頻率都是不一樣的,LINUX可以選擇(100,250,1000)HZ,而DOS的頻率是55HZ.

             

            七)為應用程序計時

            用time程序可以監視任何命令或腳本占用CPU的情況.

            1)bash內置命令time
            例如:
            time sleep 1

            real    0m1.016s
            user    0m0.000s
            sys     0m0.004s


            2)/usr/bin/time的一般命令行
            例如:
            \time sleep 1
            0.00user 0.00system 0:01.01elapsed 0%CPU (0avgtext+0avgdata 0maxresident)k
            0inputs+0outputs (1major+176minor)pagefaults 0swaps

            注:
            在命令前加上斜杠可以繞過內部命令.
            /usr/bin/time還可以加上-v看到更具體的輸出:
            \time -v sleep 1
                    Command being timed: "sleep 1"
                    User time (seconds): 0.00
                    System time (seconds): 0.00
                    Percent of CPU this job got: 0%
                    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:01.00
                    Average shared text size (kbytes): 0
                    Average unshared data size (kbytes): 0
                    Average stack size (kbytes): 0
                    Average total size (kbytes): 0
                    Maximum resident set size (kbytes): 0
                    Average resident set size (kbytes): 0
                    Major (requiring I/O) page faults: 0
                    Minor (reclaiming a frame) page faults: 178
                    Voluntary context switches: 2
                    Involuntary context switches: 0
                    Swaps: 0
                    File system inputs: 0
                    File system outputs: 0
                    Socket messages sent: 0
                    Socket messages received: 0
                    Signals delivered: 0
                    Page size (bytes): 4096
                    Exit status: 0
                   
            這里的輸出更多來源于結構體rusage.

            最后,我們看到real time大于user time和sys time的總和,這說明進程不是在系統調用中阻塞,就是得不到運行的機會.
            而sleep()的運用,也說明了這一點

            posted on 2012-05-07 09:51 多彩人生 閱讀(1575) 評論(0)  編輯 收藏 引用 所屬分類: linux program

            導航

            統計

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            囯产精品久久久久久久久蜜桃| 久久AⅤ人妻少妇嫩草影院| 奇米影视7777久久精品人人爽| 久久久久女教师免费一区| 亚洲人成网站999久久久综合| 国内精品伊人久久久久妇| 久久亚洲精品人成综合网| 色综合久久中文色婷婷| 久久久WWW成人| 国产V综合V亚洲欧美久久| 久久国产午夜精品一区二区三区| 精品久久久中文字幕人妻| 国产成人精品久久亚洲高清不卡 | 亚洲欧美另类日本久久国产真实乱对白| 久久精品国产亚洲AV不卡| 香蕉久久夜色精品国产小说| 国内精品伊人久久久久妇| 亚洲一本综合久久| 久久Av无码精品人妻系列| 人妻无码久久精品| 久久99热国产这有精品| 久久精品国产2020| 久久se精品一区二区影院 | 精品国产99久久久久久麻豆| 狠狠色噜噜狠狠狠狠狠色综合久久| 欧美精品丝袜久久久中文字幕| 久久99国产综合精品免费| 久久亚洲精品国产精品婷婷| 久久99精品久久久久久噜噜| 久久99国产精品尤物| 色综合久久无码五十路人妻| 久久99热这里只频精品6| 很黄很污的网站久久mimi色 | 久久久久婷婷| 亚洲一本综合久久| 精品国产福利久久久| 国产午夜久久影院| 久久香蕉综合色一综合色88| 国内精品久久久久久久97牛牛| 性欧美大战久久久久久久久 | 精品久久久久久久无码|