- •Кафедра программного обеспечения информационных технологий
- •«Операционные системы и системное программирование»
- •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.8 Системный вызов system
#include <stdlib.h>
int system (const char * comand);
Позволяет выполнить заданную инструкцию в командном интерепретаторе. Это действие можно рассматривать как запуск процесса и ожидание его завершения. Дейтвие функции равносильно действию строки:
/bin/sh –c comand
Можно реализовать это действие, не используя функцию system:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int my_system (const char * cmd) {
int status;
pid_t pid;
pid = fork();
if (pid == -1) exit(-1);
else
if (pid == 0) {
const char * argv[4];
argv[0] = “sh”;
argv[1] = “-c”;
argv[2] = “cmd”;
argv[3] = “NULL”;
execv (“/bin/sh”,argv);
exit (-1);
}
if (waitpid (pid, &status, 0) == -1) exit (-1);
else
if (WIFEXITED(status)) exit(WEXITSTATUS(status));
exit (0);
}
В отличие от system здесь не блокируются никакие сигналы.
3.9 Основные параметры, передаваемые процессу
идентификатор самого процесса и идентификатор родительского процесса.
идентификатор пользователя и группы (владение процессом). Имеется понятие реального и действительного (эффективного) идентификаторов для пользователя и группы. Под реальным понимается идентификатор, который запускал процесс, а под действительным (эффективным) – идентификатор пользователя, который использовался при проверке прав доступа процесса к ресурсу.
В большинстве случаев реальный и эффективный идентификаторы – это одно и то же.
Имеется набор системных вызовов, позволяющих установить реальный и эффективный идентификаторы пользователя и группы:
#include <unistd.h>
#include <sys/types.h>
uid_t geteuid(void); // эффективный
gid_t getegid(void); // эффективный
uid_t getuid(void); // реальный
gid_t getgid(void); // реальный
Сеанс пользователей – показывает, кто из пользователей подключен к системе и работает с процессом.
3.10 Сеансы и группы процессов
Каждый процесс входит в состав какой-либо группы процессов (одной или нескольких). Принадлежность к группе позволяет организовать более плотное взаимодействие между процессами. Один процесс может послать сигнал всем процессам, входящим в определенную группу. Каждая группа имеет идентификато группы (Process group ID). Идентификатор группы – это идентификатор процесса, являющегося лидером этой группы.
Когда новый пользователь входит в систему, создается новый сеанс, состоящий из одного процесса, которым является командный интерпретатор или командная оболочка. Этот процесс выполняет роль лидера сеанса, и его идентификатор является идентификатором сеанса.
Сеанс по крайней мере содержит одну группу процессов, но может содержать еще несколько фоновых групп процессов. Сеансы упорядочивают действия зарегистрированного в системе пользователя и связывают пользователя с управляющим терминалом.
Группа, которая является обязательной для сеанса называется приоритетной группой. Когда пользователь выходит из сеанса (отключается от терминала) всем процессам приоритетной группы отправляется сигнал SIGQUIT. Если пользователь нажимает Ctrl+C, всем процессам приоритетной группы посылается SIGINT.
Команды, заданные пользователем в запущенном терминале, образуют новые группы, относящиеся к одному и тому же сеансу.
Существуют системные вызовы, помогающие определить значения идентификаторов сеанса и идентификаторов группы процессов:
#include <unistd.h>
pid_t getsid (pid_t pid);
pid_t setsid (void);
pid_t getpgid (pid_t pid);
int setpgid (pid_t pid, pid_t gpid);
возвращает идентификатор сеанса для процесса, указанного в качестве аргумента. Если в качестве аргумента указан 0, то возвращает идентификатор сеанса, вызвавшего процесс
создает новый сеанс, вызываемый процесс не должен быть лидером какой-либо группы процессов, т.к. в результате выполнения он становится лидером созданного сеанса, единственным процессом в этом сеансе, причем у этого процесса (а соответственно и у сеанса) не будет управляющего устройства. Этот системный вызов также создает новую группу процессов и вызывающий процесс становится лидером этой новой группы. При успешном завершении возвращается идентификатор созданного сеанса, при ошибке -1
возвращает идентификатор группы для процесса, указанного в качестве аргумента. Если в качестве аргумента указан 0, то возвращает идентификатор группы для текушего процесса
заносит процесс, заданный идентификатором (первым аргументом), в группу, идентификатор которой задан вторым аргументом. Если pid=0, то используется идентификатор вызывающего процесса. Если pid и pgid равны, то процесс становится лидером группы. Если pgid=0, то в качестве идентификатора группы используется значение pid. в случае ошибки функция возвращает -1.
К атрибутам процесса также относится программное окружение, текущий рабочий каталог. При необходимости смены рабочего каталога используется функция
int chroot (const char * path);
при успешном завершении вызова, если в программе указать путь «./», поиск начнется с заданного пути.
Также в качестве атрибутов есть приоритет процесса. Значение приоритета находится в диапазоне от -20 до +19. ОС планирует выполнение процессов с учетом их приоритетов. Изменить текущий приоритет процесса можно при помощи вызова:
#include <unistd.h>
int nice (int i);
Число i указывает, на сколько необходимо изменить текущий приоритет: т.е. если i=-5, то уменьшить на пять, если i=4, то увеличить на четыре. Вызов возвращает измененное значение приоритета.
Только системные процессы могут уменьшать приоритет.
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fentl.h>
#include <unistd.h>
#include <linux/fs.h>
int main () {
pid_t pid;
int I;
pid = fork();
if (pid == -1) exit (-1);
else if (pid != 0) exit (EXIT_SUCSESS);
if (setsid() == -1) exit (-1);
if (chdir(“/”) == -1) exit (-1);
for (i=0; i<NR_OPEN; i++) close (i);
open (“/dev/null”, O_RDWR); dup(0); dup(0);
// действия процесса
exit (-1);
}
Процессы демоны – это процессы, которые выполняются в фоновом режиме. Они не подключены ни к одному из терминалов. Они обычно запускаются во время загрузки системы от имени суперпользователя или другого специального пользователя. В основном они предназначены для решения системных вопросов. К процессам-демонам предъявляются 2 требования:
- они должны выполняться как потомки процесса инициализатора
- они не должны быть связаны с терминалом
Для создания процесса-демона необходимо:
выполнить вызов fork
в родительском процессе выполнить exit
выполнить системный вызов setsid, создав тем самым новый сеанс, новую группу процессов. Тем самым и в сеансе и в группе лидером становится созданный процесс. Это гарантирует, что процесс не связан с терминалом
рабочий каталог меняется на корневой для того, чтобы вызывающиеся процессы могли работать с любыми каталогами
закрыть все открытые файлы
открыть стандартные дескрипторы ввода/вывода и сообщения об ошибках и перенаправить вывод на 0-е устройство