рефераты

рефераты

 
 
рефераты рефераты

Меню

Реферат: Interprocess Communication рефераты

            char Data[256]; /* сообщение */

          } Message;

int main()

{ key_t key;  int msgid;  char str[256];

 key=ftok("/usr/mash",'s');   /*получаем уникальный ключ, однозначно определяющий доступ к ресурсу                                                         данного типа */

 msgid=msgget(key, 0666 | IPC_CREAT);  /*создаем очередь сообщений , 0666 определяет права доступа */

 for(;;) {                                            /* запускаем вечный цикл */

            gets(str);                                          /* читаем из стандартного ввода строку */

            strcpy(Message.Data, str);                /* и копируем ее в буфер сообщения */

            switch(str[0]){

                        case 'a':

                        case 'A': Message.mtype=1;  /* устанавливаем тип и посылаем сообщение в очередь*/

                                      msgsnd(msgid, (struct msgbuf*) (&Message), strlen(str)+1, 0);

                                      break;

                        case 'b':

                        case 'B': Message.mtype=2;

                                      msgsnd(msgid, (struct msgbuf*) (&Message), strlen(str)+1, 0);

                                      break;

                        case q':

                        case 'Q': Message.mtype=1;

                                      msgsnd(msgid, (struct msgbuf*) (&Message), strlen(str)+1, 0);

                                      Message.mtype=2;

                                      msgsnd(msgid, (struct msgbuf*) (&Message), strlen(str)+1, 0);

                                      sleep(10);                    /* ждем получения сообщений процессами А и В */

                                      msgctl(msgid, IPC_RMID, NULL); /* уничтожаем очередь*/

                                      exit(0);

                        default: break;

}

 }

}

Процесс-приемник А   /* процесс В аналогичен с точностью до четвертого параметра в msgrcv */

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/message.h>

#include <stdio.h>

struct {  long mtype;

            char Data[256];

          } Message;

int main()

же параметрам

Семафоры

С точки зрения тех проблем, с которыми мы знакомимся, семафоры - это есть вполне законное и существующее понятие. Впервые ввел это понятие достаточно известный ученый Дейкстра. Семафор - это некоторый объект, который имеет целочисленное значение S, и с которым связаны две операции:  V(S) и P(S).

Операция P(S) уменьшает значение семафора на 1, и если S³0 процесс продолжает работу. Если S<0, то процесс будет приостановлен и встанет в очередь ожидания, связанную с семафором S, до тех пор, пока его не освободит другой процесс.

Операция V(S) увеличивает семафор на 1. Если S>0, то процесс продолжает выполнение. Если S£0, то разблокируется один из процессов, ожидающий в очереди процессов, связанной с семафором S, и текущий процесс продолжит выполнение.

Считается, что операции P(S) и V(S) неделимы. Это означает, что выполнение этих операций не может прерваться до их завершения. Т.е. если семафор реализован в системе, то это должна быть одна команда.

Частным случаем продекларированного семафора является двоичный семафор, максимальное значение которого равно единичке. При этом значение S может быть равно 1, это означает, что ни один из процессов (связанных с этим семафором) не находится в критическом участке. При S=0 один из процессов находится в критическом участке {вот-вот попадет в очередь}, а другой нормально функционирует. При S= -1 один из процессов находится в критическом участке, а другой заблокирован и находится в очереди.

На самом деле двоичные семафоры наиболее часто находили применение в аппаратных реализациях, например, в многомашинных комплексах с общей оперативной памятью.

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

Давайте рассмотрим средства, предоставляемые системой IPC, для создания, управления и взаимодействия с семафорами.

int semget(key_t key, int n, int flags);

int semop(int semid, struct sembuf * sops, int n);

struct sembuf{

 short sem_num;           /* номер семафора в массиве семафоров */

 short sem_op;  /* код операции, которую надо выполнить */

 short sem_flg;  /* флаги */

 }

Первый параметр функции semget - ключ, второй - количество семафоров (длина массива семафоров) и третий параметр - флаги. Через флаги можно определить права доступа и те операции, которые должны выполняться (открытие семафора, проверка, и т.д.). Функция  semget возвращает целочисленный идентификатор созданного разделяемого ресурса, либо -1, если ресурс не удалось создать (причина - в errno).

Первый параметр функции semop - идентификатор семафора, второй - указатель на структуру sembuf и третий параметр - количество указателей на эту структуру, которые передаются функцией semop. В структуре содержится вся информация о необходимом действии.

Поле операции интерпретируется следующим образом. Пусть значение семафора с номером sem_num равно sem_val. В этом случае, если значение операции не равно нулю, то оценивается значение суммы (sem_val + sem_op). Если эта сумма больше либо равна нулю, то значение данного семафора устанавливается равным сумме предыдущего значения и кода операции. Если эта сумма меньше нуля, то действие процесса будет приостановлено до наступления одного из следующих событий:

1.   Значение суммы (sem_val + sem_op) станет больше либо равно нулю.

