Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)
Demon's Souls |#9| Heart of surprises

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Богатырев А. Весь текст 1009.15 Kb

Хрестоматия по программированию на Си в Unix

Предыдущая страница Следующая страница
1 ... 32 33 34 35 36 37 38  39 40 41 42 43 44 45 ... 87
момента;  в  чем  полностью соответствует системному вызову time.  Однако плюс к тому
поле tv_usec содержит число миллионных долей текущей  секунды  (значение  этого  поля
всегда меньше 1000000).

6.2.11.  К данному параграфу вернитесь, изучив раздел про fork()  и  exit().   Каждый
процесс  может пребывать в двух фазах: системной (внутри тела системного вызова - его
выполняет для нас ядро операционной системы) и пользовательской  (внутри  кода  самой
программы). Время, затраченное процессом в каждой фазе, может быть измеряно системным
вызовом times(). Кроме того, этот вызов позволяет узнать суммарное время, затраченное
порожденными  процессами  (порожденными  при помощи fork).  Системный вызов заполняет
структуру

А. Богатырев, 1992-95                  - 203 -                              Си в UNIX

    struct tms {
            clock_t tms_utime;
            clock_t tms_stime;
            clock_t tms_cutime;
            clock_t tms_cstime;
    };

и возвращает значение

    #include 

    struct tms time_buf;
    clock_t real_time = times(&time_buf);

Все времена измеряются в "тиках" - некоторых долях секунды.  Число  тиков  в  секунде
можно узнать таким системным вызовом (в системе Solaris):

    #include 
    clock_t HZ = sysconf(_SC_CLK_TCK);

В старых системах, где таймер работал от сети переменного тока, это число  получалось
равным 60 (60 Герц - частота сети переменного тока).  В современных системах это 100.
Поля структуры содержат:
tms_utime
     время, затраченное вызывающим процессом  в пользовательской фазе.
tms_stime
     время, затраченное вызывающим процессом  в системной фазе.
tms_cutime
     время, затраченное порожденными процессами  в пользовательской фазе:  оно  равно
     сумме  всех tms_utime и tms_cutime порожденных процессов (рекурсивное суммирова-
     ние).
tms_cstime
     время, затраченное порожденными процессами  в системной фазе:  оно  равно  сумме
     всех tms_stime и tms_cstime порожденных процессов (рекурсивное суммирование).
real_time
     время, соответствующее астрономическому времени  системы.   Имеет  смысл  мерять
     только их разность.
Вот пример программы:

    #include 
    #include      /* _SC_CLK_TCK */
    #include      /* SIGALRM */
    #include    /* не используется */
    #include   /* struct tms */

    struct tms tms_stop,  tms_start;
    clock_t    real_stop, real_start;

    clock_t HZ;     /* число ticks в секунде */

А. Богатырев, 1992-95                  - 204 -                              Си в UNIX

    /* Засечь время момента старта процесса */
    void hello(void){
            real_start = times(&tms_start);
    }
    /* Засечь время окончания процесса */
    void bye(int n){
            real_stop = times(&tms_stop);
    #ifdef CRONO
            /* Разность времен */
            tms_stop.tms_utime -= tms_start.tms_utime;
            tms_stop.tms_stime -= tms_start.tms_stime;
    #endif

            /* Распечатать времена */
            printf("User   time          = %g seconds [%lu ticks]\n",
              tms_stop.tms_utime / (double)HZ, tms_stop.tms_utime);
            printf("System time          = %g seconds [%lu ticks]\n",
              tms_stop.tms_stime / (double)HZ, tms_stop.tms_stime);
            printf("Children user   time = %g seconds [%lu ticks]\n",
              tms_stop.tms_cutime / (double)HZ, tms_stop.tms_cutime);
            printf("Children system time = %g seconds [%lu ticks]\n",
              tms_stop.tms_cstime / (double)HZ, tms_stop.tms_cstime);
            printf("Real time            = %g seconds [%lu ticks]\n",
              (real_stop - real_start) / (double)HZ, real_stop - real_start);
            exit(n);
    }

    /* По сигналу SIGALRM - завершить процесс */
    void onalarm(int nsig){
            printf("Выход #%d ================\n", getpid());
            bye(0);
    }
    /* Порожденный процесс */
    void dochild(int n){
            hello();
            printf("Старт #%d ================\n", getpid());
            signal(SIGALRM, onalarm);

            /* Заказать сигнал SIGALRM через 1 + n*3 секунд */
            alarm(1 + n*3);

            for(;;){}       /* зациклиться в user mode */
    }

