Разработка операционных систем

Модель операционной системы реального времени, обладающая указанным типом планировщика, алгоритмом планирования, управлением ресурсами и событиями, максимальным количеством приоритетов. Написание тестов, проверяющих соответствие проекта этим свойствам.

Рубрика Программирование, компьютеры и кибернетика
Вид контрольная работа
Язык русский
Дата добавления 22.03.2014
Размер файла 237,8 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

1

Оглавление

операционный алгоритм планировщик

  • 1. Постановка задачи

2. Операционная система реального времени

3. Требования к функционалу

4. Код программы

5. Результаты работы

Выводы

1. Постановка задачи

Необходимо реализовать модель операционной системы реального времени, обладающей следующими свойствами:

Тип планировщика: POSIX

Алгоритм планирования: nonpreemptive, RMA

Управление ресурсами: простые семафоры

Управление событиями: события принадлежат задаче

Обработка прерываний: нет

Максимальное количество задач: 32

Максимальное количество приоритетов: 16

Максимальное количество ресурсов: 16

Максимальное количество событий: 16

Кроме того, в задание входит написание тестов, проверяющих соответствие проекта этим свойствам.

2. Операционная система реального времени

Операционная система реального времени (ОСРВ) - программа, распределяющая вычислительные ресурсы таким образом, чтобы обеспечить выполнение требований реального времени для приложения, использующего ОСРВ.

Управление задачами

Состояние задачи

В любой момент времени задача может находиться в одном (и только одном) из следующих состояний:

Выполняется (running). Задача назначена на выполнение и использует процессор для последовательного исполнения своих инструкций. Только одна задача может находиться в этом состоянии в заданный момент времени.

Активна (ready). Задача получила все необходимые для выполнения ресурсы (память, стек и т. п.) и ожидает назначения на выполнение. Только из этого состояния задача может перейти в состояние running.

Приостановлена (suspended, применяется также термин inactive). В этом состоянии задача пассивна, не занимает системных ресурсов и не может быть назначена на выполнение.

Состояние ожидания (waiting). Задача ждет наступления некоторого события.

Активизация задачи

Активизация задачи осуществляется сервисом ActivateTask. При этом задача переходит из состояния suspended в состояние ready, после чего может быть назначена на выполнение. Не допускается наличие нескольких работающих копий одной задачи, т.е. повторная активизация задачи допускается только после завершения работы предыдущей копии этой задачи.

Приоритеты и переключение задач

Поскольку ОСРВ выполняется в однопроцессорной системе, но может выполнять более одной задачи, необходимо назначать задачи на процессор по очереди. Последовательность назначения задач на процессор определяется планировщиком. Планировщик должен быть реализован в соответствии с конкретным алгоритмом планирования, определенным в индивидуальном задании. Собственно переключение с одной задачи на другую выполняется диспетчером.

Диспетчер вызывается в одном из следующих случаев:

Завершение задачи

Активизация задачи другой задачей (но не обработчиком прерывания)

Завершение обработчика прерывания.

Освобождение/захват ресурса одной из задач.

Установка/начало ожидания события

Планирование и диспетчеризация в системах реального времени должно удовлетворять следующим требованиям:

· строгое соблюдение дисциплины планирования

· полное исключение инверсии приоритетов между задачами (за исключением специальных планировщиков - например, невытесняющих)

· сохранение контекста задачи при вытеснении ее с процессора

· восстановление контекста задачи при назначении ей процессора

· минимально возможное потребление ресурсов - памяти и процессорного времени

Завершение задачи

В рассматриваемой ОСРВ задача не может завершить другую задачу. Кроме того, каждая задача обязана завершить саму себя вызовом системного сервиса TerminateTask. В противном случае поведение ОС не определено.

Управление ресурсами

Организация управления ресурсами

Управление ресурсами используются для организации совместного использования разделяемых ресурсов (общих областей памяти, аппаратных средств и т. п.) несколькими задачами.

Для управления ресурсами используются системные сервисы для обозначения начала использования ресурса (P) и для обозначения его конца (V). Вызовы этих сервисов ограничивают критическую секцию в пользовательской задаче. Любое использование ресурса задачей допускается только внутри критической секции.

ОСРВ должна обеспечивать неограниченную вложенность критических секций. Другими словами, задача может захватить и удерживать произвольное количество ресурсов одновременно. На порядок освобождения захваченных ресурсов также не накладывается никаких ограничений.

Простые семафоры

Семафоры - это объекты, находящиеся в диапазоне целых чисел, которые поддерживают две операции, P() и V(). Примитив P() применяется для декремента (уменьшения на единицу) значения семафора, если новое значение оказывается меньше нуля, то он блокируется. Операция V() используется для инкремента значения, при этом если результат оказывается равным нулю или больше, то V() пробуждает процесс. Эти операции являются неделимыми.

Рассмотрим применение семафоров на примере. Допустим, имеется разделяемый ресурс (файл). Необходимо блокировать доступ к ресурсу для других процессов, когда некий процесс производит операцию над ресурсом (например, записывает в файл). Для этого свяжем с данным ресурсом некую целочисленную величину - счетчик, доступный для всех процессов. Пусть, значение счетчика 1 означает доступность ресурса, а 0 - его недоступность. Тогда перед началом работы с ресурсом процесс должен проверить значение счетчика. Если оно равно 0 - ресурс занят и операция недопустима - процессу остается ждать. Если значение счетчика равно 1 - можно работать с ресурсом. Прежде всего, процессу необходимо заблокировать ресурс, т.е. изменить значение счетчика на 0. После выполнения операции для освобождения ресурса значение счетчика необходимо изменить на 1. В приведенном примере счетчик играет роль семафора.

Семафоры используются для доступа к критическим секциям кода. Семафор называется простым, если в каждый момент времени только одна задача или процесс может активировать его.

Ограничения при управлении ресурсами

Хотя вложенный захват ресурсов является допустимым, запрещается вложенный захват задачей одного и того же ресурса.

Не допускается применение сервиса TerminateTask и WaitEvent внутри критической секции. Перед завершением задача обязана освободить все захваченные ресурсы.

