Главная · Поиск книг · Поступления книг · 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 ... 31 32 33 34 35 36 37  38 39 40 41 42 43 44 ... 87
        if( match(basename, find_PATTERN))
            printf("Level#%02d %s\n", level, fullname);
        if( !strcmp( basename, "core")){
            printf("Найден дамп %s, поиск прекращен.\n", fullname);
            return FAILURE;
        }
        return SUCCESS;
    }
    void find (char *root, char *pattern){
         find_PATTERN = pattern;
         walktree(root, find_check, NULL, find_check);
    }

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

    /* -------------------------------------------------------------- */
    #ifndef TREEONLY
    void main(int argc, char *argv[]){
    #ifdef FIND
         if(argc != 3){ fprintf(stderr, "Arg count\n"); exit(1); }
         find(argv[1], argv[2]);
    #else
    # ifdef RM_REC
         for(argv++; *argv; argv++)
             recrmdir(*argv);
    # else
         du( argc == 1 ? "." : argv[1] );
         printf( "%ld килобайт в %ld файлах.\n", size, nfiles );
         printf( "%ld каталогов.\n", ndirs );
    # endif
    #endif
         exit(0);
    }
    #endif /*TREEONLY*/

6.1.6.  Используя предыдущий алгоритм, напишите  программу  рекурсивного  копирования
поддерева  каталогов в другое место. Для создания новых каталогов используйте систем-
ный вызов
    mkdir(имя_каталога, коды_доступа);

6.1.7.  Используя тот же алгоритм, напишите программу удаления каталога, которая уда-
ляет  все  файлы  в  нем и, рекурсивно, все его подкаталоги. Таким образом, удаляется
дерево каталогов.  В UNIX подобную операцию выполняет команда
    rm -r имя_каталога_корня_дерева

6.1.8.  Используя все тот же алгоритм обхода, напишите аналог команды  find,  который
будет позволять:
-    находить все файлы, чьи имена удовлетворяют заданному шаблону (используйте функ-
     цию match() из главы "Текстовая обработка");
-    находить все выполняемые файлы: обычные файлы S_IFREG, у которых

            (st.st_mode & 0111) != 0

     Как уже ясно, следует пользоваться вызовом stat для проверки каждого файла.

6.2.  Время в UNIX.

6.2.1.  Напишите функцию, переводящую год, месяц, день,  часы,  минуты  и  секунды  в
число  секунд, прошедшее до указанного момента с 00 часов 00 минут 00 секунд 1 Января
1970 года.  Внимание: результат должен иметь тип long (точнее time_t).
     Эта функция облегчит вам сравнение двух моментов времени, заданных в  общеприня-
том  "человеческом"   формате,  поскольку  сравнить два long числа гораздо проще, чем
сравнивать по очереди годы, затем, если они равны - месяцы, если месяцы равны - даты,
и.т.д.;  а  также облегчит измерение интервала между двумя событиями - он вычисляется
просто как разность двух чисел.  В  системе  UNIX  время  обрабатывается  и  хранится
именно  в  виде  числа секунд; в частности текущее астрономическое время можно узнать
системным вызовом

    #include 
    #include 
    time_t t = time(NULL);  /* time(&t); */

Функция

    struct tm *tm = localtime( &t );

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

разлагает число секунд на отдельные составляющие, содержащиеся в int-полях структуры:

    tm_year  год           (надо прибавлять 1900)
    tm_yday  день в году   0..365
    tm_mon   номер месяца  0..11 (0 - Январь)
    tm_mday  дата месяца   1..31
    tm_wday  день недели   0..6  (0 - Воскресенье)
    tm_hour  часы          0..23
    tm_min   минуты        0..59
    tm_sec   секунды       0..59

Номера месяца и дня недели начинаются с  нуля,  чтобы  вы  могли  использовать  их  в
качестве индексов:

    char *months[] = { "Январь", "Февраль", ..., "Декабрь" };
    printf( "%s\n", months[ tm->tm_mon ] );