А. Богатырев, 1992-95                  - 205 -                              Си в UNIX

    #define NCHLD 4
    int main(int ac, char *av[]){
            int i;

            /* Узнать число тиков в секунде */
            HZ = sysconf(_SC_CLK_TCK);
            setbuf(stdout, NULL);

            hello();
            for(i=0; i < NCHLD; i++)
                    if(fork() == 0)
                            dochild(i);
            while(wait(NULL) > 0);
            printf("Выход MAIN =================\n");
            bye(0);
            return 0;
    }

и ее выдача:

    Старт #3883 ================
    Старт #3884 ================
    Старт #3885 ================
    Старт #3886 ================
    Выход #3883 ================
    User   time          = 0.72 seconds [72 ticks]
    System time          = 0.01 seconds [1 ticks]
    Children user   time = 0 seconds [0 ticks]
    Children system time = 0 seconds [0 ticks]
    Real time            = 1.01 seconds [101 ticks]
    Выход #3884 ================
    User   time          = 1.88 seconds [188 ticks]
    System time          = 0.01 seconds [1 ticks]
    Children user   time = 0 seconds [0 ticks]
    Children system time = 0 seconds [0 ticks]
    Real time            = 4.09 seconds [409 ticks]
    Выход #3885 ================
    User   time          = 4.41 seconds [441 ticks]
    System time          = 0.01 seconds [1 ticks]
    Children user   time = 0 seconds [0 ticks]
    Children system time = 0 seconds [0 ticks]
    Real time            = 7.01 seconds [701 ticks]
    Выход #3886 ================
    User   time          = 8.9 seconds [890 ticks]
    System time          = 0 seconds [0 ticks]
    Children user   time = 0 seconds [0 ticks]
    Children system time = 0 seconds [0 ticks]
    Real time            = 10.01 seconds [1001 ticks]
    Выход MAIN =================
    User   time          = 0.01 seconds [1 ticks]
    System time          = 0.04 seconds [4 ticks]
    Children user   time = 15.91 seconds [1591 ticks]
    Children system time = 0.03 seconds [3 ticks]
    Real time            = 10.41 seconds [1041 ticks]

Обратите внимание, что 72+188+441+890=1591 (поле tms_cutime для main).

6.2.12.  Еще одна программа: хронометрирование выполнения другой программы.   Пример:
timer ls -l

А. Богатырев, 1992-95                  - 206 -                              Си в UNIX

    /* Хронометрирование выполнения программы */
    #include 
    #include 
    #include 

    extern errno;

    typedef struct _timeStamp {
            clock_t real_time;
            clock_t cpu_time;
            clock_t child_time;
            clock_t child_sys, child_user;
    } TimeStamp;

    TimeStamp TIME(){
            struct tms tms;
            TimeStamp  st;

            st.real_time  = times(&tms);
            st.cpu_time   = tms.tms_utime +
                            tms.tms_stime +
                            tms.tms_cutime +
                            tms.tms_cstime;
            st.child_time = tms.tms_cutime +
                            tms.tms_cstime;
            st.child_sys  = tms.tms_cstime;
            st.child_user = tms.tms_cutime;
            return st;
    }

    void PRTIME(TimeStamp start, TimeStamp stop){
            clock_t HZ = sysconf(_SC_CLK_TCK);
            clock_t real_time  = stop.real_time  - start.real_time;
            clock_t cpu_time   = stop.cpu_time   - start.cpu_time;
            clock_t child_time = stop.child_time - start.child_time;

            printf("%g real, %g cpu, %g child (%g user, %g sys), %ld%%\n",
                    real_time       / (double)HZ,
                    cpu_time        / (double)HZ,
                    child_time      / (double)HZ,
                    stop.child_user / (double)HZ,
                    stop.child_sys  / (double)HZ,
                    (child_time * 100L) / (real_time ? real_time : 1)
            );
    }