Управление событиями

Механизм событий является способом синхронизации (события могут использоваться, например, для сигнализации истечения заданного интервала времени на таймере или приема сообщения) и инициирует перемещение задачи в и из состояния waiting.

События принадлежат задаче

Любое событие в системе должно принадлежать задаче (только одной). Каждой задаче может принадлежать не более 16 событий. События, принадлежащие одной задаче, имеют идентификаторы EVENT_1, EVENT_2, … . Любое событие системы однозначно идентифицируется парой «Задача:Идентификатор».

Каждая задача может ожидать одно или несколько из своих событий. Эти события задаются маской событий, которая является структурой данных типа TEventMask. Формирование маски осуществляется операцией add_mask. Например (маска на события 1 и 12):

TEventMask mask;

mask= EVENT_1 add_mask EVENT_12;

Каждая задача имеет две маски:

Маска ожидаемых событий.

Маска произошедших (установленных) событий.

Задача, находящаяся в состоянии выполнения, может начать ожидание событий задаваемых маской и перейти в состояние waiting (предыдущая маска ожидания должна быть сброшена). Если для этой задачи будет установлено, хоть одно из ожидаемый событий, задача перейдет в состояние ready (возможно running). В маске ожидаемых событий признаки ожидания произошедших событий должны быть сброшены, признаки ожидания остальных событий должны быть оставлены. В маске произошедших событий признаки произошедших событий, ожидаемых задачей (события которых «дождалась» задача) должны быть сброшены до перехода задачи в состояние ready (возможно running).

Установка событий, не ожидаемых задачей, не должна приводить к изменению состояния задачи.

Если к моменту начала ожидания хоть одно из ожидаемых событий установлено состоянии задачи не должно измениться (то есть задача не переводится в состояние waiting и в этом случае не вызывается планировщик). При этом установленные признаки события должны быть очищены, маска ожидаемых событий должна быть изменена в соответствии с приведенными правилами.

События любой задачи могут устанавливаться любой другой задачей. Маски установленных событий задачи также могут быть прочтены любой задачей.

Ожидание событий допускается лишь задачей, которой эти события принадлежат. Очистка маски произошедших событий может осуществляться только задачей «владельцем» событий.

3. Требования к функционалу

Типы данных

При именовании типов используются следующая договорённость: имя типа должно начинаться с префикса “T”. Типы, применяемые в ОСРВ, перечислены в таблице 1.

Таблица 1: Типы данных

Тип

Описание

TTask

Идентификатор задачи

TSemaphore

Семафор

TEventMask

Маска событий

Макрос TASK

Макрос TASK используется для описания задачи (примерно так же, как описываются функции в языке С). Он имеет следующий синтаксис:

TASK(TaskID, TaskParam)

// Тело задачи

TerminateTask();

Здесь TaskID -- любой корректный идентификатор языка С, а TaskParam -- - параметр задачи, на основании которого принимается решение о приоритете задачи. Задача с идентификатором TaskID должна быть предварительно объявлена с использованием макроса DeclareTask. Удобство такого подхода заключается в том, что в дальнейшем задачу можно активизировать с использованием того же идентификатора TaskID, например:

DeclareTask(task1);

DeclareTask(task2);

TASK(task1)

{ActivateTask(task2);

TerminateTask();}

Управление задачами

DeclareTask

Синтаксис

DeclareTask(TaskID)

Параметры

TaskID -- идентификатор задачи, удовлетворяющий стандартным требованиям языка С.

Описание

Осуществляет регистрацию задачи в системе (назначение подобно объявлению глобальных функций в языке С). Должен вызываться ДО использования задачи в коде пользовательского приложения.

Особенности

-

ActivateTask

Синтаксис

void ActivateTask(TTask task)

Параметры

task -- идентификатор задачи, подлежащей активизации

Описание

Переводит задачу из состояния suspended в состояние ready

Особенности

Не допускается одновременное присутствие двух активных копий одной задачи.

TerminateTask

Синтаксис

void TerminateTask(void)

Параметры

-

Описание

Завершает выполнение текущей задачи, переводя её из состояния running в состояние suspended. При этом освобождаются все системные ресурсы, занятые задачей.

Особенности

Вызов этого сервиса всегда является последней инструкцией, которую выполняет задача.

Запрещается вызывать TerminateTask из критической секции задачи.

Завершение задачи без обращения к этому сервису также категорически запрещается.

Управление ресурсами

InitPVS

Синтаксис

void InitPVS(TSemaphore S)

Параметры

S - семафор

Описание

Инициализация семафора. Используется для задания начального состояния семафора (с каким ресурсом связан семафор, ресурс свободен). Должен вызываться до использования ресурса, связанного с семафором, в коде пользовательского приложения.

Особенности

Используется при управлении ресурсами с помощью P/V-семафоров.

P

Синтаксис

void P(TSemaphore S)

Параметры

S - семафор

Описание

Захват семафора. Вызов этого сервиса отмечает вход в критическую секцию. Выход из этой критической секции всегда должен осуществляться вызовом сервиса V.

Особенности

Используется при управлении ресурсами с помощью P/V-семафоров. Вызов TerminateTask из критической секции не допускается.

Запрещён также вложенный захват одного и того же ресурса.

V

Синтаксис

void V(TSemaphore S)

Параметры

S - семафор

Описание

Освобождение семафора. Вызов этого сервиса отмечает выход из критической секции и должен сопровождаться предварительным вызовом сервиса P.

Особенности

Используется при управлении ресурсами с помощью P/V-семафоров. Запрещено освобождать семафор, который ранее не был захвачен.

Управление событиями

DeclareEvent

Синтаксис

DeclareEvent(EventID)

Параметры

EventID -- идентификатор события, удовлетворяющий стандартным требованиям языка С.

Описание

Осуществляет регистрацию события в системе (назначение подобно объявлению глобальных функций в языке С). Должен вызываться ДО использования идентификатора события в коде пользовательского приложения.

Особенности

-

SetEvent

Синтаксис

void SetEvent(TTask task, TЕventMask mask)

Параметры

task - идентификатор задачи, для которой надо установить одно или более событий

