Добавил:
Developerrnrn Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

учебник

.pdf
Скачиваний:
30
Добавлен:
25.03.2023
Размер:
2.24 Mб
Скачать

этом случае примет значение EINTR (для вызова write и сигнала SIGPIPE соответствующее значение в порядке исключения будет

EPIPE).

Чтобы пришедший сигнал SIGPIPE не завершил работу процесса по умолчанию, необходимо его обработать самостоятельно (функция-обработчик при этом может быть и пустой!). Но этого мало. Поскольку нормальный ход выполнения системного вызова был нарушен сигналом, возврат из него будет с отрицательным значением, которое свидетельствует об ошибке. Проанализировав значение системной переменной errno на предмет совпадения со значением EPIPE, можно отличить возникновение сигнала SIGPIPE от других ошибочных ситуаций (неправильные значения параметров и т. д.) и продолжить работу программы.

9.12 Понятие о надежности сигналов. POSIX функции для работы с сигналами

Основным недостатком системного вызова signal() является его низкая надежность. Во многих вариантах операционной системы UNIX установленная при его помощи обработка сигнала пользовательской функцией выполняется только один раз, после чего автоматически восстанавливается реакция на сигнал по умолчанию. Для постоянной пользовательской обработки сигнала необходимо каждый раз заново устанавливать реакцию на сигнал прямо внутри функции-обработчика.В системных вызовах и пользовательских программах могут существовать критические участки, на которых процессу недопустимо отвлекаться на обработку сигналов. Можно выставить на этих участках реакцию «игнорировать сигнал» с последующим восстановлением предыдущей реакции, но если сигнал все-таки возникнет на критическом участке, то информация о его возникновении будет безвозвратно потеряна. Наконец, последний недостаток связан с невозможностью определения количества сигналов одного и того же типа, поступивших процессу, пока он находился в состоянии готовность. Сигналы одного типа в очередь не ставятся! Процесс может узнать о том, что сигнал или сигналы определенного типа были ему переданы, но не может определить их количество.

251

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

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

Программа 9-06 для иллюстрации ненадежности сигналов

#include <sys/types.h> #include <unistd.h> #include <wait.h> #include <signal.h> #include <stdio.h> #include <errno.h> #include <cstdlib.h> #include <iostream> using namespace std;

/* Функция my_handler – обработчик сигнала SIGCHLD */ void my_handler(int nsig)

{

int status; pid_t pid;

/* Опрашиваем статус завершившегося процесса и одновременно узнаем его идентификатор */

if((pid = waitpid(-1, &status, 0)) < 0)

{

/* Если возникла ошибка – сообщение о ней и продолжение работы */

cout<<"Some error on waitpid errno "<< errno << endl;

}

else

{

/* Иначе анализируем статус завершившегося процесса */ if ((status & 0xff) == 0)

{

252

/* Процесс завершился с явным или неявным вызовом функции exit() */

printf("Process %d was exited with status %d\n", pid, status >> 8);

}

else if ((status & 0xff00) == 0)

{

/* Процесс был завершен с помощью сигнала */

printf("Process %d killed by signal %d %s\n", pid, status &0x7f,(status & 0x80) ?"with core file" : "without core file");

}

}

}

int main(void)

{

pid_t pid; int i;

/* Устанавление обработчика для сигнала SIGCHLD */ (void) signal(SIGCHLD, my_handler);

/* В цикле порождение 5 процессов-детей */ for (i=0; i < 5; i++)

if((pid = fork()) < 0)

{

cout<< “Can't fork child ” << i<< endl; exit(1);

}

else if (pid == 0)

{

/* Child i – завершается с кодом 200 + i */ exit(200 + i);

}

/* Продолжение процесса-родителя – уход на новую итерацию */

}

/* Продолжение процесса-родителя – уход в цикл */ while(1);

return 0;

}

Листинг 9-06. Программа для иллюстрации ненадежности сигналов

253

Последующие версии System V и BSD пытались устранить эти недостатки собственными средствами. Единый способ более надежной обработки сигналов появился с введением POSIX стандарта на системные вызовы UNIX. Набор функций и системных вызовов для работы с сигналами был существенно расширен и построен таким образом, что позволял временно блокировать обработку определенных сигналов, не допуская их потери. Однако проблема, связанная с определением количества пришедших сигналов одного типа, попрежнему остается актуальной. (Необходимо отметить, что подобная проблема существует на аппаратном уровне и для внешних прерываний. Процессор зачастую не может определить, какое количество внешних прерываний с одним номером возникло, пока он выполнял очередную команду.)

Порядок выполнения лабораторной работы:

1.Наберите программу 9-01, откомпилируйте ее и запустите на исполнение (лучше всего из-под оболочки Midnight Commander – mc). Запустив команду "ps –e j" с другого экрана, проанализируйте значения идентификаторов группы процессов, сеансов, прикрепления управляющего терминала, текущей и фоновой групп. Убедитесь, что тривиальные процессы относятся к текущей группе сеанса. Проверьте реакцию текущей группы на сигналы SIGINT – нажатие клавиш <CTRL> и <C> – и SIGQUIT – нажатие клавиш

