RSS    

   Реферат: Администрирование локальных сетей

Поведение всех программ в системе вытекает из поведения системных вызовов, которыми они пользуются. Даже то, что UNIX является многозадачной системой, непосредственно вытекает из наличия системных вызовов fork, exec, wait и спецификации их функционирования! То же можно сказать про язык Си - мобильность программы зависит в основном от набора используемых в ней библиотечных функций (и, в меньшей степени, от диалекта самого языка, который должен удовлетворять стандарту на язык Си). Если две разные системы предоставляют все эти функции (которые могут быть по-разному реализованы, но должны делать одно и то же), то программа будет компилироваться и работать в обоих системах, более того, работать в них одинаково.

Сам термин "системный вызов" как раз означает "вызов системы для выполнения действия", т.е. вызов функции в ядре системы. Ядро работает в привелегированном режиме, в котором имеет доступ к некоторым системным таблицам*, регистрам и портам внешних устройств и диспетчера памяти, к которым обычным программам доступ аппаратно запрещен (в отличие от MS DOS, где все таблицы ядра доступны пользовательским программам, что создает раздолье для вирусов). Системный вызов происходит в 2 этапа: сначала в пользовательской программе вызывается библиотечная функция-"корешок", тело которой написано на ассемблере и содержит команду генерации программного прерывания. Это - главное отличие от нормальных Си-функций - вызов по прерыванию. Вторым этапом является реакция ядра на прерывание:

1.    переход в привелегированный режим;

2.    разбирательство, КТО обратился к ядру, и подключение u-area этого процесса к адресному пространству ядра (context switching);

3.    извлечение аргументов из памяти запросившего процесса;

4.    выяснение, ЧТО же хотят от ядра (один из аргументов, невидимый нам - это номер системного вызова);

5.    проверка корректности остальных аргументов;

6.    проверка прав процесса на допустимость выполнения такого запроса;

7.    вызов тела требуемого системного вызова - это обычная Си-функция в ядре;

8.    возврат ответа в память процесса;

9.    выключение привелегированного режима;

10.   возврат из прерывания.

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

Большинство системных вызовов возвращают в программу в качестве своего значения признак успеха: 0 - все сделано, (-1) - сисвызов завершился неудачей; либо некоторое содержательное значение при успехе (вроде дескриптора файла в open(), и (-1) при неудаче. В случае неудачного завершения в предопределенную переменную errno заносится номер ошибки, описывающий причину неудачи (коды ошибок предопределены, описаны в include-файле <errno.h> и имеют вид Eчтото). Заметим, что при УДАЧЕ эта переменная просто не изменяется и может содержать любой мусор, поэтому проверять ее имеет смысл лишь в случае, если ошибка действительно произошла:

    #include <errno.h>      /* коды ошибок */

    extern int errno;

    extern char *sys_errlist[];

    int value;

    if((value = sys_call(...)) < 0 ){

       printf("Error:%s(%d)\n", sys_errlist[errno],

                                errno );

       exit(errno); /* принудительное завершение программы */

    }

Предопределенный массив sys_errlist, хранящийся в стандартной библиотеке, содержит строки-расшифровку смысла ошибок (по-английски). Посмотрите описание функции per- ror().

Время в UNIX.

Ниже приведены примеры как узнавать время:

. В системе UNIX время обрабатывается и хранится именно в виде числа секунд; в частности текущее астрономическое время можно узнать системным вызовом

    #include <sys/types.h>

    #include <time.h>

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

Функция

    struct tm *tm = localtime( &t );

разлагает число секунд на отдельные составляющие, содержащиеся в 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 ] );

Часто бывает нужда передавать значения времени в одной строке

Вот пример программы которая преобразовывает в ремя в такой формат:

/* Mon Jun 12 14:31:26 2000 */

#include <stdio.h>

#include <time.h>

main()     { /* команда date */

time_t t = time(NULL);

char *s = ctime(&t);

printf("%s", s);

}

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

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

    #include <sys/types.h>

    #include <signal.h>

    #include <sys/time.h>

    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;

            /* Сохраняем прежнюю реакцию на сигнал SIGALRM в old_vec,

               заносим в качестве новой реакции do_nothing()

             */

            new_vec.sa_handler = do_nothing;

            sigemptyset(&new_vec.sa_mask);

            new_vec.sa_flags = 0;

            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);

    }

   

Пример оспользования интервалов

Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51


Новости


Быстрый поиск

Группа вКонтакте: новости

Пока нет

Новости в Twitter и Facebook

                   

Новости

© 2010.