скачать рефераты
  RSS    

Меню

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

скачать рефераты

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

     соответствует fd     0         1        2

     связан с        клавиатурой     дисплеем

    #include <stdio.h>

    main(ac, av) char **av; {

      execl("/bin/sleep", "Take it easy", "1000", NULL);

    }

Эти каналы достаются процессу "в наследство" от запускающего процесса и связаны с дисплеем и клавиатурой, если только не были перенаправлены. Кроме того, программа может сама явно открывать файлы (при помощи open, creat, pipe, fopen). Всего программа может одновременно открыть до определенное количество  файлов в зависииости от настройки ядра.

d) Процесс имеет уникальный номер, который он может узнать вызовом

       int pid = getpid();

а также узнать номер "родителя" вызовом

       int ppid = getppid();

Процессы могут по этому номеру посылать друг другу сигналы:

       kill(pid /* кому */, sig /* номер сигнала */);

и реагировать на них

       signal (sig /*по сигналу*/, f /*вызывать f(sig)*/);

e) Существуют и другие средства коммуникации процессов: семафоры, сообщения, общая память, сетевые коммуникации.

f) Существуют некоторые другие параметры (контекст) процесса: например, его текущий каталог, который достается в наследство от процесса-"родителя", и может быть затем изменен системным вызовом

       chdir(char *имя_нового_каталога);

У каждого процесса есть свой собственный текущий рабочий каталог. К "прочим" характеристикам отнесем также: управляющий терминал; группу процессов (pgrp); идентификатор (номер) владельца процесса (uid), идентификатор группы владельца (gid), реакции и маски, заданные на различные сигналы; и.т.п.

g) Издания других запросов (системных вызовов) к операционной системе ("богу") для выполнения различных "внешних" операций.

h) Все остальные действия происходят внутри процесса и никак не влияют на другие процессы и устройства ("миры"). В частности, один процесс НИКАК не может получить доступ к памяти другого процесса, если тот не позволил ему это явно (механизм shared memory); адресные пространства процессов независимы и изолированы (равно и пространство ядра изолировано от памяти процессов).

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

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

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

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

    }

   

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

    #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 используют много разных механизмов взаимодействия. Одним из них являются сигналы.

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

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


Новости

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

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

Пока нет

Новости в Twitter и Facebook

  скачать рефераты              скачать рефераты

Новости

скачать рефераты

© 2010.