<CTRL> и <4>.

2.Запустите теперь программу 9-01 в фоновом режиме, например командой "a.out". Проанализируйте значения идентификаторов группы процессов, сеансов, прикрепления управляющего терминала, текущей и фоновой групп. Убедитесь, что тривиальные процессы относятся к фоновой группе сеанса. Проверьте реакцию фоновой группы на сигналы SIGINT – нажатие клавиш <CTRL> и <C> – и SIGQUIT – нажатие клавиш <CTRL> и <4>. Ликвидируйте тривиальные процессы с помощью команды kill .

3.Возьмите снова тривиальную программу из предыдущего раздела и запустите ее на исполнение из-под Midnight Commander в текущей группе. Проанализировав значения идентификаторов группы процессов, сеансов, прикрепления

254

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

4.Запустите тривиальную программу в фоновом режиме. Снова удалите лидера сеанса для тривиальных процессов. Убедитесь, что фоновая группа продолжает работать. Ликвидируйте тривиальные процессы.

5.Модифицируйте программу 9-02 так, чтобы она перестала реагировать и на нажатие клавиш <CTRL> и <4>. Откомпилируйте и запустите ее, убедитесь в отсутствии ее реакций на внешние раздражители. Снимать программу придется теперь с другого терминала командой kill.

6.Модифицируйте программу 9-03 так, чтобы она печатала сообщение и о нажатии клавиш <CTRL> и <4>. Используйте одну и ту же функцию для обработки сигналов SIGINT и SIGQUIT. Откомпилируйте и запустите ее, проверьте корректность работы. Снимать программу также придется с другого терминала командой kill.

7.Наберите, откомпилируйте программу 9-04 и запустите ее на исполнение

8.Когда рассматривалась связь родственных процессов через pipe, речь шла о том, что pipe является однонаправленным каналом связи и что для организации связи через один pipe в двух направлениях необходимо задействовать механизмы взаимной синхронизации процессов. Организуйте двустороннюю поочередную связь процесса-родителя и процесса-ребенка через pipe, используя для синхронизации сигналы SIGUSR1 и SIGUSR2, модифицировав программу для организации однонаправленной связи между родственными процессами через pipe семинара 4.

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

10.Откомпилируйте программу 9-05 и запустите ее на исполнение. Второй порожденный процесс завершайте с помощью команды kill с каким-либо номером сигнала. Родительский процесс также будет необходимо завершать командой kill.

255

11.Задача повышенной сложности: модифицируйте обработку сигнала в программе 6, не применяя POSIX-сигналы, так, чтобы процесс-родитель сообщал о статусе всех завершившихся процессов-детей.

Контрольные вопросы

1.Понятие виртуальной файловой систем.

2.Операции над файловыми системами.

3.Монтирование файловых систем. Блочные, символьные устройства.

4.Понятие драйвера. Блочные, символьные драйверы, драйверы низкого уровня.

5.Файловый интерфейс. Аппаратные прерывания (interrupt), исключения (exception), программные прерывания (trap, software interrupt). Их обработка.

6.Понятие сигнала. Способы возникновения сигналов и виды их обработки.

7.Понятия группы процессов, сеанса, лидера группы, лидера сеанса, управляющего терминала сеанса.

8.Системные вызовы getpgrp(), setpgrp(), getpgid(), setpgid(), getsid(), setsid().

9.Системный вызов kill() и команда kill.

10.Изучение особенностей получения терминальных сигналов текущей и фоновой группой процессов.

11.Системный вызов signal(). Установка собственного обработчика сигнала.

12.Сигналы SIGUSR1 и SIGUSR2. Использование сигналов для синхронизации процессов.

13.Завершение порожденного процесса. Системный вызов waitpid(). Сигнал SIGCHLD.

14.Возникновение сигнала SIGPIPE при попытке записи в pipe

или FIFO.

15.Понятие о надежности сигналов.

16.POSIX функции для работы с сигналами.

256

Лабораторная работа 10 СЕМЕЙСТВО ПРОТОКОЛОВ TCP/IP.

СОКЕТЫ (sockets) В UNIX И ОСНОВЫ РАБОТЫ С НИМИ

Цели и задачи

Изучить семейство протоколов TCP/IP. Рассмотреть использование модели клиент-сервер для взаимодействия удаленных процессов. Научиться организации связи между удаленными процессами с помощью датаграмм. Рассмотреть функции преобразования IP-адресов inet_ntoa(), inet_aton(). Научиться использовать основные функции и системные вызовы для работы с сокетами.

10.1 Краткая история семейства протоколов TCP/IP

