- •Ос в общей структуре компьютера.
- •История операционных систем.
- •Классификация современных ос. Задачи современных ос.
- •6. Понятие процесса – ключевое понятие ос.
- •8. Трансляторы: компиляторы и интерпретаторы.
- •9. Иерархия зу (запоминающих устройств).
- •10. Управление оперативной памятью (оп). Менеджер памяти; swapping; виртуальная память.
- •11. Модели организации виртуальной памяти.
- •12. История ос unix.
- •13. Общая архитектура unix. Основные подсистемы ядра.
- •14. Пользовательская среда unix.
- •Командный интерпретатор shell.
- •16. Система каталогов в oс unix. Управление с помощью команд языка Bourn shell.
- •17. Управление файлами с помощью команд языка Bourn shell. Перенаправление ввода/вывода.
- •19. Обработка аргументов командной строки. Переменные окружения.
- •20. Пользователь и группа. Права доступа к файлу.
- •21. Системные вызовы и функции стандартных библиотек. Обработка ошибок.
- •22.Структура программы на языке с. Параметры главной функции (пример).
- •23. Файловая система ос unix: монтирование, индексные дескрипторы, жесткие и символические ссылки, файлы устройств.
- •24.Системные вызовы для работы с файлами
- •25. Понятие «процесс» в ос unix. Контекст процесса; свойства процесса; состояние процесса.
- •26.Создание процессов и упр-е ими.
- •27. Запуск внешней программы
- •29.Общая классификация средств взаимодействия процессов в ос unix.
- •30.Иерархия процессов в ос unix. Понятие сеанса. Фоновые процессы.
- •31.Каналы – средства взаимодействия процессов. Неименованные каналы. Организация конвейера (пример программы).
- •33.Сигналы как средство взаимодействия процессов в ос unix. Диспозиция сигналов.
- •34.Ограничения для процесса в ос unix (по ресурсам). Связь со свойствами процесса.
- •36.Отображение файлов в виртуальное адресное пространство. Разделяемая память.
- •37. Взаимодействие процессов через псевдотерминал.
- •38. Недостатки потокового взаимодействия процессов. Средства System vipc. Пространство имен. Общие принципы работы со средствами System vipc.
- •39. Организация очереди сообщений в ос unix. Структура сообщения. Отправка и принятие сообщений.
- •40.Семафоры, как средство взаимодействия процессов System vipc. Понятие атомарной операции. Массив семафоров.
- •41.Разделяемая память, как средство взаимодействия процессов System vipc.
- •42.Взаимодействие по сети. Понятие протокола. Семейства адресации и типы взаимодействия. Создание сокета в ос unix.
- •45. Потоковые сокеты. Клиент – серверная модель.
- •46. Проблема очередности действий и ее решение.
- •47. Процессы-демоны. Система журнализации.
- •48. Загрузка и жизненный цикл в ос unix.
- •49. Взаимоисключения. Понятие критической секции. Устаревшие подходы к организации взаимного исключения.
- •50.Поддержка взаимоисключения на уровне ос. Мьютексы и семафоры (Дейкстры). Команда ассемблера tsl.
- •51.Проблема тупиков. Граф ожидания
- •52. Нити исполнения (pthreads) в ос unix. Мьютексы pthreads.
- •53.Графический интерфейс в ос unix. Базовые принципы построения x_window.
- •54.Файловая подсистема. Общая структура. Методы выделения дискового пространства. Управление дисковым пространством.
- •55.Файловая подсистема. Структура файловой системы на диске. Реализация директорий. Поиск в директории (хеширование).
- •56.Подсистема ввода/вывода. Схема взаимодействия подсистем ос. Понятие драйвера. Типы драйверов.
46. Проблема очередности действий и ее решение.
У нас имеется 2 дескриптора (как минимум). На одном из дескрипторов может ожидаться запрос на соединение нового клиента (accept). Если выполним accept, а никакого запроса на соединение не было, наша прога зависнет внутри этого вызова accept сколько угодно долго. В это время на любой из клиентских сокетов могут придти данные, требующие обработки, но пока мы внутри accept никакой обработки не будет. С другой стороны если произвести чтение с клиентского сокета есть риск что клиент не примет никаких данных в течение длительного времени. Все это время наша прога зависнет внутри вызова read.
Самое простое решение: перевести все сокеты в неблокирующий режим при котором вызовы read и accept всегда возвращают управление немедленно ничего не ожидая. Можно начать их опрашивать по очереди в бесконечном цикле, т.е. режим активного ожидания. В многозадачным системах это не приемлимо, т.к. процесс бесконечно опрашивающий набор сокетов будет вхолостую тратить ресурсы.
Другое решение:
При написании сервер. проги можно создать отдельный процесс для обслуживания каждого клиента.
Если жалко, что созданные процессы много простаивают, можно сделать иначе: это решение на основе обслуживающих процессов. Наш главный процесс будет бОльшую часть времени находится в режиме accept. При принятии запроса от клиента наш процесс породит дочерний процесс для обслуживания клиента. После порождения родит процесс закрывает клиент. сокет, а дочерний процесс закрывает слушающий сокет, т.о. все обязанности по обслуживанию клиента ложатся на дочерний процесс. Все это время родит. процесс продолжает использовать слушающие обязанности вызывая accept.
Программа:
int ls;
struct sockaddr_cr addr;
ls = socket (AF_INET, SOCK_STREAM, 0);
if (ls==-1) {perror (“Error socket”);}
addr.sin_family = AF_INET;
addr.sin_port = htons (port);
addr.sin_addr.s_addr = INADDR_ANY;
// Заданная инструкция в системе принимает соединение по заданному порту при любом IP-адресе.
if (bind(ls, &addr, sizeof(addr))==-1) {perror (“error bind”);}
// Сформируем 3й параметр для accept – это будет размер адрес. структуры, куда будет записан адрес сокета с которого будет устанавливаться соединение.
for ( ; ; )
{
sock_len_t slen = sizeof (addr);
int cls = accept (ls, %addr, &slen);
if (fork()==0) {close(ls); anet(0);}
// Дальше работа с клиентом идет через сокет cls. Клиент пойдет с адреса, который хранится в addr.
// Дальше действия в родит. процессе:
close(cls);
// Далее проверим не завершился ли какой-нить дочерний процесс:
while (wait4(-1,NULL); //wait4 ждет любого заверш. процесса и убирает «зомби»
}
Мультиплексирование ввода/вывода. Событийно-управляемое программирование:
Когда порождение процесса по каждому клиент. соединению не приемлимо (например, сервер перегружен или между сеансами обслуживания разных клиентов происходит активное взаимодействие) надо оставить обслуживание всех клиентов в рамках одного процесса, но активное ожидание не приемлемо.
Пусть имеем некоторое количество типов событий, каждое из которых требует своей обработки. Многие систем. вызовы, предназначенные для обработки имеют след. свойство: будучи вызванными дл наступления события они это событие ожидают, блокируют вызвавший процесс и делают невозможным обработку других событий. Но возможно, что длительное время не наступит ни одного события =>надо исключить холостой расход процессорного времени, т.е. нужно иметь возможность отдать ОС процессорное время до наступления события.
Вызов select() позволяет обрабатывать события 3 типов:
Изменение состояния ФД (появление данных на чтение/запись на соединении; освобождение места в буфере; исключительная ситуация).
Истечение заданного количества времени с момента входа в вызов.
Получение процессом не игнорируемого сигнала.
int select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
readfds, writefds, exceptfds – множество ФД.
n – какое количетсво элементов в этих множествах является значимым.
(n = max_d+1 – рекомендуемое значение, где max_d – максимальный номер дескриптора)
timeout – параметр задает промежуток времени, спустя который требует вернуть управление процессу, даже если не произошло событие.
Тип fd_set можно представить как битовую строку, где каждому дескриптору соотв. 1 бит. Для работы с переменный такого типа UNIX предоставляет макросы:
FD_ZERO (fd_set *set);
FD_CLR (int fd, fd_set *set);
FD_SET (int fd, fd_set *set);
FD_ISSET (int fd, fd_set *set);
Тип timeval – структура которая имеет 2 поля (оба типа long int). 1ое поле – количество секунд, 2ое поле – количество vrc/
timeout = 5.3 c
struct timeval t
t.tv_sec = 5;
t.tv_usec = 300 000;
Вызов select() возвращает управление в следующих случаях:
Ошибка, возврат -1.
Получен не игнорируемый сигнал =>возврат тоже -1, далее надо сделать проверку errno = EINTR.
Истек timeout, возврат 0.
Примем данные на какой-либо из дескрипторов, а дескриптор определен в множестве readfds.
Какой-либо из дескрипторов writefds готов на записью
На каком-либо дескрипторе exceptfds возникло исключение.
В случаях 4,5,6 select возвращает количество дескрипторов изменивших статус, при этом все множество изменяется и в них остаются только те дескрипторы, которые изменили свой статус.
Способ построения программ при котором прога имеет главный цикл, 1 итерация этого цикла соответствует наступлению события из определенного множества, а все остальные действия проги построены как реакция на событие, вот это событийно-ориентированное программирование.