
- •1.Архитектура операционных систем
- •1.1Общие вопросы архитектуры операционных систем
- •1.2Архитектура Windows
- •1.2.1История возникновения Windows
- •1.2.2Архитектура ос Windows
- •1.2.3История возникновения ос Linux
- •1.2.4Архитектура Linux
- •1.2.5Интерфейсы системы unix
- •1.2.6Файловая система unix
- •1.2.7Аутентификация в unix
- •1.2.8Сценарии командной оболочки unix
- •1.3Операционная система qnx
- •1.3.1 Архитектура qnx
- •1.4Выводы
- •1.5Вопросы для самоконтроля
- •2.Типы и алгоритмы работы с оперативной памятью
- •2.1Общие принципы функционирования подсистемы памяти в ос
- •2.1.1Обобщённые принципы управления памятью
- •2.1.2Однозадачная система без подкачки на диск
- •2.1.3Многозадачность с фиксированными разделами
- •2.1.4Подкачка
- •2.1.5Управление памятью с помощью битовых массивов
- •2.1.6Управление памятью с помощью связанных списков
- •2.1.7Виртуальная память
- •2.1.8Многоуровневые таблицы страниц
- •2.1.9Алгоритмы замещения страниц
- •2.2Виртуальная память ос Windows
- •2.2.1Архитектура памяти в ос Windows
- •2.2.2Работа с виртуальной памятью в ос Windows
- •2.2.3Использование виртуальной памяти в приложениях
- •2.3Пример организации страничной памяти на примере linux
- •2.3.1Страничная организация памяти в Linux
- •2.3.2Права доступа к области памяти
- •2.3.3Работа с областями памяти в Linux
- •3.Процессы и потоки
- •3.1Процессы
- •3.1.1Модель процесса
- •3.1.2Создание процесса
- •3.1.3Завершение процесса
- •3.1.4Состояния процессов
- •3.1.5Реализация процессов
- •3.2Потоки
- •3.2.1Реализация потоков
- •3.2.2Реализация потоков на уровне ядра
- •3.2.3Смешанная реализация
- •3.2.4 Метод управления «Активация планировщика»
- •3.2.5Всплывающие потоки
- •3.3Межпроцессное взаимодействие
- •3.3.1Состояние состязания
- •3.3.2Критические секции (Критические области)
- •3.3.3Взаимное исключение с активным ожиданием
- •3.3.4Примитивы межпроцессного взаимодействия
- •3.4Семафоры
- •3.5Мьютексы
- •3.6Организация многопоточной обработки в среде Windows
- •3.6.1Объекты ядра Windows
- •3.6.2Потоки Windows
- •3.6.3Синхронизация потоков в Windows
- •3.6.4Синхронизация потоков с помощью объектов ядра
- •3.6.5Сравнение объектов, используемых для синхронизации потоков
- •3.7Организация процессов и потоков в Linux
- •3.7.1Среда окружения в Linux
- •3.7.2Создание нового процесса. Системный вызов exec.
- •3.7.3Потоки unix. Функции потоков стандарта posix.
- •3.8Синхронизация потоков в unix
- •3.8.1Мьютексы
- •3.8.2Семафоры
- •0,0,0, //Ожидать обнуления семафора
- •0,1,0 // Затем увеличить значение семафора на 1};
- •0,1, 0 // Увеличитьзначение семафора на 1};
3.8Синхронизация потоков в unix
3.8.1Мьютексы
Синхронизация потоков осуществляется с помощью мьютексов. Мьютексы создаются с помощью системных вызовов pthread_mutex_init и уничтожаются - pthread_ mutex_destroy.
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex,
const pthread_mutexattr_t *attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
Поток блокирует мьютекс с помощью вызова pthread_ mutex_lock. Разблокирование - pthread_ mutex_unlock.
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
Мьютексы предназначены для кратковременной блокировки, например для защиты совместно используемой переменной. Они не предназначены для долговременной синхронизации, например для ожидания, когда освободиться накопитель на магнитной ленте. Для долговременной синхронизации предоставляются переменные состояния. Создаются с помощью вызова pthread_ cond _init и уничтожаются вызовом pthread_cond_destroy.
#include <pthread.h>
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
Переменные состояния используются следующим образом: один поток ждет, когда переменная примет определенное значение, а другой поток сигнализирует ему об изменении этой переменной. Например, обнаружив, что накопитель на магнитной ленте занят, поток может обратиться к вызову pthread_cond_wait, задав в качестве параметра адрес переменной, которую все потоки договорились связать с накопителем на магнитной ленте. Когда поток, использующий накопитель на магнитной ленте, освободит этот устройство (возможно через несколько часов), он обращается к вызову pthread_cond_signal, чтобы изменить переменную состояния и тем самым сообщить вызывающим потокам, что магнитофон свободен. Если ни один поток в этот момент не ждет, когда освободится накопитель, то сигнал просто теряется. Другими словами переменные состояния не считаются семафорами.
3.8.2Семафоры
Для нормальной работы семафора необходимо выполнение следующих условий:
1. Значение семафора должно быть доступно различным процессам. Семафор находится в адресном пространстве ядра.
2. Единственным способом гарантировать атомарность критических участков операций является выполнение этих операций в режиме ядра.
Семафоры SYSTEM V обладают следующими характеристиками:
Семафор представляет собой не один счетчик, а группу, состоящую из нескольких счетчиков, объединенных общими признаками (например, дескриптором объекта, права доступа т.д.)
Каждое из этих чисел может принимать любое неотрицательное значение в пределах, определенных системой ( а не только значения 0 и 1).
Для каждой группы семафоров ядро поддерживает структуру данных semid_ds, включающую следующие поля:
Таблица 3.4. Структура семафоров в ядре
Поле |
Данные |
sem_perm |
Данные, хранящиеся в записи struct semid_ds |
sem_nsems |
Число семафоров в наборе |
sem_base |
Указатель на массив семафоров |
sem_otime |
Время, когда какой-либо процесс в последний раз выполняет операции над семафорами |
sem_stime |
Время, когда тот или иной процесс в последний раз изменяет управляющие параметры набора.
|
Значение конкретного семафора из набора хранится во внутренней структуре sem
Таблица 3.5. Внутренняя структура sem.
Поле |
Данные |
Semval |
Целочисленное значение текущего семафора |
Sempid |
Идентификатор процесса, который выполнял операции над данным семафором в последний раз |
Semncnt |
Число процессов, которые заблокированы и ожидают увеличение значения семафора |
Semzcnt |
Число процессов, которые заблокированы и ожидают обращения значения семафора в нуль. |
Помимо собственно значения семафора, в структуре sem хранится идентификатор процесса, вызвавшего последнюю операцию над семафором, число процессов, ожидающих увеличение значения семафора, и число процессов, ожидающих, когда значение семафора станет равным нулю.
Набор семафоров
s
truct
semid_ds, struct
sem struct
sem
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Таблица семафоров
Рис 5.1. Структура данных ядра, используемая для манипулирования семафорами.
Как и сообщения, семафоры хранятся в адресном пространстве ядра и являются устойчивыми, т.е. сохраняются независимо от завершения создавшего их процесса. У каждого набора семафоров есть назначенный владелец, и удалить набор или изменить его управляющие параметры могут только процессы, имеющие право привилегированного пользователя, создателя набора или назначенного владельца. Если набор семафоров удаляется, то ядро активизирует все процессы, которые в данный момент заблокированы семафорами этого набора; все произведенные данными процессами системные вызовы прерываются и возвращают код неудачного завершения, -1.
В ОС UNIX SYSTEM V имеются три API, предназначенные для манипулирования семафорами
API |
Назначение |
Semget |
Открытие и создание набора семафоров |
Semop |
Запрос и изменение значение семафора |
Semctl |
Запрос и изменение управляющих параметров набора семафоров, удаление набора. |
Для этих API необходимы следующие файлы заголовков:
#include<sys/types.h>
#include<sys/ips.h>
#include<sys/sem.h>
Функция semget
int semget( key_t key, int num_sem, int flag);
Функция открывает набор семафоров, идентификатор которого задан значением аргумента key, и возвращает неотрицательный целочисленный дескриптор. Его можно использовать в других API семафоров, а также для запроса и установки управляющих параметров набора семафоров.
Если значение аргумента key – положительное целое, рассматриваемый API пробует открыть набор семафоров, ключевой идентификатор совпадает с указанным значением. Если же значением key является макрос IPC_PRIVATE, API создает новый набор семафоров, который будет использоваться исключительно вызывающим процессом. Такие «частные» семафоры обычно выделяются родительским процессом, создающим один или несколько порожденных процессов. Родительский и порожденный процессы пользуются этими семафорами для синхронизации своей работы.
При нулевом значении flag API прерывает свою работу, если отсутствует набор семафоров, ключевой идентификатор которого совпадает с указанным значением key; в противном случае возвращается дескриптор этого набора. Если процессу необходимо создать новый набор с идентификатором key (и набора с таким идентификатором нет), то значение аргумента flag должно представлять собой результат побитового логического сложения константы IPC_CREAT и числовых значений прав доступа к этому набору для чтения и записи.Значение num_sem может быть равно нулю, если флаг IPC_CREAT в аргументе flag не указан, или числу семафоров во вновь создаваемом наборе.
Пример.
int semd=semget(15, 2, IPC_CREAT | 0544);
Вызов создает двухсемафорный набор с идентификатором 15
Для гарантированного создания нового набора семафоров можно указывать одновременно с флагом IPC_CREAT флаг IPC_EXCL. Тогда API будет успешно выполнен только в том случае, если он создаст новый набор с заданным значением key. В случае неудачи возвращает –1.
Функция semop
int semop(int semid, struct sembuf * opPtr , int nops);
В качестве второго аргумента функции передается указатель на структуру данных, определяющую операции, которые требуется произвести над семафором с дескриптором semid. Операций может быть несколько и их число указывается в последнем аргументе nops. Ядро обеспечивает атомарность всех операций . указанных в этой структуре.
Тип данных struct sembuf определяется в заголовке <sys/sem.h>
struct sembuf
{
short sem_num;// индекс семафора
short sem_op;// операция над семафором
short sem_flg;// флаги операции
}
Переменная sem_op может иметь следующие значения
Значение semop |
Смысл |
Положительное число |
Увеличить значение указанного семафора на эту величину |
Отрицательное число |
Процесс ожидает, пока значение семафора не станет большим либо равным по абсолютной величине semop. Затем абсолютная величина semop вычитается из значения семафора |
0 |
Процесс ожидает, пока семафор не обнулится. |
При работе с семафорами взаимодействующие процессы должны договорится об их использовании и кооперативно проводить операции над семафорами. При работе с семафорами процессы используют различные комбинации из трех операциях, по своему трактуя значения семафоров.
Пример №1: 0 – разрешающее значение; 1 – запрещающее
Операция, запирающая ресурс выглядит следующим образом:
static struct sembuf sop_lock[2]={