mask - маска, согласно которой будут установлены события для задачи task

Описание

Устанавливает для задачи task события, задаваемые маской mask. При вызове данного сервиса задача task будет переведена в готовое состояние, если она ждала, хотя бы одного из событий, заданных маской mask.

Особенности

Любые события, не заданные в маске, останутся неизменны.

GetEvent

Синтаксис

void GetEvent(TTask task, TЕventMask* event)

Параметры

task - задача, чья маска событий должна быть возвращена

event - указатель на область памяти, куда будут помещены выходные данные

Описание

Возвращает текущее состояние маски установленных событий для задачи task (но не событий, которые задача ждет)

Особенности

-

WaitEvent

Синтаксис

void WaitEvent(TЕventMask mask)

Параметры

mask - маска ожидаемых задачей событий

Описание

Если не установлено ни одного события, заданного маской, то задача переводится в состояние ожидания. При выходе из данного сервиса должны быть сброшены те события, которые вызвали этот выход (то есть те из наступивших событий, наступления которых задача ждала), должно быть произведено удаление признаков ожидания этих событий

Особенности

Данный сервис может быть вызван только задачами, владеющими заданными в маске событиями

ClearEvent

Синтаксис

Void ClearEvent (TЕventMask mask)

Параметры

mask - маска очищаемых событий задачи

Описание

Сервис производит очистку признаков событий (в маске установленных событий задачи) в соответствии с параметром mask

Особенности

Данный сервис может быть вызван только задачами, владеющими событиями

Управление операционной системой

StartOS

Синтаксис

void StartOS(TTask task)

Параметры

task - задача, которую необходимо назначить на выполнение после инициализации системы.

Описание

Осуществляет необходимую инициализацию и запускает ОС на выполнение.

Особенности

Вызов этого сервиса возможен только «извне» ОС, то есть когда она ещё не начала свою работу.

Возврат из этой сервиса осуществляется только после вызова ShutdownOS из задачи, обработчика прерывания или внутренней функции ОС.

ShutdownOS

Синтаксис

void ShutdownOS(void)

Параметры

-

Описание

Используется для немедленного завершения работы системы.

Особенности

-

4. Код программы

Структура

Файл

Содержание

additional.cpp

Описание дополнительных процедур и функций, необходимых для работы

event.cpp

Управление событиями

global.cpp

Описание всех глобальных переменных

os.cpp

Управление операционной системой

resource.cpp

Управление ресурсами (реализация функционала простых семафоров)

task.cpp

Управление задачами (планировщик, диспетчер и т.д.)

test.cpp

Тесты для проверки правильности работы

rtos_api.h

Содержатся все макросы, описания типов, декларации функций и другие объекты, которые необходимо включать в пользовательское приложение,

Rtos_api.h

/****************************************/

/* rtos_api.h */

/****************************************/

#include <Windows.h>

#include <conio.h>

#include <stdio.h>

#define MAX_TASK 32

#define MAX_RES 16

#define MAX_PRIOR 16

#define MAX_EVENT 16

typedef struct Type_Mask

{bool mask[MAX_EVENT]; // маска событий

} TEventMask;

typedef struct Type_stack

{void *stack; // стек

int size; // рамер стека

} _stack;

typedef struct Type_Task

{int priority; // приоритет

int state; // состояние задачи

void (*entry)(void); // точка входа

char* name; // имя задачи

TEventMask mask_w; // маска ожидаемых событий

TEventMask mask_h; // маска произошедших событий

bool eventwaiting; // флаг ожидания события

bool semaphorewaiting; // флаг ожидагия семафора

CONTEXT context; // контекст задачи

_stack Rsp; // стек вызовов

} TTask;

typedef struct Type_runningtask

{int priority; // приоритет

int task; // номер задачи в очереди

} TRunningTask;

typedef struct Type_semaphore

{int sem_id; // идентификатор

int task_id; // идентификатор задачи

bool isfree; // состояние

} TSemaphore;

#define DeclareTask(TaskID, priority)\

TASK(TaskID); \