2.   Пришел какой-то сигнал. (Значение semop в этом случае будет равно -1).

 

Если код операции semop равен нулю, то процесс будет ожидать обнуления семафора. Если мы обратились к функции semop с нулевым кодом операции, а к этому моменту значение семафора стало равным нулю, то никакого ожидания не происходит.

Рассмотрим третий параметр - флаги. Если третий параметр равен нулю, то это означает, что флаги не используются. Флагов имеется большое количество в т.ч. IPC_NOWAIT (при этом флаге во всех тех случаях, когда мы говорили, что процесс будет ожидать, он не будет ожидать).

Обращаю ваше внимание, что за одно обращение к функции semop можно передать n структур и соответственно выполнить действия с n семафорами из этого массива. Если в этой последовательности будут присутствовать две разных операции с одни семафором, то скорее всего, выполнится последняя.

Функция управления массивом семафоров.

int semctl(int id, int sem_num, int cmd, union sem_buf arg);

            Первый параметр - идентификатор, второй - номер семафора в массиве, с которым мы будем выполнять команду cmd из третьего параметра. Последний параметр - некоторое объединение типа sembuf.

            Команды могут быть традиционные (IPC_RMID), и кроме них есть другие команды, и среди них IPC_SET, которая устанавливает значение семафора, при этом значение передается через объединение arg. При установке семафора этой функцией, задержек, которые определяют основной смысл работы семафора, не будет.

           

            Вот те функции, которые предназначены для работы с семафорами. Пример работы с семафорами рассмотрим на следующей лекции.


Лекция №19

            Мы остановились на средствах синхронизации доступа к разделяемым ресурсам - на семафорах. Мы говорили о том, что семафоры - это тот формализм, который изначально был предложен ученым в области компьютерных наук Дейкстрой, поэтому часто в литературе их называют семафорами Дейкстры. Семафор - это есть некоторая переменная и над ней определены операции P и V. Одна позволяет увеличивать значение семафора, другая - уменьшать. Причем с этими изменениями связаны возможности блокировки процесса и разблокировки процесса. Обратим внимание, что речь идет о неразделяемых операциях, то есть тех операциях, которые не могут быть прерваны, если начались. То есть не может быть так, чтобы во время выполнения P или V пришло прерывание, и система передала управление другому процессу. Это принципиально. Поэтому семафоры можно реализовывать программно, но при этом мы должны понимать, что эта реализация не совсем корректна, так как

1) программа пишется человеком, а прерывается аппаратурой, отсюда возможно нарушение неразделяемости;

2) в развитых вычислительных системах, которые поддерживают многопроцессорную обработку или обработку разделяемых ресурсов в рамках одного процесса, предусмотрены семафорные команды, которые фактически реализовывают операции P и V. Это важно.

            Мы говорили о реализации семафоров в Unix в системе IPC и о том, что эта система позволяет создать разделяемый ресурс “массив семафоров”, соответственно, как и к любому разделяемому ресурсу, к этому массиву может быть обеспечен доступ со стороны различных процессов, обладающих нужными правами и ключом к данному ресурсу.

            Каждый элемент массива - семафор. Для управления работой семафора есть функции:

A.         semop, которая позволяет реализовывать операции P и V над одним или несколькими семафорами;

B.         segctl - управление ресурсом. Под управлением здесь понимается три вещи:

1.          - получение информации о состоянии семафора;

2.          - возможность создания некоторого режима работы семафора, уничтожение семафора;

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

            Давайте приведем пример, которым попытаемся проиллюстрировать использование семафоров на практике.

            Наша программа будет оперировать с разделяемой памятью.

            1 процесс - создает ресурсы “разделяемая память” и “семафоры”, далее он начинает принимать строки со стандартного ввода и записывает их в разделяемую память.

            2 процесс - читает строки из разделяемой памяти.

            Таким образом мы имеем критический участок в момент, когда один процесс еще не дописал строку, а другой ее уже читает. Поэтому следует установить некоторые синхронизации и задержки.

            Следует отметить, что, как и все программы, которые мы приводим, эта программа не совершенна. Но не потому, что мы не можем ее написать (в крайнем случае можно попросить своих аспирантов или студентов), а потому, что совершенная программа будет занимать слишком много места, и мы сознательно делаем некоторые упрощения. Об этих упрощениях мы постараемся упоминать.

1й процесс:

#include <stdio.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

int main(void)

