О. С. Попова Хіхловська І. В. Системне та прикладне програмне забезпечення у телекомунікаціях Конспект

Вид материалаКонспект
Права доступа к объекту
Идентификаторы и имена в IPC
Объект IPC
Разделяемая память
Другие интерфейсы к коммуникационным протоколам
Лина записи
Подобный материал:
1   2   3   4   5   6   7   8   9   10   ...   14

Права доступа к объекту





Значение ,,,,, в 8-ричн.

Аналог прав доступа для файлов

Разрешено

0400

z - - - - - - - -

Чтение для владельца

0200

- w - - - - - - -

Запиь для владельца

0040

- - - z - - - - -

Чтение для вл. группы

0020

- - - - w - - - -

Запись для вл. группы

0004

- - - - - - z - -

Чтение для всех ост.

0002

- - - - - - - w -

Запись для всех ост.


Идентификаторы и имена в IPC


Как было показано, отсутствие имен у каналов делает их недоступными для независимых процессов. FIFO имеют имена. Другие средства межпроцессного взаимодействия требуют дополнительных соглашений по именам и идентификаторам. Множество возможных имен объектов конкретного типа межпроцессного взаимодействия называется пространством имен ( name space). Имена являются важным компонентом системы межпроцессного взаимодействия для всех объектов, кроме каналов, т.к. позволяют процессам получить доступ к общему объекту. Именем FIFO, является имя файла именованного канала. Используя условное имя созданного FIFO два процесса могут обращаться к этому объекту для обмена данными.

Для таких объектов IPC, как очереди сообщений, семафоры и разделяемая память, процесс назначения имени более сложен, чем просто указание имени файла. Имя для этих объектов называется ключом (key) и генерируется функцией ftok(3c) из двух компонентов – имени файла и идентификатора проекта:

# include

# include

key –t ftok (char *filename, char proj);

В качестве filename можно использовать имя некоторого файла, известное взаимодействующим процессам, например, имя программы-сервера. Главное, чтобы этот файл существовал на момент создания ключа. Нежелательно использовать имя файла, который создается и удаляется в процессе работы распределенного приложения, т.к. при генерации ключа используется номер inode файла. Вновь созданный файл может иметь другой inode и впоследствии процесс, желающий иметь доступ к объекту, получит неверный ключ.

Пространство имен позволяет создать и совместно использовать IPC неродственным объектам.

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

Идентификация объектов выполняется в соответствии с табл.

Таблица . Идентификация объектов IPC

Объект IPC

Пространство имен

Дескриптор

Канал



Файловый дескриптор

FIFO

Имя файла

Файловый дескриптор

Очередь сообщений

Ключ

Идентификатор

Семафор

Ключ

Идентификатор

Разделяемая память

Ключ

Идентификатор



  1. СООБЩЕНИЯ

Внутренний, связанный список процессов в порядке их поступления, который в виде очереди хранится в адресном пространстве ядра. Для каждой очереди ядро создает заголовок msgid_ds, где содержится информация оправах доступа к очереди, ее текущем состоянии на первое и последнее сообщения. Каждый элемент очереди является отдельным сообщением.

  1. СЕМАФОРЫ

Используются для синхронизации доступа нескольких процессов к разделяемым ресурсам. Разрешают или запрещают доступ к разделяемому ресурсу.

Семафоры являются системным ресурсом, действия над которыми производятся через интерфейс системных вызовов.

Семафоры хранятся в адресном пространстве ядра.

  1. РАЗДЕЛЯЕМАЯ ПАМЯТЬ

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

  1. СОКЕТЫ

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

Для коммутационного узла, обеспечивающего прием и передачу данных для объекта (процесса) предложен специальный объект – сокет (socket), который создается в рамках коммутационного домена (communication domain) и адресуется своим дескриптором.

Сокет – виртуальный объект. Он существует, пока в нем есть необходимость.

Реализованы основные виды сокетов:

– сокет датаграмм (datagram socket) – осуществляет теоретически ненадежную, несвязную передачу пакетов;

– сокет потока (stream socket) – осуществляет надежную передачу потока байтов, без сохранения границ сообщений. Используется для передачи экстренных сообщений;

– сокет пактов (packet socket) – выполняет надежную передачу потока данных без дублирования с предварительным установлением связи. При использовании, сохраняются границы сообщений;

– сокет низкого уровня (raw socket) – такой сокет позволяет осуществить непосредственный доступ к коммуникационному протоколу.


Другие интерфейсы к коммуникационным протоколам


В UNIX в качестве интерфейса к TCP/IP в основном используются следующие API:
  1. сокеты Беркли;
  2. транспортный интерфейс XTI (X/Open Transport Interface);


Интерфейс XTI является расширением к транспортному протоколу TLI(XTI/TLI)-Transport Layer Interface.Он задумывался как интерфейс, не зависящий от протокола, так как он легко поддерживал новые протоколы OSI, которые, как считалось, придут на смену TCP/IP. Имена функцийTLI похожи на используемые в API сокетов, но начинаются с t_. Но их семантика кардинально отличается в ряде случаев. Этот протокол используется в системах фирмы NOVELL, а также поставляются в OC UNIX. Протоколы XTI называется интерфейсом наряду с интерфейсом сокетов, так как это всего лишь доступ к стеку TCP/IP, так как коммуникационные протоколы реализуются стеком протоколов, также имеет значение, какой API использует клиент. Приложение с использованием сокетов, может обмениваться данными с приложением на базе XTI.В системах SVR4 оба интерфейса обычно реализуются в виде библиотек. Достоинством XTI/TLI является возможность с его помощью добавить новый протокол, не имея доступа к ядру, причём достаточно просто.

