
Основной процесс
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/message.h>
#include <stdio.h>
struct { long mtype; /* тип сообщения */
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()
{ key_t key; int msgid;
key=ftok("/usr/mash",'s'); /* получаем ключ по тем же параметрам */
msgid=msgget(key, 0666 | IPC_CREAT); /*создаем очередь сообщений */
for(;;) { /* запускаем вечный цикл */
msgrcv(msgid, (struct msgbuf*) (&Message), 256, 1, 0);
/* читаем сообщение с типом 1*/
if (Message.Data[0]='q' || Message.Data[0]='Q') break;
printf("%s",Message.Data);
}
exit(0);
}
Билет №20. Семафоры.
Семафор - некоторый объект, который имеет целочисленное значение S, и с которым связаны 2 или 3 операции. Одним из разделяемых ресурсов, который поддерживает система 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 - процесс не будет ожидать. Частным случаем является двоичный семафор, максимальное значение которого равно единичке. При этом значение 1, это означает, что ни один из процессов не находится в критическом участке. При S=0 один из процессов находится в критическом участке, а другой нормально функционирует. При S= -1 один из процессов находится в критическом участке, а другой заблокирован и находится в очереди.
int semctl(int id, int sem_num, int cmd, union sem_buf arg);
Первый параметр - идентификатор, второй - номер семафора в массиве, с которым мы будем выполнять команду cmd из третьего параметра. Последний параметр - некоторое объединение типа sembuf.
Команды: IPC_RMID, IPC_SET устанавливает значение семафора, при этом значение передается через объединение arg.
По Робачевскому: 1. Если semop>0 то он прибавляется к текущему знач. семафора. 2. Если semop=0, процесс ожидает обнуления семафора. 3. semop<0 - процесс ждет, пока не выполнится semop+semval>=0, и тогда semval+=semop.
Билет №25. Типы трансляторов. Проходы. Анализ.
Транслятор - это программа, которая переводит программу в нотации одного языка, в нотацию другого языка. Компилятор - это транслятор, который переводит программу из одного языка в нотацию машинного языка. Машинным языком может быть либо код конкретной машины, либо объектный код. Трансляторы могут быть интерпретаторами, т.е. совмещать анализ исходной программы с ее выполнением. Кросс-трансляторы. Кросс транслятор работает на инструментальной ЭВМ. Кросс-транслятор обеспечивает перевод программы в код вычислительной системы, отличной от инстр. ЭВМ. Та система, для которой генерируется код, называется объектной ЭВМ, тот код, который мы получаем, называется объектным кодом. Например, компьютеру, который управляет двигательной установкой самолета, совершенно не нужно иметь операц. среду со средствами разраб.
Каждый транслятор при обработке программы выполняет следующие действия. Лексический анализ, Синтаксический анализ, Семантический анализ и генерация кода. Лексический анализ. Лексический анализатор производит анализ исходного текста на предмет правильности записи лексических единиц входного языка. Затем он переводит программу из нотации исходного текста в нотацию лексем. Лексические единицы - это минимальные конструкции, которые могут быть продекларированы языком. (идентификаторы, ключевые слова, код операции, разделители, константы). После этого программа переводится в вид лексем. Лексема - это некоторая конструкция, содержащая два значения - тип лексемы и номер лексемы. Типа begin - ключевое слово (тип), номер соотв. begin. Синтаксический анализ. Осуществляет проверку программы на предмет правильности с точки зрения синтаксических правил. Результат: либо ошибки, либо представление программы в некотором промежуточном виде, оно поступает на вход семантическому анализатору. Семантический анализ. Семантика - это все то, что не описывается синтаксисом и лексикой языка. К примеру, лексикой и синтаксисом языка сложно описать то, что нехорошо передавать управление в тело цикла не через начало цикла. Выявление таких ошибок - одна из функций семантического анализа. при этом семантический анализатор ставит в соответствие синтаксически и семантически правильным конструкциям объектный код, т.е. происходит генерация кода. Проходы трансляторов. Проход - это полный просмотр некоторого представления исходного текста программы. Большинство - двухпроходные. 1 проход - препроцессор. На 2-м проходе происходит лекс., синт. и семант. анализ, и итог объектная программа в виде ассемблера. Количество проходов в некоторых трансляторах связано с количеством этапов, т.е. бывают реализации, для которых удобно сделать отдельный проход для лексического анализа и т. д..
Билет №27. Многомашинные ассоциации. Понятие о сетях ЭВМ (структура, протоколы, интерфейсы)
Терминальные комплексы
Терминальный комплекс - набор программных и аппаратных средств, предназначенных для взаимодействия пользователей с вычислительной установкой, через телефонную или телеграфную сеть. Типы каналов связи: cимплексные, дуплексные, полудуплексные. Многомашинные Вычислительные комплексы (ММВК) - это программно аппаратное объединение группы вычислительных машин, в которых: 1.На каждой из машин работает своя операционная система (этот признак отличает ММВК от многопроцессорного вычислительного комплекса), 2. В ММВК имеются общие физические ресурсы (а следовательно имеются проблемы синхронизации доступа). ММВК использовались в качестве систем сбора и обработки больших наборов данных, и для организации глобальных терминальных комплексов. Предположим у нас есть некоторая группа вычислительных машин, которые мы будем называть абонентскими машинами (АМ). Имеется коммутационная среда - каналы передачи данных, обеспечивающие взаимодействие между машинами, специальные вычислительные машины - коммутационные машины. Сеть коммутации каналов Происходит соединение каналов и коммутационных машин между этими АМ. Это соединение будет существовать до конца взаимодействия АМ2 и АМ3. Сеть коммутации сообщений. Коммутация сообщений - это связь, при которой весь сеанс разделяется на передачу сообщений (сообщение - некоторая, логически завершенная, порция данных), и коммутация происходит на период передачи сообщения. Сеть коммутации пакетов. Сеанс разбивается на сообщения, сообщения разбиваются на порции данных одинакового объема - пакеты. По сети перемещаются не сообщения, а пакеты. Основное действие коммутационной машины - как можно быстрее избавиться от пакета, определив кому его дальше можно перекинуть. Стандарт ISO/OSI. Развитие многомашинных ассоциаций вообще, и сетей ЭВМ в частности, определило возникновение необходимости стандартизации взаимодействия, происходящего в сети. Поэтому в конце 70-х начале 80-х годов ISO предложила т.н. стандарт взаимодействия открытых систем ISO/OSI (Open System Interface). Семь уровней взаимодействия:
1. Физический уровень или уровень сопряжения с физическим каналом. На этом уровне решаются самые земные вопросы организации взаимосвязи: это вопросы уровней и типов сигналов, и т.д. Этот уровень определяет конкретную физическую среду. Предположим, физической средой может быть среда, которая называется "витая пара", или среда, которая называется "коаксиальный провод", или средой может быть оптоволокно, и т.д. Канальный уровень. На этом уровне формализуются правила передачи данных через канал. Сетевой уровень. Этот уровень управляет связью в сети между машинами. Здесь решается вопрос адресации и маршрутизации данных. Транспортный уровень. Этот уровень иногда называют уровнем логического канала. На этом уровне решаются проблемы управления передачей данных, и связанные с этими проблемами задачи - локализация и обработка ошибок и непосредственно сервис передачи данных. Сеансовый уровень обеспечивает взаимодействие программ. При этом решаются проблемы синхронизации обмена данных, отмены сеанса в результате фатального исхода, подтверждения паролей. Представительский уровень. На этом уровне решается проблема с представлением данных. Понятно, что разные системы имеют разные формы представления данных. Прикладной уровень. На прикладном уровне решаются проблемы стандартизации взаимодействия с прикладными системами. Интернет. В конце 60-х годов американское агентство перспективных исследований в обороне DARPA приняло решение о создании экспериментальной сети с названием ARPANet. Основным свойством этой сети было то, что предполагалось отсутствие какой-либо централизации. Этот проект начал развиваться.
Билет №28. Многомашинные ассоциации. TCP/IP.
Internet основан на протоколах TCP/IP (Transfer Control Protocol / Internet Protocol) - набор протоколов, объединенных под одним названием. Есть отдельно протокол TCP и отдельно протокол IP. Cоответствие TCP/IP модели ISO/OSI: I. Прикладных программ (Прикладных программ, Представление данных), II. Транспортный (Сеансовый , Транспортный), III. Межсетевой (Сетевой), IV. Доступа к сети (Канальный, Физический) Уровень доступа к сети TCP/IP обеспечивают аппаратные интерфейсы и драйверы этих аппаратных интерфейсов. Ethernet - широковещательная сеть, любое сообщение, выходящее из источника становится видимым всем остальным Ethernet- устройствам. Сеть симметрична, то возникает проблема столкновения пакетов передающихся данных - после этого они замирают на некоторое время, а затем делают еще одну попытку. Каждое из Ethernet-устройств имеет уникальный адрес.Еще одно свойство Интернет - широковещательность. Соответственно все сообщения имеют адресацию, и сообщения могут адресоваться всем устройствам, либо какому-то отдельному, но сообщение пройдет через все устройства, и каждое само решит - оставить ли его. Интернет - объединение сетей. Можно выделить два вида компьютеров, которые можно выделить в сети: хост и шлюз. Основная функция протокола IP - межсетевая адресация. Одним из основных свойств или качеств IP-протокола является IP-адрес. Также, в функции IP входит маршрутизация, то есть выбор пути, по которому будут передаваться сообщения, определение базовых блоков данных (они называются дейтаграммы), которые передаются, и взаимодействие с транспортным уровнем и уровнем доступа к сети. Соответственно, в связи с этим взаимодействием возможна фрагментация и дефрагментация дейтаграмм. На межсетевом уровне кроме протокола IP существует еще группа вспомогательных протоколов. Часть из них зависит от того, чем мы будем пользоваться и что мы будем делать. В любом случае - основа для них - протокол IP. Следующие протоколы - транспортные. UDP (User Datagram Protocol) и TCP. Протокол TCP обеспечивает передачу данных с контролем и исправлением ошибок. Кроме того, TCP гарантирует логическое соединение. То есть TCP позволяет создавать логические каналы, гарантируя отправку и прием порций данных в определенном порядке. Протокол жесткий, так как контролирует ошибки. Но TCP является ресурсоемким протоколом. Протокол UDP - это быстрая доставка сообщений без осуществления контроля доставки. Протокол TCP больше рассчитан на использование в Интернете (для передачи на дальние расстояния, где не может гарантироваться безошибочность передачи). UDP ориентирован на работу в локальной сети, где гарантирован определенный уровень качества передачи данных. Протоколы транспортного уровня общаются с прикладными протоколами и межсетевыми протоколами. Далее идет уровень прикладных систем. TCP/IP обладает тем свойством, что в семействе этих протоколов стандартизованы протоколы, на которых базируются прикладные системы. В частности, FTP (File Transfer Protocol). Реально система FTP присутствует в каждой операционной системе и в каждой набор FTP систем может быть значительным. Но за счет того, что имеется стандарт FTP, все эти приложения работают единообразно. Есть сетевой продукт Telnet - сетевая эмуляция алфавитно-цифрового терминала. То есть в системе стандартизованы протоколы с помощью которых организованы прикладные системы. И мы можем строить свои приложения FTP или Telnet из предоставленных кирпичиков. Разные прикладные системы общаются с разными протоколами - кто-то с UDP, кто-то с TCP. FTP и Telnet, например, работают через TCP, а сетевая файловая система NFS, которая позволяет объединять файловые системы разных машин в одну (и видеть их, как свою локальную), основывается на UDP, потому что NFS работает в рамках локальной сети.
Св-ва TCP/IP: 1. Открытые. Доступны пользователю. Стандартные протоколы - платформенные. 2. Передача данных не зависит от аппаратного обеспечения сети. Это семейство может работать и объединяться в сеть. 3. Единая система адресации. Любому TCP/IP устройству можно однозначно адресовать любое другое устройство в сети. 4. Протоколы широко используются пользовательскими программами. Обязательно должна быть своя модель (передача данных) и архитектура. Протокол ICMP (интернет протокол контрольных сообщений)Этот протокол является неотъемлемой частью IP. Пользовательским сервисом передается информация протокола IP для получения сообщений. Они выполняют: 1. Контроль за трафиком (переполнение, а следовательно необходимо приостановить поток на некоторое время). 2.Определяет несуществование получателей или тех, кого нельзя достичь (тому, кто отправил сообщение посылается сигнал). Если нельзя добраться до хоста, то шлюз посылает сигнал. 3. Проверка связи с хостом. echo - message определяет можно ли прозвониться. 4.Изменение маршрута дейтаграмм (в случае, если отправитель и оба шлюза соединены напрямую, то можно послать сообщение о переадресации для того, чтобы узнать возможно ли использование другого шлюза).
Билет №29. Сокеты.
Средства межпроцессорного взаимодействия UNIX решают проблемы взаимодействия процессов в рамках одной ОС. Следовательно возникает проблема взаимодействия процессов в рамках сети. Она связана с принятой системой именования, которая обеспечивает уникальность в рамках одной системы и не годится для сети. Существует механизм, который получил название сокет (гнезда). Сокеты представляют собой обобщение механизма каналов, но с учетом возможных особенностей при работе в сети.
Модель клиент - сервер (при использовании сокетов) Траляля…
Сервер: socket, bind, listen, accept, send, recv. Клиент: socket, bind, connect, send, recv.
Интерфейс. #include <sys\types.h> #include <sys\socket.h>
int socket(int domain; int type; int protocol) domain - номер домена, которому будет принадлежать сокет; type - тип соединения, которым будет пользоваться сокет; SOCK_STREAM - с использованием виртуального канала, Sock_DGRAM - с использованием дейтаграмм. Если значение protocol=0, то система сама выбирает нужный протокол (удобно использовать константы IPRROTO_TCP - для первого типа, IPRROTO_UDP - для второго типа, аналогия с разделяемой памятью). В противном случае будет генерироваться “-1” (если не корректное сочетание аргументов.)
Связь с сокетом. int bind(int sockfd, struct sockaddr *myaddr, int addrlen)
Для AF_INET формат структуры описан в <netinet\in.h>.
struct sockaddr_in {
short sin_family;
U_short sin_port;
struct in_addrsin_addr;
char sin_zero[8];
}
Сокеты с предварительно установленным соединением и без него. Запрос на соединение.
int connect(int sockfd,struct sockaddr *serv_addr, int addrbn) sockfd - ДФ сокета. *serv_addr - указатель на структуру, с которой устанавливается соединение. Сервер: прослушивание сокета и подтверждение соединения
1) int listen (int sockfd, int backbag); backbag - максимальный размер очередного запроса на соединение. 2) int accept (int sockfd, struct sockaddr *addr, int *addrlen);
int sendto (int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *from, int *from_len);
int recvfrom (int sockfd, void *buf, int len, unsigned int flags, const struct sockaddr *from, int *from_len);
int shutdown (int sockfd, int mode);
Пример по сокетам.
Рассмотрим небольшой пример, иллюстрирующий работу с сокетами в рамках локального домена (AF_UNIX). Ниже приведена небольшая программа, которая в зависимости от параметра командной строки исполняет роль клиента или сервера. Клиент и сервер устанавливают соединение с использованием датаграммных сокетов. Клиент читает строку со стандартного ввода и пересылает серверу; сервер посылает ответ в зависимости от того, какова была строка. При введении строки «quit» и клиент, и сервер завершаются.
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un. h>
#include <stdio. h>
#include <string. h>
#define SADDRESS "mysocket"
#define CADDRESS "clientsocket"
#define BUFLEN 40
int main (int argc, char* argv [ ]) {
struct sockaddr_un party_addr, own_addr;
int sockfd;
int is_server;
char buf [BUFLEN];
int party_len;
int quitting;
if (argc! = 2) {
printf ("Usage: %s client|server. \n", argv [0]);
return 0;
quitting = 1; /* определяем, кто мы: клиент или сервер */
is_server = ! strcmp (argv [1], "server");
memset (&own_addr, 0, sizeof (own_addr));
own_addr. sun_family = AF_UNIX;
strcpy (own_addr. sun_path, is_server ? SADDRESS: CADDRESS);
/+ создаем сокет*/
if ((sockfd = socket (AF_UNIX, SOCK_DGRAM, 0)) < 0) {
printf ("can't create socket\n");
return 0;
}
/* связываем сокет */
unlink (own_addr. sun_path);
if (bind (sockfd, (struct sockaddr*) &own_addr,
sizeof (own_addr. sun_family)+ strlen (own_addr. sun_path)) < 0) {
printf ("can't bind socket!");
return 0;
}
if ( ! is_server) { /* это - клиент*/
memset(&party_addr, 0, sizeof (party_addr));
party_addr. sun_family = AF_UNIX;
strcpy(party_addr. sun_path, SADDRESS);
printf("type the string: ");
while (gets (buf)) {
/* не пора ли выходить?*/
quitting = (! strcmp (buf, "quit"));
/* считали строку и передаем ее серверу*/
if (sendto (sockfd, buf, strlen (buf) + 1, О, (struct sockaddr*) &party_addr, sizeof (party_addr. sun_family)+ strlen (SADDRESS))! = strlen (buf)+ 1) {
printf ("client: error writing socket! \n");
return 0;
/* получаем ответ и выводим его на печать*/
if (recvfrom (sockfd, buf, BUFLEN, 0, NULL, 0) < 0) {
printf ("client: error reading socket! \n");
return 0;
}
printf ("client: server answered: %s\n", buf);
if (quitting) break;
printf ("type the string: ");
}
close (sockfd);
return 0;
/* это – сервер */
while (1) {
/* получаем строку от клиента и выводим на печать*/
party_len = sizeof (party_addr);
if (recvfrom (sockfd, buf, BUFLEN, 0, (struct sockaddr*) &party_addr, &party_len) < 0) {
printf ("server: error reading socket!");
return 0;
}
printf ("server: received from client: %s \n", buf);
/* не пора ли выходить?*/
quitting = (! strcmp (buf, "quit"));
if (quitting) strcpy (buf, "quitting now!");
else if (! strcmp (buf, "ping!")) strcpy (buf, "pong!");
else strcpy (buf, "wrong string!");
/* посылаем ответ*/
if (sendto (sockfd, buf, strlen (buf)+ 1, 0, (struct
sockaddr*) &party_addr, party_len)! = strlen (buf)+ 1) {
printf ("server: error writing socket! \n");
return 0;
}
if (quitting) break;
}
close (sockfd);
return 0;
}