Пример использования этих функций есть в приложении.
     Установить время в системе может суперпользователь вызовом
     stime(&t);

6.2.2.  Напишите  функцию  печати  текущего  времени  в  формате  ЧЧ:ММ:СС ДД-МЕС-ГГ.
Используйте системный вызов time() и функцию localtime().
     Существует стандартная функция ctime(), которая печатает время в формате:

    /* Mon Mar 25 18:56:36 1991 */
    #include 
    #include 
    main(){ /* команда date */
            time_t t = time(NULL);
            char *s  = ctime(&t);
            printf("%s", s);
    }

Обратите внимание, что строка s уже содержит на конце символ '\n'.

6.2.3.  Структура stat, заполняемая системным  вызовом  stat(),  кроме  прочих  полей
содержит  поля типа time_t st_ctime, st_mtime и st_atime - время последнего изменения
содержимого I-узла файла, время последнего изменения файла и время последнего доступа
к файлу.
-    Поле st_ctime изменяется (устанавливается равным текущему астрономическому  вре-
     мени)  при  применении к файлу вызовов creat, chmod, chown, link, unlink, mknod,
     utime[*], write (т.к. изменяется длина файла); Это поле следует рассматривать  как
     время модификации прав доступа к файлу;
-    st_mtime - write, creat, mknod, utime; Это поле следует рассматривать как  время
     модификации содержимого файла (данных);
-    st_atime - read, creat, mknod, utime; Это поле следует рассматривать  как  время
     чтения содержимого файла (данных).
Модифицируйте функцию typeOf(), чтобы она печатала еще и эти даты.

____________________
   [*] Время модификации файла можно изменить на текущее  астрономическое  время  и  не
производя записи в файл.  Для этого используется вызов

    utime(имяФайла, NULL);

Он используется для взаимодействия с программой make -  в  команде  touch.   Изменить
время можно только своему файлу.

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

6.2.4.  Напишите аналог команды ls -tm, выдающей список имен  файлов  текущего  ката-
лога,  отсортированный  по  убыванию  поля st_mtime, то есть недавно модифицированные
файлы выдаются первыми.  Для каждого прочитанного  из  каталога  имени  надо  сделать
stat; имена файлов и времена следует сохранить в массиве структур, а затем отсортиро-
вать его.

6.2.5.  Напишите аналогичную программу, сортирующую файлы в  порядке  возрастания  их
размера (st_size).

6.2.6.  Напишите аналог команды ls -l, выдающий имена файлов каталога и их коды  дос-
тупа в формате rwxrw-r--.  Для получения кодов доступа используйте вызов stat

    stat( имяФайла, &st);
    кодыДоступа = st.st_mode & 0777;

Для изменения кодов доступа используется вызов

    chmod(имя_файла, новые_коды);

Можно изменять коды доступа, соответствующие битовой маске

    0777 | S_ISUID | S_ISGID | S_ISVTX

(смотри ).  Тип файла (см. функцию typeOf) не может быть изменен.   Изме-
нить коды доступа к файлу может только его владелец.
     Печатайте еще номер I-узла файла: поле d_ino каталога либо поле st_ino структуры
stat.

6.2.7.  Вот программа, которая каждые 2 секунды проверяет - не изменилось ли содержи-
мое текущего каталога:

    #include 
    #include 
    extern char *ctime();
    main(){
       time_t last; struct stat st;
       for( stat(".", &st), last=st.st_mtime; ; sleep(2)){
            stat(".", &st);
            if(last != st.st_mtime){
               last  = st.st_mtime;
    printf("Был создан или удален какой-то файл: %s",
                       ctime(&last));
            }
       }
    }

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