Все многообразие сетевых приложений и многомиллионная всемирная компьютерная сеть выросли из четырехкомпьютерной сети ARPANET, созданной по заказу Министерства обороны США и связавшей вычислительные комплексы в Стэндфордском исследовательском институте, Калифорнийском университете в СантаБарбаре, Калифорнийском университете в Лос-Анджелесе и университете Юты. Первая передача информации между двумя компьютерами сети ARPANET состоялась в октябре 1969 года, и эту дату принято считать датой рождения нелокальных компьютерных сетей. (Необходимо отметить, что дата является достаточно условной, так как первая связь двух удаленных компьютеров через коммутируемые телефонные линии была осуществлена еще в 1965 году, а реальные возможности для разработки пользователями ARPANET сетевых приложений появились только в 1972 году.) При создании ARPANET был разработан протокол сетевого взаимодействия коммуникационных узлов – Network Control Protocol (NCP), осуществлявший связь посредством передачи датаграмм. Этот протокол был предназначен для конкретного архитектурного построения сети и базировался на предположении, что сеть является статической и настолько надежной, что компьютерам не требуется умения реагировать на возникающие ошибки. По мере роста ARPANET и необходимости подключения к ней сетей, построенных на других архитектурных принципах (пакетные спутниковые сети, наземные пакетные радиосети), от этого предположения пришлось

257

отказаться и искать другие подходы к построению сетевых систем. Результатом исследований в этих областях стало появление семейства протоколов TCP/IP, на базе которого обеспечивалась надежная доставка информации по неоднородной сети. Это семейство протоколов до сих пор занимает ведущее место в качестве сетевой технологии, используемой в операционной системе UNIX.

10.2 Общие сведения об архитектуре семейства протоколов TCP/IP

Семейство протоколов TCP/IP построено по «слоеному» принципу. Хотя оно и имеет многоуровневую структуру, его строение отличается от строения эталонной модели OSI, предложенной стандартом ISO. Это и неудивительно, так как основные черты семейства TCP/IP были заложены до появления эталонной модели и во многом послужили толчком для ее разработки. В семействе протоколов TCP/IP можно выделить четыре уровня:

Уровень сетевого интерфейса.

Уровень Internet.

Транспортный уровень.

Уровень приложений/процессов.

Соотношение уровней семейства TCP/IP и уровней модели OSI/ISO приведено на рисунке 10.1.

Рис. 10.1. Соотношение моделей OSI/ISO и TCP/IP

258

На каждом уровне семейства TCP/IP присутствует несколько протоколов. Связь между наиболее употребительными протоколами и их принадлежность уровням изображены на рисунке 10.2.

Рис.10.2. Основные протоколы семейства TCP/IP

10.3 Уровень сетевого интерфейса

Уровень сетевого интерфейса составляют протоколы, которые обеспечивают передачу данных между узлами связи, физически напрямую соединенными друг с другом или, иначе говоря, подключенными к одному сегменту сети, и соответствующие физические средства передачи данных. К этому уровню относятся протоколы Ethernet, Token Ring, SLIP, PPP и т.д. и такие физические средства, как витая пара, коаксиальный кабель, оптоволоконный кабель и т.д. Формально протоколы уровня сетевого интерфейса не являются частью семейства TCP/IP, но существующие стандарты определяют, каким образом должна осуществляться передача данных семейства TCP/IP с использованием этих протоколов. На уровне сетевого интерфейса в операционной системе UNIX обычно функционируют драйверы различных сетевых плат.

Передача информации на уровне сетевого интерфейса производится на основании физических адресов, соответствующих точкам входа сети в узлы связи (например, физических адресов

259

сетевых карт). Каждая точка входа имеет свой уникальный адрес – MAC-адрес (Media Access Control), физически зашитый в нее на этапе изготовления. Так, например, каждая сетевая плата Ethernet имеет собственный уникальный 48-битовый номер.

10.4 Уровень Internet. Протоколы IP, ICMP, ARP, RARP. Internet–адреса

Из многочисленных протоколов уровня Internet перечислены только некоторые:

ICMP – Internet Control Message Protocol. Протокол обработки ошибок и обмена управляющей информацией между узлами сети.

IP – Internet Protocol. Это протокол, который обеспечивает доставку пакетов информации для протокола ICMP и протоколов транспортного уровня TCP и UDP.

ARP – Address Resolution Protocol. Это протокол для отображения адресов уровня Internet в адреса уровня сетевого интерфейса.

RARP – Reverse Address Resolution Protocol. Этот протокол

служит для решения обратной задачи: отображения адресов уровня сетевого интерфейса в адреса уровня Internet.

Два последних протокола используются не для всех сетей; только некоторые сети требуют их применения.

Уровень Internet обеспечивает доставку информации от сетевого узла отправителя к сетевому узлу получателя без установления виртуального соединения с помощью датаграмм и не является надежным.Центральным протоколом уровня является протокол IP. Вся информация, поступающая к нему от других протоколов, оформляется в виде IP-пакетов данных (IP datagrams). Каждый IP-пакет содержит адреса компьютера отправителя и компьютера получателя, поэтому он может передаваться по сети независимо от других пакетов и, возможно, по своему собственному маршруту. Любая ассоциативная связь между пакетами, предполагающая знания об их содержании, должна осуществляться на более высоком уровне семейства протоколов.

IP-уровень семейства TCP/IP не является уровнем, обеспечивающим надежную связь, так как он не гарантирует ни

260

Соседние файлы в предмете Современные операционные системы