А. Богатырев, 1992-95                  - 207 -                              Си в UNIX

    TimeStamp start, stop;

    int main(int ac, char *av[]){
            char *prog = *av++;
            if(*av == NULL){
                    fprintf(stderr, "Usage: %s command [args...]\n", prog);
                    return(1);
            }
            start = TIME();
            if(fork() == 0){
                    execvp(av[0], av);
                    perror(av[0]);
                    exit(errno);
            }
            while(wait(NULL) > 0);
            stop = TIME();
            PRTIME(start, stop);
            return(0);
    }

6.3.  Свободное место на диске.

6.3.1.  Системный вызов ustat() позволяет узнать количество свободного места в файло-
вой системе, содержащей заданный файл (в примере ниже - текущий каталог):

    #include 
    #include 
    #include 
    struct stat st; struct ustat ust;
    void main(int ac, char *av[]){
         char *file = (ac==1 ? "." : av[1]);
         if( stat(file, &st) < 0) exit(1);
         ustat(st.st_dev, &ust);
         printf("На диске %*.*s\n"
           "%ld свободных блоков (%ld Кб)\n"
           "%d свободных I-узлов\n",
         sizeof ust.f_fname, sizeof ust.f_fname,
         ust.f_fname, /* название файловой системы (метка) */
         ust.f_tfree, /* блоки по 512 байт */
        (ust.f_tfree * 512L) / 1024,
         ust.f_tinode );
    }

Обратите внимание на запись длинной строки в printf: строки, перечисленные последова-
тельно, склеиваются ANSI C компилятором в одну длинную строку:

    char s[] = "This is"  " a line "  "of words";
            совпадает с
    char s[] = "This is a line of words";

6.3.2.  Более правильно, однако, пользоваться сисвызовом statvfs - статистика по вир-
туальной  файловой  системе.  Рассмотрим его в следующем примере: копирование файла с
проверкой на наличие свободного места.

А. Богатырев, 1992-95                  - 208 -                              Си в UNIX

    #include 
    #include 
    #include 
    #include 
    #include               /* O_RDONLY */
    #include 
    #include 
    #include 
    #include           /* MAXPATHLEN */

    char *progname;                 /* имя программы */

    void error(char *fmt, ...){
            va_list args;

            va_start(args, fmt);
            fprintf(stderr, "%s: ", progname);
            vfprintf(stderr, fmt, args);
            fputc('\n', stderr);
            va_end(args);
    }

    int copyFile(char *to, char *from){       /* куда, откуда */
            char newname[MAXPATHLEN+1];
            char answer[20];
            struct stat stf, stt;
            int fdin, fdout;
            int n, code = 0;
            char iobuf[64 * 1024];
            char *dirname = NULL, *s;

            if((fdin = open(from, O_RDONLY)) < 0){
                    error("Cannot read %s", from);
                    return (-1);
            }
            fstat(fdin, &stf);
            if((stf.st_mode & S_IFMT) == S_IFDIR){
                    close(fdin);
                    error("%s is a directory", from);
                    return (-2);
            }

А. Богатырев, 1992-95                  - 209 -                              Си в UNIX

            if(stat(to, &stt) >= 0){
                    /* Файл уже существует */

                    if((stt.st_mode & S_IFMT) == S_IFDIR){
                            /* И это каталог */
Предыдущая страница Следующая страница
1 ... 32 33 34 35 36 37 38  39 40 41 42 43 44 45 ... 87
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 

Реклама