- •Кафедра программного обеспечения информационных технологий
- •«Операционные системы и системное программирование»
- •40 01 01
- •Содержание
- •Введение
- •Разработка программ в ос unix
- •1.1 Отличительные черты ос unix
- •1.2 Основы архитектуры операционной системы unix
- •1.3 Ядро системы
- •1.4 Пользователи системы, атрибуты пользователя
- •1.5 Системные вызовы и функции стандартных библиотек
- •1.6 Описание программы, переменные окружения
- •1.7 Аргументы и опции программы
- •1.8 Обработка ошибок
- •2 Файлы и файловая система
- •2.1 Файлы
- •2.2 Типы файлов
- •2.2.1 Обычные файлы
- •2.2.2 Каталоги
- •2.2.3 Файлы символичной связи (ссылки)
- •2.2.4 Файлы устройства
- •2.2.5 Именованные каналы
- •2.2.6 Сокеты
- •2.3 Владельцы файлов и права доступа к файлу
- •2.4 Дополнительные атрибуты файла
- •2.5 Файловый ввод/вывод
- •Открытие файла
- •2.6 Мультиплексированный ввод/вывод
- •2.7 Векторный ввод/вывод
- •2.8 Файлы, отображающиеся в памяти
- •2.9 Каталоги, работа с каталогами
- •2.9.1 Создание каталога
- •2.9.2 Удаление каталога
- •2.9.3 Чтение информации из каталога
- •2.9.4 Закрытие каталога
- •2.10 Создание жестких ссылок
- •2.11 Символическая ссылка
- •2.12 Удаление ссылки (или имени файла)
- •2.13 Переименование файла
- •2.14 Файловая система ос unix
- •2.14.1 Организация файловой системы ext2
- •2.15 Файлы устройств
- •3 Процессы
- •3.1 Виды процессов
- •3.2 Создание процесса
- •3.3 Вызовы семейства exec
- •3.4 Функции завершения процесса
- •3.5 Ошибки
- •3.6 Копирование при записи
- •3.7 Системные вызовы ожидания завершения процесса
- •3.8 Системный вызов system
- •3.9 Основные параметры, передаваемые процессу
- •3.10 Сеансы и группы процессов
- •4 Взаимодействие процессов
- •4.1 Сигналы
- •4.1.1 Отправка (генерация) сигнала
- •4.1.2 Наборы сигналов
- •4.1.3 Блокировка сигналов
- •4.2 Неименнованные каналы (трубы)
- •4.2.1 Размер канала и взоимодействие процессов при передаче данных
- •4.3 Именнованные каналы
- •4.4 Дополнительные средства межпроцессного взоимодействия
- •4.5 Механизмы межпроцессорного взаимодействия
- •4.5.1 Очереди сообщений
- •4.5.2 Семафоры Семафоры как теоретическая конструкция
- •4.5.3 Разделяемая память
- •4.5.4 Потоки
- •Int pthread_setschedparam(pthread_t tid, int policy, const struct sched_param *param);
- •Int pthread_getschedparam(pthread_t tid, int policy, struct schedparam *param);
- •5 Операционные системы
- •5.1 Понятие операционной системы
- •5.2 Характеристики современных ос
- •5.2.1 Многопоточность
- •5.2.2 Распределенные ос
- •5.2.3 Концепция ос на основе микроядра
- •5.2.4 Функции микроядра.
- •5.3 Принципы построения ос
- •5.4 Концептуальные основы ос
- •5.4.1 Процессы
- •Модель работы процесса с двумя приостановочными состояниями
- •Варианты решения:
- •Решение задачи взаимного исключения. Алгоритм Деккера.
- •Решение задачи взаимного исключения. Алгоритм Пэтерсона..
- •Синхронизирующие примитивы (семафоры).
- •Задача “производитель-потребитель” Общие семафоры
- •Задача “производитель-потребитель”, буфер неограниченного размера(Спящий парикмахер)
- •Задача “производитель-потребитель”, буфер ограниченного размера
- •5.4.2 Распределение ресурсов. Проблема тупиков
- •Алгоритм банкира
- •Применение алгоритма банкира
- •5.4.3 Монитороподобные средства синхронизации
- •Механизм типа «критическая область»
- •5.4.4 Виртуализация
- •5.4.5 Подсистема управления памятью
- •5.4.6 Виртуальная оперативная память
- •5.5 Аппаратные особенности процессоров Intel-архитектуры, направленных на поддержку многозадачности
- •5.5.1 Сегментация памяти. Ia-32
- •5.5.2 Распределение памяти в реальном режиме
- •5.5.3 Организация защиты в процессоре
- •5.5.4 Поддержка многозадачности в процессорах архитектуры ia-32
4 Взаимодействие процессов
4.1 Сигналы
Программные прерывания, предоставляющие механизм для обработки асинхронных событий. Такие события могут инициироваться пользователем (нажатие клавиш ctrl+c) или возникать вследствие действий в программе или ядре.
Отличительная особенность сигналов состоит в том, что они появляются асинхронно, и обработка их производится тоже асинхронно. Могут быть написаны функции обработки сигналов, эти функции регистрируются процессом в ядре операционной системы, а операционная система инициирует выполнение этих функций при получении соответствующих сигналов в соответствии с установленными правилами обработки.
Сигналы имеют определенный жизненный цикл:
состояние, связанное с генерированием (отправлением, поднятием) сигнала:
generate //
send // смысл: сигнал появился
raise //
состояние хранения (store) – ядро операционной системы хранит его до тех пор, пока не появляется условие для доставки сигнала. И после того, как соответствующие условия создаются, ядро инициирует (обрабатывает) поступивший сигнал.
Ядро может выполнить 3 действия связанные с обработкой сигнала:
Игнорирование сигнала. //сигнал направлен процессу, но действий нету. НО есть ряд сигналов, которые нельзя игнорировать:
SIGKILL //связаны с остановкой или «убийством» процесса
SIGSTOP
Выполнить действие по умолчанию.
Для всех сигналов предусмотрены действия, которые выполняются по умолчанию. Это или завершение процесса, или может быть действие игнорировать сигнал, захватить и обработать сигнал. Процесс прерывается, и запускается функция обработчик
Установление собственного обработчика
Написать функцию обработчик и зарегистрировать её. Но есть некоторые сигналы, которые нельзя описать самостоятельно. Ядро приостанавливает текущее выполнение процесса, и переходит к выполнению ранее зарегистрированной функции. После завершения выполнения функции ядро продолжает обрабатывать остановленный исходный процесс.
Все сигналы имеют символическое имя. Все символические имена описаны в <signal.h> и начинаются с префикса SIG. Сигналы имеют номера (целочисленные). Общее число сигналов системы порядка 30.
SIGKILL |
завершить мгновенно, отправляется системным вызовом kill() |
завершить процесс |
SIGSTOP |
остановить сигнал |
остановить процесс |
SIGALARM |
отправляется процессу при завершении времени установленного функцией alarm(). |
завершить процесс |
SIGHUP |
ядро оправляет лидеру сеанса, когда терминал сеанса отключается. Также этот сигнал отправляется всем процессам приоритетной группы, когда лидер сеанса завершается (пользователь выходит из системы) |
завершить процесс |
SIGINT |
отправляется всем процессам приоритетной группы, при нажатии CTRL+C. Можно написать обработчик. |
завершить процесс |
SIGUSR1
|
Используются только пользователями. могут использоваться для взаимодействия с процессом демоном. Можно написать обработчик |
завершить процесс |
SIGUSR2 |
Методика асинхронного механизма получения и обработки сигнала: обработка сигнала производится во время приостановки самого процесса.
Системный вызов установки обработчика на сигнал
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signo, sighandler_t handler)
Позволяет зарегистрировать обработчик для сигнала, указанного в качестве первого аргумента. Второй аргумент - адрес функции обработчика. В качестве второго аргумента могут использоваться также:
SIG_DFL//восстановить поведение по умолчанию для сигнала signo.
SIG_IGN//игнорировать сигнал, указанный параметром signo
Функция signal() возвращает предыдущее поведение сигнала, которое может принимать вид указателя на обработчик сигнала, SIG_DFL или SIG_IGN. При ошибке возвращается значение SIG_ERP. Переменная errno не устанавливается.
Функция ожидания:
#include <unistd.h>
int pause (void);
выполнение процесса приостанавливается, пока не будет получен сигнал, допускающий либо обработку, либо завершение процесса. Функция возвращает значение только тогда, когда получен сигнал, который перехватывается, и возвращается -1, а переменная errno = EINTR.
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
static void sig_hand(int signo)
{signal (signo, sig_hand);
if (signo == SIGINT) printf(“получен сигнал SIGINT ”);
else if (signo == SIGTERM) printf(“ получен сигнал SIGTERM”)
else {printf(“неописанный сигнал”); exit(EXIT_FAILURE);}
exit(EXIT_SUCCESS);}
int main()
{
if (signal (SIGINT, sig_hand) == SIG_ERR) {printf(“ошибка SIGINT”);
exit(-1);}
if (signal(SIGTERM, sig_hand) == SIR_ERR) {printf(“ошибка SIGTERM”);
exit(-2);}
if (signal(SIGHUP, SIG_IGN) == SIR_ERR) {printf(“невозможно игнорировать SIGHUP”);
exit(-3);}
for (;;) pause();
}
Когда порождается новый процесс, для него устанавливается поведение всех сигналов по умолчанию, если только родительский процесс не игнорирует какие-то сигналы. Таким образом, новый процесс выполняет действие по умолчанию для всех сигналов захватываемых предком, а все прочие сигналы не вызывают действий
#include <signal.h> <stdlib.h> <stdio.h> <unistd.h>
if (signal(SIGINT, SIG_IGN) != SIGIGN)
{if (signal(SIGINT, sigint_handler) == SIG_ERR) {…}}
Свойство игнорирования сигналов порожденным процессом, заимствованное у родительского процесса, можно использовать для создания фоновых процессов. Для этого перед тем как фоновый процесс запускается для сигналов SIGINT & SIGQUIT, устанавливается игнорирование этих сигналов. Поэтому процессы, которые производят перехват этих сигналов перед установкой обработчика проверяют, не было ли установлено игнорирование для этих сигналов.