RSS    

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

    #include <stdio.h>

    #include <unistd.h>     /* _SC_CLK_TCK */

    #include <signal.h>     /* SIGALRM */

    #include <sys/time.h>   /* не используется */

    #include <sys/times.h>  /* struct tms */

    struct tms tms_stop,  tms_start;

    clock_t    real_stop, real_start;

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

    /* Засечь время момента старта процесса */

    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 */

    }

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

    }

Сигналы.

Процессы в UNIX используют много разных механизмов взаимодействия. Одним из них являются сигналы.

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

Схема с синхронными событиями очень распространена. Кассир сидит у кассы и ожидает, пока к нему в окошечко не заглянет клиент. Поезд периодически проезжает мимо светофора и останавливается, если горит красный. Функция Си пассивно "спит" до тех пор, пока ее не вызовут; однако она всегда готова выполнить свою работу (обслужить клиента). Такое ожидающее заказа (события) действующее лицо называется сервер. После выполнения заказа сервер вновь переходит в состояние ожидания вызова. Итак, если событие ожидается в специальном месте и в определенные моменты времени (издается некий вызов для ОПРОСА) - это синхронные события. Канонический пример - функция gets, которая задержит выполнение программы, пока с клавиатуры не будет введена строка. Большинство ожиданий внутри системных вызовов - синхронны. Ядро ОС выступает для программ пользователей в роли сервера, выполняющего сисвызовы (хотя и не только в этой роли - ядро иногда предпринимает и активные действия: передача процессора другому процессу через определенное время (режим разделения времени), убивание процесса при ошибке, и.т.п.).

Сигналы - это асинхронные события. Они приходят неожиданно, в любой момент времени - вроде телефонного звонка. Кроме того, их не требуется заказывать - сигнал процессу может поступить совсем без повода. Аналогия из жизни такова: человек сидит и пишет письмо. Вдруг его окликают посреди фразы - он отвлекается, отвечает на вопрос, и вновь продолжает прерванное занятие. Человек не ожидал этого оклика (быть может, он готов к нему, но он не озирался по сторонам специально). Кроме того, сигнал мог поступить когда он писал 5-ое предложение, а мог - когда 34-ое. Момент времени, в который произойдет прерывание, не фиксирован.

Сигналы имеют номера, причем их количество ограничено - есть определенный список допустимых сигналов. Номера и мнемонические имена сигналов перечислены в includeфайле <signal.h> и имеют вид SIGнечто. Допустимы сигналы с номерами 1..NSIG-1, где NSIG определено в этом файле. При получении сигнала мы узнаем его номер, но не узнаем никакой иной информации: ни от кого поступил сигнал, ни что от нас хотят. Просто "звонит телефон". Чтобы получить дополнительную информацию, наш процесс должен взять ее из другого известного места; например - прочесть заказ из некоторого файла, об имени которого все наши программы заранее "договорились". Сигналы процессу могут поступать тремя путями:

  • От другого процесса, который явно посылает его нам вызовом

         kill(pid, sig);

где pid - идентификатор (номер) процесса-получателя, а sig - номер сигнала. Послать сигнал можно только родственному процессу - запущенному тем же пользователем.

  • От операционной системы. Система может посылать процессу ряд сигналов, сигнализирующих об ошибках, например при обращении программы по несуществующему адресу или при ошибочном номере системного вызова. Такие сигналы обычно прекращают наш процесс.
  • От пользователя - с клавиатуры терминала можно нажимом некоторых клавиш послать сигналы SIGINT и SIGQUIT. Собственно, сигнал посылается драйвером терминала при получении им с клавиатуры определенных символов. Так можно прервать зациклившуюся или надоевшую программу.

Процесс-получатель должен как-то отреагировать на сигнал. Программа может:

  • проигнорировать сигнал (не ответить на звонок);
  • перехватить сигнал (снять трубку), выполнить какие-то действия, затем продолжить прерванное занятие;
  • быть убитой сигналом (звонок был подкреплен броском гранаты в окно);

В большинстве случаев сигнал по умолчанию убивает процесс-получатель. Однако процесс может изменить это умолчание и задать свою реакцию явно. Это делается вызовом signal:

    #include <signal.h>

    void (*signal(int sig, void (*react)() )) ();

Параметр react может иметь значение:

SIG_IGN

сигнал sig будет отныне игнорироваться. Некоторые сигналы (например SIGKILL) невозможно перехватить или проигнорировать.

SIG_DFL

восстановить реакцию по умолчанию (обычно - смерть получателя). имя_функции Например

          void fr(gotsig){ ..... }  /* обработчик */

          ... signal (sig, fr); ... /* задание реакции */

Тогда при получении сигнала sig будет вызвана функция fr, в которую в качестве аргумента системой будет передан номер сигнала, действительно вызвавшего ее gotsig==sig. Это полезно, т.к. можно задать одну и ту же функцию в качестве реакции для нескольких сигналов:

          ... signal (sig1, fr); signal(sig2, fr); ...

После возврата из функции fr() программа продолжится с прерванного места. Перед вызовом функции-обработчика реакция автоматически сбрасывается в реакцию по умолчанию SIG_DFL, а после выхода из обработчика снова восстанавливается в fr. Это значит, что во время работы функции-обработчика может прийти сигнал, который убьет программу.

Приведем список некоторых сигналов; полное описание посмотрите в документации. Колонки таблицы: G - может быть перехвачен; D - по умолчанию убивает процесс (k), игнорируется (i); C - образуется дамп памяти процесса: файл core, который затем может быть исследован отладчиком adb; F - реакция на сигнал сбрасывается; S - посылается обычно системой, а не явно.

    сигнал         G   D   C   F   S  смысл

    SIGTERM        +   k   -   +   -  завершить процесс

    SIGKILL        -   k   -   +   -  убить процесс

    SIGINT         +   k   -   +   -  прерывание с клавиш

    SIGQUIT        +   k   +   +   -  прерывание с клавиш

Страницы: 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.