{           key_t key;

            int semid, shmid;

            struct sembuf sops;

            char *shmaddr;

            char str[256];

            key = ftok(“/usr/mash/exmpl”,’S’);                       /* создаем уникальный ключ */

            semid = semget(key,1,0666 | IPC_CREAT); /* создаем один семафор с определенными                                                                                                                                   правами доступа */

shmid = shmget(key,256, 0666 | IPC_CREAT); /*создаем разделяемую память на 256                                                                                                                                       элементов */

            shmaddr = shmat(shmid, NULL, 0); /* подключаемся к разделу памяти, в shaddr - указатель на                                                                                                            буфер с разделяемой памятью*/

            semctl(semid,0,IPC_SET, (union semun) 0); /*инициализируем семафор со значением 0 */

            sops.sem_num = 0; sops.sem_flg = 0;

            /* запуск бесконечного цикла */

            while(1) { printf(“Введите строку:”);

                        if ((str = gets(str)) == NULL) break;

                        sops.sem_op=0;                                   /* ожидание обнуления семафора */

                        semop(semid, &sops, 1);

                        strcpy(shmaddr, str);                             /* копируем строку в разд. память */

                        sops.sem_op=3;                                   /* увеличение семафора на 3 */

                        semop(semid, &sops, 1);

            }

            shmaddr[0]=’Q’;                                                /* укажем 2ому процессу на то, */

            sops.sem_op=3;                                               /* что пора завершаться */

            semop(semid, &sops, 1);

            sops.sem_op = 0;                                             /* ждем, пока обнулится семафор */

            semop(semid, &sops, 1);

            shmdt(shmaddr);                                               /* отключаемся от разд. памяти */

            semctl(semid, 0, IPC_RMID, (union semun) 0);    /* убиваем семафор */

            shmctl(shmid, IPC_RMID, NULL);                       /* уничтожаем разделяемую память */

            exit(0);

}

               

2й процесс:

/* здесь нам надо корректно определить существование ресурса, если он есть - подключиться, если нет - сделать что-то еще, но как раз этого мы делать не будем */

#include <stdio.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

int main(void)

{           key_t key; int semid;

            struct sembuf sops;

            char *shmaddr;

            char st=0;

            /* далее аналогично предыдущему процессу  - инициализации ресурсов */

            semid = semget(key,1,0666 | IPC_CREAT);

            shmid = shmget(key,256, 0666 | IPC_CREAT);

            shmaddr = shmat(shmid, NULL, 0);

            sops.sem_num = 0; sops.sem_flg = 0;

            /* запускаем цикл */

            while(st!=’Q’) {

                        printf(“Ждем открытия семафора \n”);

                                                                        /* ожидание положительного значения семафора */

                        sops.sem_op=-2;

                        semop(semid, &sops, 1);

                        /* будем ожидать, пока “значение семафора”+”значение sem_op” не перевалит за 0, то                                                                                                          есть если придет “3”, то “3-2=1” */

                        /* теперь значение семафора равно 1 */

                        st = shmaddr[0];

{           /*критическая секция - работа с разделяемой памятью - в этот момент первый                                              процесс к разделяемой памяти доступа не имеет*/}

                                                            /*после работы - закроем семафор*/

                        sem.sem_op=-1;

                        semop(semid, &sops, 1);

                                                                        /* вернувшись в начало цикла мы опять будем ждать,                                                                         пока значение семафора не станет больше нуля */

}

            shmdt(shmaddr); /* освобождаем разделяемую память и выходим */

            exit(0);

}

            Это программа, состоящая из двух процессов, синхронно работающих с разделяемой памятью. Понятно, что при наличии интереса можно работать и с сообщениями.

           

            На этом мы заканчиваем большую и достаточно важную тему организации взаимодействия процессов в системе.

            Наша самоцель - не изучение тех средств, которые предоставляет Unix, а изучение принципов, которые предоставляет система для решения тех или иных задач, так как другие ОС предоставляют аналогичные или похожие средства управления процессами.

Системы программирования.

Система программирования - это комплекс программных средств, обеспечивающих поддержку технологий проектирования, кодирования, тестирования и отладки, называется системой программирования

            Этап проектирования

            Было сказано, что на сегодняшний день достаточно сложно, а практически невозможно создавать программное обеспечение без этапа проектирования, такого же долгого, нудного и детального периода, который проходит во время проектирования любого технического объекта. Следует понять, что те программы, которые пишутся студентами в качестве практических и дипломных задач не являются по сути дела программами - это игрушки, так как их сложность невелика, объемы незначительны и такого рода программы можно писать слегка. Реальные же программы так не создаются, так же, как и не создаются сложные технические объекты. Никто никогда не может себе представить, чтобы какая-нибудь авиационная компания продекларировала создание нового самолета и дала команду своим заводам слепить лайнер с такими-то параметрами. Так не бывает. Каждый из элементов такого объекта, как самолет, проходит сложный этап проектирования.

            Например, фирма Боинг подняла в воздух самолет “Боинг-777”, замечательность этого факта заключается в том, что самолет взлетел без предварительной продувки в аэродинамической трубе. Это означает, что весь самолет был спроектирован и промоделирован на программных моделях, и это проектирование и моделирование было настолько четким и правильным, что позволило сразу же поднять самолет в воздух. Для справки - продувка самолета в аэродинамической трубе стоит сумасшедшие деньги.

Страницы: 1, 2, 3, 4, 5