- •Кафедра программного обеспечения информационных технологий
- •«Операционные системы и системное программирование»
- •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
3.6 Копирование при записи
В ранних реализациях UNIX систем при ветвлении процессов ядро создавало копии всех внутренних структур данных, дублировало записи таблицы страниц процесса, а затем выполняло копирование родительского адресного пространства в новое адресное пространство. Это требовало значительных временных затрат и затрат ресурсов системы.
Современные ОС вместо полного копирования родительского адресного пространства используют страницы памяти со свойством копирования при записи. Подход копирования при записи предполагает, что страница памяти, которую совместно используют несколько родственных процессов, будет копироваться только в том случае, когда этот новый процесс инициирует изменения данных в этой новой странице. В современных вычислительных машинах предполагается аппаратная поддержка реализации таких действий.
3.7 Системные вызовы ожидания завершения процесса
Прототипы:
#include <sys/waith>
pid_t wait(int *status_p);
pid_t waitpid(pid_t child_pid, unt *status_p, int options);
Родительский процесс использует системные вызовы wait и waitpid для перехода в режим ожидания завершения порождённого процесса и для выборки его статуса завершения. Эти вызовы также освобождают ячейку таблицы процессов, соответствующую порождённому процессу.
Функция wait приостанавливает выполнение родительского процесса до тех пор, пока ему не будет послан сигнал, либо пока один из его порождённых процессов не завершится или не будет остановлен.
Если порождённый процесс уже завершился до вызова wait, то wait немедленно завершится и возвратит статус завершившегося процесса, который будет хранится в status_p, а возвращённое значение будет иметь значение PID завершившегося процесса.
Если родительский процесс не имеет порождённых процессов, завершения которых он ожидает, или был прерван сигналом при выполнении wait, то wait возвратит значение равное -1, а в errno будет находится код ошибки. Если было порождено более одного процесса, то wait будет ожидать завершения любого из них.
Пример:
/* ожидание завершения дочерного процесса вызовом wait */
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
main()
{ pid_t pid
int status,exit_status;
if ((pid=fork())<0)
{ printf(“Ошибка fork\n”); exit(1); };
if (pid==0)
{ sleep(10); exit(2); };
if ((pid=wait(&status))==-1)
{ printf(“Ошибка wait\n”); exit(3); }
if (WIFEXITED(&status)) // завершен ли системным вызовом _exit
{
exit_status=WEXITSTATUS(status);
printf(“Статус завершения процесса %d равен %d\n”,pid,exit_status);
}
exit(0);
}
Функция waitpid более сложная и универсальная. В этой функции можно указать, завершения какого из порождённых процессов следует ожидать.
Параметр child_pid может содержать следующие значения:
> 0 - ожидать завершения процесса с этим PID;
-1 - ожидать завершения любого порождённого процесса;
0 - ожидать завершения любого порождённого процесса, принадлежащего к той же группе, что и родительский процесс;
< -1 - ожидать завершения любого порождённого процесса, идентификатор группы которого равен абсолютному значению аргумента.
Третий аргумент (option) определяет модификацию вызова waitpid.
WNOHANG - не блокирующий вызов, т.е. функция немедленно возвращает управление, если нет завершённого процесса, отвечающего критериям ожидания. В противном случае функция будет блокирующей.
WUNTRACED - функция будет ожидать завершения порождённого процесса, остановленного механизмом управления заданиями, но о статусе которого не было ранее сообщено. Если status_p равен NULL, то нет необходимости запрашивать статус завершения порожденного процесса. Если в status_p хранится адрес переменной типа int, то в неё будет помещён статус завершения порождённого процесса.
Родительский процесс может проверить это значение с помощью нескольких макроопределений:
WIFEXITED (*status_p) возвращает ненулевое значение, если порождённый процесс был завершён с помощью _exit, иначе возвращает ноль.
WEXITSTATUS (*status_p) возвращает код завершения порождённого процесса, присвоенного _exit. Это макроопределение следует использовать только тогда, если WIFEXITED возвращает ненулевое значение.
WIFSIGNALED (*status_p) возвращает ненулевое значение, если порождённый процесс был завершён по получению прерывающего сигнала.
WTERMSIG (*status_p) возвращает номер сигнала, завершившего порождённый процесс, если WIFSIGNALED вернуло ненулевое значение.
WIFSTOPPED (*status_p) возвращает ненулевое значение, если порождённый процесс был остановлен механизмом управления заданиями
WSTOPSIG (*status_p) возвращает номер сигнала, завершившего порождённый процесс, если WIFSTOPPED вернуло ненулевое значение.
Если возвращаемое wait или waitpid значение положительное, то это - идентификатор порождённого процесса. Иначе возвращается - 1.Тогда errno может быть:
ECHILD - для wait процесс не имеет порождённых процессов, завершение которого он ожидает, а для waitpid это означает, что либо значение child_pid недопустимо, либо процесс не может находиться в состоянии, определённом в option.
EFAULT - аргумент status_p указывает на недопустимый адрес.
EINVAL - значение option недопустимо.
EINTR – во время ожидания был получен сигнал.
/* ожидание завершения дочерного процесса вызовом waitpid */
#inckude <iostream.h>
#inckude <stdio.h>
#inckude <sys/types.h>
#inckude <sys/wait.h>
#inckude <unistd.h>
int main()
{ pid_t child_pid, pid; int status;
switch (child_pid=fork())
{
case (pid_t) -1 : printf(“|nОшибка fork”); break;
case (pid_t) 0 : printf(“\nПроцесс-сын создан”); _exit(15);
default : printf(\n“Процесс-отец %d”);
pid=waitpid(child_pid, &status, WUNTRACED));
}
if ( WIFEXITED(status) )
printf(“\n Статус завершения %d”, WEXITSTATUS(status));
else
if ( WIFSTOPPED(status) )
printf(“\n Номер сигнала %d”,WSTOPSIG(status));
else if ( WIFSIGNALED(status) )
printf(“\n Номер перехваченного сигнала %d”,WTERMSIG(status));
else printf(“\n Ошибка waitpid!”);
_exit(0);
return(0);
}