enum {TaskID##prior=priority}

#define DeclareResource(ResID, priority)\

enum {ResID=priority}

#define DeclareEvent(Event_ID, EventID)\

enum {Event_ID=EventID}

#define TASK(TaskID) void TaskID(void)

typedef void TTaskCall(void);

extern TTask TaskQueue[MAX_PRIOR][MAX_TASK]; // Очередь задач для POSIX планировщика, отдельная очередь на каждый приоритет

extern TRunningTask RunningTask; // Запущенная задача

extern TRunningTask FreeTask[MAX_TASK]; // Очередь свободных задач отсортированных по убыванию приоритетов

extern TRunningTask SemaphoreWaitingTask[MAX_TASK]; // Очередь задач, ожидающих освобождение семафора

extern TSemaphore Semaphore; // Семафор

extern void *SP; // Начало стека

extern bool RestoreStack; // Флаг, характеризующий необходимость восстанавления стека

extern HANDLE MainProcess; // Дескриптор процесса

void CheckTask(int prt, int tasknumber);

void ActivateTask(TTask tsk);

void TerminateTask(void);

void Schedule(int prt, int task);

void Dispatch(int prt, int task);

void InitializeTaskQueue();

int StartOS(TTask Task);

void ShutdownOS();

void InitPVS(TSemaphore semaphore);

void P(TSemaphore semaphore);

void V(TSemaphore semaphore);

void SetEvent(TTask *Task, TEventMask Mask);

void GetEvent(TTask Task, TEventMask *Mask);

void WaitEvent(TEventMask Mask);

void ClearEvent(TEventMask Mask);

void ClearMask(TTask *Task);

void ClearMask(TEventMask *Mask);

void Sort(TRunningTask *Task);

void InsertIntoQueue(TRunningTask *Task);

Additional.cpp

/*********************************/

/* additional.cpp */

/*********************************/

#include "rtos_api.h"

void Sort(TRunningTask *Task)

{TRunningTask Buf;

for(int i=0; i<MAX_TASK - 1; i++)

{if(Task[i+1].priority == -1) break;

Buf = Task[i];

Task[i] = Task[i + 1];

Task[i + 1] = Buf;}}

void InsertIntoQueue(TRunningTask *Task)

{int i = 0, j;

TRunningTask Bufo, Bufn;

for(i=0; i<MAX_TASK; i++)

{if(Task[i].priority<RunningTask.priority)

{if(Task[i].priority!=-1)

{j=i+1;

Bufo = Task[i];

while((Task[j].priority!=-1) & (j<MAX_TASK))

{Bufn = Task[j];

Task[j] = Bufo;

Bufo = Bufn;

}Task[j] = Bufo;

break;

}else break;}}

Task[i] = RunningTask;}

Event.cpp

/*******************************************************/

/* Управление событиями - события принадлежат задаче */

/*******************************************************/

#include <stdlib.h>

#include "rtos_api.h"

/* Генерация событий для задачи Task */

void SetEvent(TTask *Task, TEventMask Mask)

{int i = 0;

bool flag = false, comma = true;

printf("Setting for %s ", (*Task).name);

/* Устанавливаем маску произошедших событий */

for(int i=0; i<MAX_EVENT; i++)

{if(Mask.mask[i])

{if(comma) { printf("Event_%i", i + 1); comma = false; }

else printf(", Event_%i", i + 1);

(*Task).mask_h.mask[i] = Mask.mask[i];}

if(((*Task).mask_w.mask[i])&((*Task).mask_h.mask[i]))

{flag = true;

(*Task).mask_h.mask[i] = false;

(*Task).mask_w.mask[i] = false;}}

printf("\n");

if(flag)

{int TaskNumber = atoi(&(*Task).name[4]) - 1;

Schedule((*Task).priority, TaskNumber);}

printf("Setting events for %s completed\n", (*Task).name);}

void GetEvent(TTask Task, TEventMask *Mask)

{(*Mask) = Task.mask_h;}

/* Для вызвавшей задачи устанавливается маска ожидаемых событий, задаваемая Mask */

void WaitEvent(TEventMask Mask)

{bool flag = false, temp = false, comma = true;

int count = 0, i = 0, addr = 0;

SIZE_T sz;

printf("Waiting (Task%i) ", RunningTask.task + 1);

/* Устанавливаем маску ожидаемых событий */

for(i=0; i<MAX_EVENT; i++)

{if(Mask.mask[i])

{if(comma) { printf("Event_%i", i + 1); comma = false; }

else printf(", Event_%i", i + 1);

count++;

TaskQueue[RunningTask.priority][RunningTask.task].mask_w.mask[i] = Mask.mask[i];}}

printf("\n"); comma = true;

/* Проверка установленной маски */

for(i=0; i<MAX_EVENT; i++)

{if((TaskQueue[RunningTask.priority][RunningTask.task].mask_w.mask[i]) & (TaskQueue[RunningTask.priority][RunningTask.task].mask_h.mask[i]))

{/* если ожидаемые события уже произошли сбрасываем маску */

TaskQueue[RunningTask.priority][RunningTask.task].mask_w.mask[i] = false;

TaskQueue[RunningTask.priority][RunningTask.task].mask_h.mask[i] = false;

if(!flag) printf("Events which have already happened: ");

flag = true;

count-; temp = true;

if(comma) { printf("Event_%i", i + 1); comma = false; }

else printf(", Event_%i", i + 1);}}

if(temp) printf("\n");

/* Если все события произошли, то ничего не делаем, в противном случае задача переходит в состояние waiting и запускаем другую задачу */

if(count!=0)

{/* Есть события, появление которых нужно ожидать */

/* Приостанавливаем запущенную задачу и устанавливаем флаг, сигнализирующий о том, что есть события, появления которых

нужно ожидать */

TaskQueue[RunningTask.priority][RunningTask.task].state = -1;

TaskQueue[RunningTask.priority][RunningTask.task].eventwaiting = true;

/* Сохраняем контекст задачи и запускаем другую задачу */

TaskQueue[RunningTask.priority][RunningTask.task].context.ContextFlags = CONTEXT_ALL;

RtlCaptureContext(&(TaskQueue[RunningTask.priority][RunningTask.task].context));

if(TaskQueue[RunningTask.priority][RunningTask.task].eventwaiting)

{TaskQueue[RunningTask.priority][RunningTask.task].Rsp.size = (int)SP - (int)&addr;

TaskQueue[RunningTask.priority][RunningTask.task].Rsp.stack = malloc(TaskQueue[RunningTask.priority][RunningTask.task].Rsp.size);

if(ReadProcessMemory(MainProcess, (LPVOID)(TaskQueue[RunningTask.priority][RunningTask.task].context.Rsp),

TaskQueue[RunningTask.priority][RunningTask.task].Rsp.stack,

TaskQueue[RunningTask.priority][RunningTask.task].Rsp.size, &sz))

{printf("Reading memory... Ok %i bytes\n", sz);}

else{printf("Error: ReadProcessMemory %i\n", GetLastError());}

if(FreeTask[0].priority!=-1)

{Dispatch(FreeTask[0].priority, FreeTask[0].task);}

else

{printf("Error: Deadlock in WaitEvent routine!\n");

_getch();

exit(1);}}

if(RestoreStack)

{RestoreStack = false;

CONTEXT Ctx = TaskQueue[RunningTask.priority] [RunningTask.task]. context;

if(WriteProcessMemory(GetCurrentProcess(), (void *)(Ctx.Rsp),

TaskQueue[RunningTask.priority][RunningTask.task].Rsp.stack,

TaskQueue[RunningTask.priority][RunningTask.task].Rsp.size, &sz))

{printf("Writing memory... Ok %i bytes\n", sz);}

Else

{printf("Error: WriteProcessMemory %i\n", GetLastError());}}}

else

{printf("All events have already happened!\n");}

if(RunningTask.task!=-1) printf("Waiting events (Task%i) completed\n", RunningTask.task + 1);}

void ClearEvent(TEventMask Mask)

{TaskQueue[RunningTask.priority][RunningTask.task].mask_h = Mask;}

void ClearMask(TTask *Task)

{for(int i=0; i<MAX_EVENT; i++)

{(*Task).mask_w.mask[i] = false;

(*Task).mask_h.mask[i] = false;}}

void ClearMask(TEventMask *Mask)

{for(int i=0; i<MAX_EVENT; i++)

{(*Mask).mask[i] = false;

(*Mask).mask[i] = false;}}

Global.cpp

/****************************************************/

/* Описание глобальных переменных */

/****************************************************/

#include "rtos_api.h"

TTask TaskQueue[MAX_PRIOR][MAX_TASK];

TRunningTask RunningTask;

TRunningTask FreeTask[MAX_TASK];

TRunningTask SemaphoreWaitingTask[MAX_TASK];

TSemaphore Semaphore;

void *SP;

bool RestoreStack;

HANDLE MainProcess;

Os.cpp

/*******************************************/

/* Управление ОС */

/*******************************************/

#include "rtos_api.h"

/* Инициализация очереди задач и очереди указателей на активные задачи */

void InitializeTaskQueue()

{for(int i=0; i<MAX_PRIOR; i++)

{for(int j=0; j<MAX_TASK; j++)

{TaskQueue[i][j].priority=0;

TaskQueue[i][j].state = -1;

TaskQueue[i][j].entry=NULL;

TaskQueue[i][j].name=NULL;

TaskQueue[i][j].eventwaiting = false;

TaskQueue[i][j].semaphorewaiting = false;

TaskQueue[i][j].Rsp.stack = NULL;

TaskQueue[i][j].Rsp.size = 0;

ClearMask(&TaskQueue[i][j]);}}

for(int i=0; i<MAX_TASK; i++)

{FreeTask[i].priority = -1;

FreeTask[i].task = -1;

SemaphoreWaitingTask[i].priority = -1;

SemaphoreWaitingTask[i].task = -1;}}

/* Инициализация очереди задач и очереди ресурсов, запуск первой задачи */

int StartOS(TTask Task)

{int tmp = 0;

SP = &tmp;

RunningTask.priority = -1;

RunningTask.task = -1;

RestoreStack = false;

TSemaphore Sem;

Sem.isfree = true; Sem.sem_id = 1;

printf("Starting OS...\n");

InitPVS(Sem);

InitializeTaskQueue(); // Инициализируем очереди ресурсов и задач

ActivateTask(Task); // запускаем задачу

return 0;}

/* Завершение работы ОС */

void ShutdownOS()

{printf("Shutdown OS...\n");}

Resource.cpp

/*********************************************/

/* Управление ресурсами - простые семафоры */

/*********************************************/

#include "rtos_api.h"

/* Инициалищация семафоров */

void InitPVS(TSemaphore semaphore)

{Semaphore.isfree = semaphore.isfree;

Semaphore.sem_id = semaphore.sem_id;

Semaphore.task_id = -1;}

/* Захват семафора */

void P(TSemaphore semaphore)

{int addr = 0;

SIZE_T sz;

printf("Trying to obtain semaphore (Task%i)...", RunningTask.task + 1);

if(!Semaphore.isfree)

{printf(" semaphore is busy\n");

/* Сохоаняем контекст задачи и запускаем другую задачу */

TaskQueue[RunningTask.priority][RunningTask.task].semaphorewaiting = true;

TaskQueue[RunningTask.priority][RunningTask.task].state = -1;

/* Ставим задачу в очередб задач ожидающих семафора */

InsertIntoQueue(SemaphoreWaitingTask);

TaskQueue[RunningTask.priority][RunningTask.task].context.ContextFlags = CONTEXT_ALL;

RtlCaptureContext(&(TaskQueue[RunningTask.priority][RunningTask.task].context));

if(TaskQueue[RunningTask.priority][RunningTask.task].semaphorewaiting)

{TaskQueue[RunningTask.priority][RunningTask.task].Rsp.size = (int)SP - (int)&addr;

TaskQueue[RunningTask.priority][RunningTask.task].Rsp.stack = malloc(TaskQueue[RunningTask.priority][RunningTask.task].Rsp.size);

if(ReadProcessMemory(GetCurrentProcess(), (LPVOID)(TaskQueue[RunningTask.priority][RunningTask.task].context.Rsp),

TaskQueue[RunningTask.priority][RunningTask.task].Rsp.stack,

TaskQueue[RunningTask.priority][RunningTask.task].Rsp.size, &sz))

{printf("Reading memory... Ok %i bytes\n", sz);}

else

{printf("Error: ReadProcessMemory %i\n", GetLastError());}

if(FreeTask[0].priority!=-1)

{Dispatch(FreeTask[0].priority, FreeTask[0].task);}

else

{printf("Error: Deadlock in primitive P!\n");

_getch();

exit(1);}}

if(RestoreStack)

{RestoreStack = false;

CONTEXT Ctx = TaskQueue[RunningTask.priority][RunningTask.task].context;

if(WriteProcessMemory(GetCurrentProcess(), (void *)(Ctx.Rsp),

TaskQueue[RunningTask.priority][RunningTask.task].Rsp.stack,

TaskQueue[RunningTask.priority][RunningTask.task].Rsp.size, &sz))

{printf("Writing memory... Ok %i bytes\n", sz);}

else

{printf("Error: WriteProcessMemory %i\n", GetLastError());}}}

printf("Semaphore is obtained (Task%i)\n", RunningTask.task + 1);

Semaphore.isfree = false;

Semaphore.task_id = RunningTask.task;}

/* Освобождение семафора */

void V(TSemaphore semaphore)

{int prt, tsk;

if(RunningTask.task!=-1)

{if(RunningTask.task == Semaphore.task_id)

{printf("Retrieving semaphore (Task%i)...\n", RunningTask.task + 1);

prt = SemaphoreWaitingTask[0].priority;

tsk = SemaphoreWaitingTask[0].task;

SemaphoreWaitingTask[0].priority = -1;

SemaphoreWaitingTask[0].task = -1;

Sort(SemaphoreWaitingTask);

Semaphore.isfree = true;

Semaphore.task_id = -1;

if((prt!=-1)&(tsk!=-1)) Schedule(prt, tsk);}

else

{printf("Error: Can not retrieve semaphore, it belongs to another task!");

_getch(); exit(1);}}}

Task.cpp

/*********************************/

/* Управление задачами */

/*********************************/

#include <stdlib.h>

#include "rtos_api.h"

/* Проверка наличия задачи в очереди и её состояния.

Завершение программы произойдет в следующих случаях: данная задача уже запущена, неправильный приоритет или номер задачи */

void CheckTask(int prt, int tasknumber)

{if(prt<MAX_PRIOR)

{if(tasknumber<MAX_TASK)

{if(TaskQueue[prt][tasknumber].state==1)

{printf("Checking... Error: Task%i is running\n", tasknumber);

_getch(); exit(1);}}

else

{printf("Checking... Error: Trying to activate wrong task - Task%i\n", tasknumber);

_getch(); exit(1);}

printf("Checking... Ok\n",tasknumber);}

else

{printf("Checking... Error: Trying to activate task with wrong priority %i\n", prt);

_getch(); exit(1);}}

/* Активизация задачи */

void ActivateTask(TTask tsk)

{printf("Activating %s\n", tsk.name);

int TaskNumber = atoi(&tsk.name[4]) - 1;

CheckTask(tsk.priority, TaskNumber);

// Задача вносится в очередь задач

TaskQueue[tsk.priority][TaskNumber].priority = tsk.priority;

TaskQueue[tsk.priority][TaskNumber].name = tsk.name;

TaskQueue[tsk.priority][TaskNumber].entry = tsk.entry;

TaskQueue[tsk.priority][TaskNumber].eventwaiting = false;

TaskQueue[tsk.priority][TaskNumber].semaphorewaiting = false;

Schedule(tsk.priority,TaskNumber); // запускаем планировщик

printf("Activation of %s completed\n",tsk.name);

if(RunningTask.priority==-1) Dispatch(tsk.priority,TaskNumber); // запускаем диспетчер}

/* Завершение задачи */

void TerminateTask(void)

{if(RunningTask.task!=-1)

{printf("Terminating %s\n",TaskQueue[RunningTask.priority][RunningTask.task].name);

printf("Termination of %s completed\n", TaskQueue[RunningTask.priority] [RunningTask.task].name);

TaskQueue[RunningTask.priority][RunningTask.task].state = -1;

RunningTask.priority = -1;

RunningTask.task = -1;}

// Изменяем состояние задачи

// Запускаем следующую в очереди задачу

if(FreeTask[0].priority!=-1)

{Dispatch(FreeTask[0].priority, FreeTask[0].task);}}

/* Планировщик */

void Schedule(int prt, int task)

{int i = 0, j;

TRunningTask Bufo,Bufn;

printf("Sheduling %s, priority - %i\n",TaskQueue[prt][task].name, TaskQueue[prt][task].priority);

// Меняем состояние задачи

TaskQueue[prt][task].state = 0;

/* Подготавливаем место в очереди готовых задач

Очередь отсортирована по убыванию приоритета, и содержит только указатели на задачи в очереди TaskQueue */

for(i=0; i<MAX_TASK; i++)

{if(FreeTask[i].priority<prt)

{if(FreeTask[i].priority!=-1)

{j=i+1;

Bufo = FreeTask[i];

while((FreeTask[j].priority!=-1) & (j<MAX_TASK))

{Bufn = FreeTask[j];

FreeTask[j] = Bufo;

Bufo = Bufn;}

FreeTask[j] = Bufo;

break;}

else break;}}

// Вставляем задачу в очередь готовых задач

FreeTask[i].priority = prt;

FreeTask[i].task = task;

printf("Scheduling of %s completed\n",TaskQueue[prt][task].name);}

/* Диспетчер */

void Dispatch(int prt, int task)

{printf("Dispatching...\n");

// Выбираем первую задачу в очереди готовых задач на исполнение

RunningTask.priority = FreeTask[0].priority;

RunningTask.task = FreeTask[0].task;

// Удаляем выбранную задачу из очереди

FreeTask[0].priority = -1;

FreeTask[0].task = -1;

Sort(FreeTask);

TaskQueue[prt][task].state = 1;

// Запускаем задачу

if(TaskQueue[prt][task].eventwaiting | TaskQueue[prt][task]. semaphorewaiting)

{/* Запускаем приостановленную задачу */

TaskQueue[RunningTask.priority][RunningTask.task].context.ContextFlags = CONTEXT_ALL;

TaskQueue[prt][task].eventwaiting = false;

TaskQueue[prt][task].semaphorewaiting = false;

RestoreStack = true;

RtlRestoreContext(&(TaskQueue[RunningTask.priority][RunningTask.task].context), NULL);}

else

{TaskQueue[prt][task].entry();}

if(RunningTask.task!=-1) printf("Dispatching of Task%i completed\n",task+1);}

Test.cpp

/*********************************/

/* test.cpp */

/*********************************/

#include <stdlib.h>

#include "rtos_api.h"

DeclareTask(Task1,0);

DeclareTask(Task2,1);

DeclareTask(Task3,2);

DeclareTask(Task4,3);

DeclareTask(Task5,4);

DeclareTask(Task6,5);

DeclareTask(Task7,6);

DeclareTask(Task8,7);

DeclareTask(Task9,8);

DeclareTask(Task10,9);

DeclareEvent(Event1,0);

DeclareEvent(Event2,1);

DeclareEvent(Event3,2);

DeclareEvent(Event4,3);

DeclareEvent(Event5,4);

DeclareEvent(Event6,5);

DeclareEvent(Event7,6);

DeclareEvent(Event8,7);

DeclareEvent(Event9,8);

DeclareEvent(Event10,9);

TASK(Task1)

{printf("Starting Task1...\n");

TTask task2, task3;

TEventMask msk;

task2.priority = Task2prior;

task2.state = -1;

task2.name = "Task2";

task2.entry = Task2;

task2.eventwaiting = false;

task2.semaphorewaiting = false;

ClearMask(&task2); ClearMask(&msk);

msk.mask[Event1] = true; msk.mask[Event2] = true;

task3.priority = Task3prior;

task3.state = -1;

task3.name = "Task3";

task3.entry = Task3;

task3.eventwaiting = false;

task3.semaphorewaiting = false;

ClearMask(&task3);

ActivateTask(task2);

ActivateTask(task3);

P(Semaphore);

WaitEvent(msk);

V(Semaphore);

if(RunningTask.task!=-1) printf("Executing Task1...\n");

TerminateTask();}

TASK(Task2)

{printf("Starting Task2...\n");

TEventMask msk;

ClearMask(&msk);

msk.mask[0] = true; msk.mask[1] = true;

SetEvent(&(TaskQueue[0][0]), msk);

printf("Executing Task2...\n");

TerminateTask();}

TASK(Task3)

{printf("Starting Task3...\n");

TEventMask msk;

ClearMask(&msk);

msk.mask[0] = true; msk.mask[1] = true;

P(Semaphore);

printf("Executing Task3...\n");

V(Semaphore);

TerminateTask();}

TASK(Task4)

{printf("Starting Task4...\n");

TTask task5, task6;

TEventMask msk;

task5.priority = Task5prior;

task5.state = -1;

task5.name = "Task5";

task5.entry = Task5;

task5.eventwaiting = false;

task5.semaphorewaiting = false;

ClearMask(&task5); ClearMask(&msk);

msk.mask[Event3] = true; msk.mask[Event4] = true; msk.mask[Event5] = true;

task6.priority = Task6prior;

task6.state = -1;

task6.name = "Task6";

task6.entry = Task6;

task6.eventwaiting = false;

task6.semaphorewaiting = false;

ClearMask(&task6);

ActivateTask(task5);

ActivateTask(task6);

WaitEvent(msk);

if(RunningTask.task!=-1) printf("Executing Task4...\n");

TerminateTask();}

TASK(Task5)

{printf("Starting Task5...\n");

TEventMask msk;

ClearMask(&msk);

msk.mask[Event5] = true;

SetEvent(&(TaskQueue[3][3]), msk); // Task4 3

ClearMask(&msk);

msk.mask[Event10] = true;

SetEvent(&(TaskQueue[6][6]), msk); // Task7 6

printf("Executing Task5...\n");

TerminateTask();}

TASK(Task6)

{printf("Starting Task6...\n");

TTask task7;

task7.priority = Task7prior;

task7.state = -1;

task7.name = "Task7";

task7.entry = Task7;

task7.eventwaiting = false;

task7.semaphorewaiting = false;

ClearMask(&task7);

P(Semaphore);

ActivateTask(task7);

V(Semaphore);

printf("Executing Task6...\n");

TerminateTask();}

TASK(Task7)

{printf("Starting Task7...\n");

TEventMask msk;

ClearMask(&msk);

msk.mask[Event10] = true;

WaitEvent(msk);

printf("Executing Task7...\n");

TerminateTask();}

void Test(int testNumber)

{TTask InitialTask;

InitialTask.state = -1;

InitialTask.eventwaiting = false;

InitialTask.semaphorewaiting = false;

ClearMask(&InitialTask);

switch(testNumber)

{case(0):

{InitialTask.priority = Task1prior;

InitialTask.name = "Task1";

InitialTask.entry = Task1;

break;}

case(1):

{InitialTask.priority = Task4prior;

InitialTask.name = "Task4";

InitialTask.entry = Task4;

break;}}

StartOS(InitialTask);

ShutdownOS();}

int main(void)

{HANDLE Temporary = GetCurrentProcess();

if(DuplicateHandle(GetCurrentProcess(), Temporary, GetCurrentProcess(), &MainProcess, 0, FALSE, DUPLICATE_SAME_ACCESS))

{printf("DupliicateHandle... Ok\n");}

printf("******************************************\n");

Test(0);

_getch();

return 0;}

5. Результаты работы

Рассмотрим более подробно результат работы операционной системы реального времени.

В системе есть три задачи. Две, из которых работают с семафором (Task1, Task3) и одна задача устанавливает события (Task2).

После запуска операционной системы происходит запуск первой задачи с нулевым приоритетом. Запуск включает в себя: активизацию, проверку задачи, планирование и диспетчеризацию. Во время проверки задачи происходит проверка номера задачи, её приоритета. В случае если какой-либо элемент задачи является неправильным, то произойдет экстренное завершение ОСРВ.

Первая задача запускает задачу 2 и 3 с приоритетами 1 и 2 соответственно. Так как реализован невытесняемый тип планирования, то задачи, запускаемые другой задачей не начинают выполняться сразу, а только активизируются, проверяются и планируются. Далее задача 1 захватывает семафор, так как он свободен перехода в состояние waiting не происходит. В маске ожидаемых событий устанавливаются события с номерами 1 и 2, т.е. задача начинает ждать их появления, при этом происходит перевод данной задачи в состояние waiting, сохранение контекста и стека вызовов. Вслед за этим происходит запуск другой задачи. Наиболее приоритетной является задача 3, поэтому она и запускается. Задаче 3 необходим семафор, но он уже занят первой задачей, поэтом задача 3 переводится в состояние waiting, происходит сохранение контекста и стека вызовов. Запускается следующая задача, которая находится в очереди (Task2). Задача с номером 2 устанавливает события 1 и 2 для первой задачи, т.е. изменяется маска произошедших событий. Задача 1 планируется и переводится из состояния waiting в состояние ready. После того как завершится вторая задача, запустится задача с номером 1, но она запустится с того места на котором была прервана, т.е. произойдет восстановление контекста и стека вызовов. После восстановления первой задачи происходит возвращение семафора и планирование задачи с номером 3 (перевод из состояния waiting в состояние ready). Задача номер 1 завершается. В конце концов, восстанавливается задача 3 (восстанавливается контекст и стек вызовов). Она захватывает семафор, выполняется, возвращает семафор и завершается. На этом работа операционной системы завершается.

Таким образом, данная операционная система реального времени поддерживает вытеснение и восстановление задач (сохранение и восстановление контекста и стека вызовов) при ожидании событий и захвате семафора. Приведенный результат работы позволяет судить о правильности выполнения задания.

Рисунок 1: Результат работы ОСРВ

Выводы

В ходе работы была реализована модель операционной системы реального времени, обладающая свойствами, указанными в задании. Были получены навыки позволяющие реализовывать важные компоненты операционных систем: планировщик, диспетчер, простые семафоры, события и т.д.

Размещено на Allbest.ru

...

Подобные документы

  • Обзор требований проблемной области. Особенности управления задачами. Исполнительные системы реального времени. Программирование на уровне микропроцессоров. Модели и методы предметной области. Реализация прототипа системы реального времени.

    курсовая работа [263,1 K], добавлен 15.02.2005

  • Классификация систем реального времени. Ядра и операционные системы реального времени. Задачи, процессы, потоки. Преимущества и недостатки потоков. Свойства, планирование, синхронизация задач. Связанные задачи. Синхронизация с внешними событиями.

    реферат [391,5 K], добавлен 28.12.2007

  • Основные характеристики систем реального времени, типы архитектур. Система приоритетов процессов (задач) и алгоритмы диспетчеризации. Понятие отказоустойчивости, причины сбоев. Отказоустойчивость в существующих системах реального времени (QNX Neutrino).

    контрольная работа [428,8 K], добавлен 09.03.2013

  • Операционные системы пакетной обработки, разделения времени, реального времени. Особенности алгоритмов управления ресурсами. Поддержка многопользовательского режима. Вытесняющая и невытесняющая многозадачность. Операционные системы и глобальные сети.

    реферат [55,0 K], добавлен 11.12.2011

  • Планирование задач в операционной системе реального времени. Основные виды планирования применительно к задачам реального времени. Выбор приемлемого алгоритма планирования при проектировании RTS. Статическое прогнозирование с использованием таблиц.

    контрольная работа [40,7 K], добавлен 28.05.2014

  • Характеристики, основы применения, архитектура жестких и операционных систем реального времени. Последовательное программирование задач реального времени. Структура и языки параллельного программирования, мультипрограммирования и многозадачности.

    курсовая работа [195,9 K], добавлен 17.12.2015

  • Создание средств представления процессов и механизмов управления на уровне диспетчеризации, разработка алгоритма и написание программы, имитирующую работу простейшей операционной системы. Формирование дескриптора, ввод информации, интерфейс программы.

    лабораторная работа [1,1 M], добавлен 09.07.2010

  • Использование операционных систем Microsoft Windows. Разработка операционной системы Windows 1.0. Возможности и характеристика последующих версий. Выпуск пользовательских операционных систем компании, доработки и нововведения, версии Windows XP и Vista.

    реферат [23,3 K], добавлен 10.01.2012

  • Основные понятия операционных систем. Современное оборудование компьютера. Преимущества и недостатки операционной системы Linux. Функциональные возможности операционной системы Knoppix. Сравнительная характеристика операционных систем Linux и Knoppix.

    реферат [1,5 M], добавлен 17.12.2014

  • Основные понятия об операционных системах. Виды современных операционных систем. История развития операционных систем семейства Windows. Характеристики операционных систем семейства Windows. Новые функциональные возможности операционной системы Windows 7.

    курсовая работа [60,1 K], добавлен 18.02.2012

  • Основные моменты истории операционных систем, связывающих аппаратное обеспечение и прикладные программы. Характеристика операционной системы Microsoft Windows Seven, анализ операционной системы Linux. Преимущества и недостатки каждой операционной системы.

    курсовая работа [63,0 K], добавлен 07.05.2011

  • Понятие и функции операционной системы. Основная особенность операционных систем реального времени. Работа с электронными таблицами. Фильтрация записей в таблице MS Excel. Установка пользовательского автофильтра в оборотную ведомость движения товаров.

    контрольная работа [547,8 K], добавлен 21.11.2013

  • Функции операционной системы как совокупности программных средств, осуществляющих управление ресурсами электронно-вычислительных машин. Предназначение Windows, Linux и Mac. Особенности реализации алгоритмов управления основными ресурсами компьютера.

    реферат [22,5 K], добавлен 16.03.2017

  • Автоматизация технологических процессов. Написание имитационных моделей систем с дискретными событиями. Модели систем массового обслуживания в общецелевой системе GPSS. Логическая схема алгоритмов и схема программы. Математическая модель и ее описание.

    курсовая работа [1,4 M], добавлен 29.06.2011

  • Характеристика сущности, назначения, функций операционных систем. Отличительные черты их эволюции. Особенности алгоритмов управления ресурсами. Современные концепции и технологии проектирования операционных систем, требования, предъявляемые к ОС XXI века.

    курсовая работа [36,4 K], добавлен 08.01.2011

  • Рассмотрение основных принципов и методов проектирования систем реального времени. Описание конструктивных и функциональных особенностей объекта управления, построение диаграммы задач. Выбор аппаратной архитектуры, модели процессов-потоков, интерфейса.

    курсовая работа [1,2 M], добавлен 19.01.2015

  • Разработка системы синхронизации уведомлений (клиентское приложение для смартфонов под управлением операционной системы Android версии 4.0.0 и выше). Разработка сервера, работающего под управлением Windows. Расчет себестоимости создания системы.

    дипломная работа [706,7 K], добавлен 17.07.2016

  • Возможности библиотеки OpenGL, создание матрицы и эффекта тумана. Разработка процедуры визуализации трехмерной модели "Корабль", интерфейса пользователя и подсистемы управления событиями. Логическая структура и функциональная декомпозиция проекта.

    курсовая работа [507,2 K], добавлен 02.07.2011

  • Важность операционной системы для мобильных устройств. Популярность операционных систем. Доля LINUX на рынке операционных систем. История OS Symbian, BlackBerry OS, Palm OS. Отличия смартфона от обычного мобильного телефона. Учет ограничений по памяти.

    презентация [477,3 K], добавлен 01.12.2015

  • Раскрытие сущности планирования в программных компонентах. Понятие процесса и потока, их планирование в операционной системе. Категории и задачи алгоритмов планирования в пакетных и интерактивных системах. Планирование в системах реального времени.

    контрольная работа [303,5 K], добавлен 24.10.2014

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.