Тем не менее есть примеры реализации с помощью сокетов простого, не зависящего от протокола сервера времени дня, который поддерживает IP версий 4 и 6, и сокеты в адресном домене UNIX. Существует спор, какие из интерфейсов более производительны, но они одинаковы.

Большое преимущество сокетов –переносимость - на MsWin.Сокеты проще используются, и их рекомендуется преимущественно использовать SVR4 и SVR6-протоколы IP, позволяющие пересылать в пакете 4 или 6 байтов.

Solaris-это SVR4 фирмы SUN.


TCP как потоковый протокол


Данные доставляются получателю в виде потока, в котором нет понятия сообщения или границы сообщения. В этом отношении чтение данных похоже на чтение из последовательного порта - заранее неизвестно, сколько байтов будет возвращено после выполнения функции чтения. Для TCP –приложения нет понятия «пакет», и хотя данные передаются в IP-пакетах, размер пакета не связан напрямую с количеством данных, переданных TCP при вызове send. У принимающего приложения нет надёжного способа определения, как именно данные распределены по пакетам, так как между соседними вызовами recv может прийти несколько пакетов. Если один пакет потерян, а последующие пришли нормально, TCP “задерживает поступившие данные”, пока не будет повторно передан и корректно принят пропавший пакет. TCP следит за количеством байтов, посланных и подтвержденных, но не за их распределением по пакетам. Если пользоваться для чтения данных стандартной библиотечной функцией fgets, то она сама будет разбивать поток байтов на строки. Самый простой случай-это сообщение фиксированной длины. Тогда нужно прочесть заранее известное число байтов из потока. Для этого недостаточно выполнить простое однократное чтение:

Recv(s,msg,size of(msg),o);

Так как при этом можно получить меньше, чем size of(msg) байт


Функция readn

  1. in readn(SOCKET fd,char*bp,size_t len)

  2. {
  3. int ent;
  4. int rc;
  5. ent=len;
  6. while(ent>0)
  7. {
  8. rc=recv(fd,bp,ent,0);
  9. if(rc<0) /’’ошибка чтения ?*/
  10. {
  11. if(errno==ENTER)/*Вызов прерван?*/
  12. continue;/*повторить чтение*/
  13. return-1/*вернуть код ошибки*/
  14. }
  15. if(rc==0)/*конец файла*?/
  16. return len-ent/*вернуть неполный счётчик*/
  17. bp+=rc
  18. ent-=rc;
  19. }
  20. return len;
  21. }



Функция readn не возвращает управление, пока не будет прочитано len байт или не получен конец файла, или не возникнет ошибка. Её прототип выглядит следующим образом :

# include

int readn(SOCKET s,char*buf,size_tlen);

возвращаемое значение - число прочитанных байтов или –1 в случае ошибки.

Оператор if

If (errno==ENTER)

Continue;

(Errno-глобальная переменная ,ENTER -прерванный вызов функции) возобновляет выполнение вызова recv, если он прерван сигналом.


В случае сообщений переменной длины есть два метода разделения записей:
  1. с помощью специальных маркеров с использованием fgets для разбиения потока на строки, например, с помощью разделителя-символа новой строки/. Тогда, если оно применяется в теле, то нужно здесь заменить его на //. На приёмной стороне происходит обратный процесс.
  2. Каждое сообщение снабжается заголовком, содержащим, как минимум длину следующего за ним тела.




Д ЛИНА ЗАПИСИ

ДРУГИЕ ДАННЫЕ ЗАГОЛОВКА

ДАННЫЕ ПЕРЕМЕННОЙ ДЛИНЫ

В процедуре fgets происходит считывание символов из потока в буфер пока не встретится символ/.

Принимающее приложение читает сообщение в два приёма: заголовок фиксированной длины и из него извлекается переменная длина тела сообщения, а затем самое тело.
  1. int readvrec(SOCKET fd,char*bp,size_t len),где SOCKET-тип данных,t-длина буфера.
  2. {
  3. uint32_t reclen;
  4. Int rc;
  5. /*прочитать длину записи*/
  6. rc=readn(fd,(char*)&reclen ,size of(u_int32_t));
  7. if(rc!=sizeof(u_int32_t))
  8. return rc<0?-1:0;
  9. reclen=ntohl(reclen);/*сетевой в машинный*/
  10. if(reclen>len)
  11. {
  12. /*
  13. *Не хватает места в буфере для размещения
  14. *данных – отбросить их и вернуть код ошибки
  15. */
  16. while(reclen>0)
  17. {
  18. rc=readn(fd,bp,len);
  19. if(rc!=len)
  20. returnrc<0?-1:0;
  21. reclen==len;/*reclen=reclen-len*/
  22. if(reclen
  23. len=reclen;
  24. }
  25. set_errno(EMSGSIZE);
  26. return-1;
  27. }
  28. /*прочитать саму запись*/
  29. rc=readn(fd,bp,reclen);
  30. if(rc!=reclen)
  31. return rc<0?-1:0;
  32. return rc;
  33. }