6.2.8.  Напишите по аналогии программу, которая выдает сообщение, если указанный вами
файл был кем-то прочитан, записан или удален. Вам следует отслеживать изменение полей
st_atime, st_mtime и значение stat() < 0 соответственно. Если файл удален - программа
завершается.

6.2.9.  Современные UNIX-машины имеют встроенные таймеры (как  правило  несколько)  с
довольно  высоким разрешением. Некоторые из них могут использоваться как "будильники"
с обратным отсчетом времени: в таймер загружается некоторое  значение;  таймер  ведет
обратный  отсчет, уменьшая загруженный счетчик; как только это время истекает - посы-
лается сигнал процессу, загрузившему таймер.

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

     Вот как, к примеру, выглядит функция задержки в микросекундах (миллионных  долях
секунды).   Примечание:  эту  функцию  не следует использовать вперемежку с функциями
sleep и alarm (смотри статью про них ниже, в главе про сигналы).

    #include 
    #include 
    #include 

    void do_nothing() {}

    /* Задержка на usec миллионных долей секунды (микросекунд) */
    void usleep(unsigned int usec) {

            struct itimerval        new, old;
            /*  struct itimerval  содержит поля:
                struct timeval    it_interval;
                struct timeval    it_value;

                Где struct timeval содержит поля:
                long    tv_sec;    -- число целых секунд
                long    tv_usec;   -- число микросекунд
             */
            struct sigaction        new_vec, old_vec;

            if (usec == 0) return;

            /* Поле tv_sec  содержит число целых секунд.
               Поле tv_usec содержит число микросекунд.

               it_value    - это время, через которое В ПЕРВЫЙ раз
                             таймер "прозвонит",
                             то есть пошлет нашему процессу
                             сигнал SIGALRM.

                             Время, равное нулю, немедленно остановит таймер.

               it_interval - это интервал времени, который будет загружаться
                             в таймер после каждого "звонка"
                             (но не в первый раз).

                             Время, равное нулю, остановит таймер
                             после его первого "звонка".
             */
            new.it_interval.tv_sec  = 0;
            new.it_interval.tv_usec = 0;
            new.it_value.tv_sec  = usec / 1000000;
            new.it_value.tv_usec = usec % 1000000;

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

            /* Сохраняем прежнюю реакцию на сигнал SIGALRM в old_vec,
               заносим в качестве новой реакции do_nothing()
             */
            new_vec.sa_handler = do_nothing;
            sigemptyset(&new_vec.sa_mask);
            new_vec.sa_flags = 0;

            sighold(SIGALRM);
            sigaction(SIGALRM, &new_vec, &old_vec);

            /* Загрузка интервального таймера значением new, начало отсчета.
             * Прежнее значение спасти в old.
             * Вместо &old можно также NULL - не спасать.
             */
            setitimer(ITIMER_REAL, &new, &old);

            /* Ждать прихода сигнала SIGALRM */
            sigpause(SIGALRM);

            /* Восстановить реакцию на SIGALRM */
            sigaction(SIGALRM, &old_vec, (struct sigaction *) 0);
            sigrelse(SIGALRM);

            /* Восстановить прежние параметры таймера */
            setitimer(ITIMER_REAL, &old, (struct itimerval *) 0);
    }

6.2.10.  Второй пример использования таймера  -  это  таймер,  отсчитывающий  текущее
время суток (а также дату).  Чтобы получить значение этого таймера используется вызов
функции gettimeofday

    #include 

    void main(){
            struct timeval timenow;

            gettimeofday(&timenow, NULL);
            printf("%u sec, %u msec\n",
                    timenow.tv_sec,
                    timenow.tv_usec
            );
            printf("%s", ctime(&timenow.tv_sec));
            exit(0);
    }

Поле tv_sec содержит число секунд, прошедшее с полуночи 1 января 1970 года до данного
Предыдущая страница Следующая страница
1 ... 31 32 33 34 35 36 37  38 39 40 41 42 43 44 ... 87
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 

Реклама