40гг первые цифровые компьютеры программирование путем коммутации проводов

Вид материалаДокументы

Содержание


По области применения
Пример макроса для синтаксического макропроцессора
X: данные
X: данные
Функции ПОЛОН(B) и ПУСТ(B) возвращают результаты сравнения
B.buffer((B.first + B.count) % n ) := X
Подобный материал:
1   ...   4   5   6   7   8   9   10   11   12

По области применения – специализированные и общего назначения.
  • Специализированные макропроцессоры, имея возможность использовать знания о синтаксисе языка программирования, могут предоставить более удобный и широкий набор средств.
  • Макропроцессоры общего назначения имеет смысл применять в многоязыковых программных системах, когда важны единообразие используемых средств и легкость обучения.
  • По степени близости макросредств к языкам программирования – языкоподобные и независимые.
  • Языкоподобные макропроцессоры хороши тем, что знание исходного языка программирования помогает в изучении макросредств.
  • Однако похожий синтаксис имеет и недостатки: в тексте программы трудно отличить макросредства от обычных операторов; одинаковое написание может привести к неправильному пониманию семантики макросредств.
  • По фазе трансляции, на которой производится макрообработка – текстовые, синтаксические и вычислительные.
  • Текстовые – обработка исходного текста программы до трансляции
  • Синтаксические – обработка исходного текста на этапе синтаксического анализа
  • Вычислительные – обработка исходного текста на этапе генерации кода, используются главным образом для вставки в генерируемый код последовательностей команд, для выполнения не обеспечиваемых языком действий.

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

Виды макроопределений
  • Подстановка нескольких лексем вместо одной.

macro L is

PL

end macro;

  • Параметрическая подстановка

macro L(PlfP2, . . . ,Pn) is

PL

end macro;

  • Определение значения лексемы (macroeval)

macroeval L is

Е

end macroeval;
  • Условный макрооператор (macroif)

macroif В macrothen

PL1

macroelse

PL2

end macroif;

  • Макрооператор цикла (macrowhile).

macrowhile В macrodo

PL

end macrodo;


Дополнительные средства
  • Ввод текста из дополнительных источников
  • Промежуточное хранение отдельных частей текста
  • Выдача диагностических сообщений о ходе макрообработки
  • Управление печатью листинга программы


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


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


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


Пример макроса для синтаксического макропроцессора

macro while <логическое выражение> do

<последовательностъ операторов> end do;

is

метка: if %1 then %2

goto метка;

end if;

end macro;


Макрообработка в С++
  • Исторически сложилось, что макропроцессор в С++ называется «препроцессором».
  • По классификации препроцессор относится к специализированным, независимым, текстовым макропроцессорам
  • Инструкции препроцессора называются директивами.
  • Директивы должны начинаться с символа #, перед которым в строке могут находиться только пробельные символы.


Директива #include
  • Директива #include <имя_файла> вставляет содержимое указанного файла в ту точку исходного файла, где она записана.
  • Включаемый файл также может содержать директивы #include.
  • Поиск файла, если не указан полный путь, ведется в стандартных каталогах включаемых файлов. Вместо угловых скобок могут использоваться кавычки (" ") — в этом случае поиск файла ведется в каталоге, содержащем исходный файл, а затем уже в стандартных каталогах.
  • Директива #include является простейшим средством обеспечения согласованности объявлений в различных файлах, она включает в них информацию об интерфейсе из заголовочных файлов.



Директива #define
  • Директива #def ine определяет подстановку в тексте программы. Она используется для определения:
  • символических констант:
    #define имя текст_подстановки
  • макросов, которые выглядят как функции, но реализуются подстановкой их
    текста в текст программы:

#define имя(параметры) текст_подстановки
  • символов, управляющих условной компиляцией. Они используются вместе с директивами #i fdef и #i fndef. Формат: #define имя : Примеры:

#define VERSION 1

#define VASIA "Василий Иванович"

#define MAX(x.y) ((x)>(y)?(x):(y))

#define MUX
  • Имена рекомендуется записывать прописными буквами, чтобы зрительно отличать их от имен переменных и функций.
  • Параметры макроса используются при макроподстановке, например, если в тексте программы используется вызов макроса у = MAX(suml. sum2):, он будет заменен на

у = ((suml)>(sum2)?(suml):(sum2));


Директивы условной компиляции
  • Директивы условной компиляции #if, #ifdef и #ifndef применяются для того, чтобы исключить компиляцию отдельных частей программы.
  • Это бывает полезно при отладке или, например, при поддержке нескольких версий программы для различных платформ.



Формат директивы #if:

#if константное_выражение



[#elif константное_выражение

]

[#elif константное_выражение

]


[#else

]

#endif


Пример условной компиляции

#if VERSION ==1

#define INCFILE "vers1.h"

#elif VERSION == 2

#define INCFILE "vers2.h"

/* и так далее */

#else

#define INCFILE "versN.h“

#endif

#include INCFILE

Директивы #ifdef и #ifndef
  • Часто в программах используются директивы #ifdef и #ifndef, позволяющие управлять компиляцией в зависимости от того, определен ли с помощью директивы fdefine указанный в них символ (хотя бы как пустая строка, напри­мер, fdefine 32_BIT_SUPP0RT):

#ifdef символ

// Расположенный ниже код компилируется, если символ

// определен

#ifndef символ

// Расположенный ниже код компилируется, если символ не

// определен
  • Действие этих директив распространяется до первого #elif, #else или #endif.

Директива #undef
  • Директива #undef имя удаляет определение символа.
  • Используется редко, например, для отключения какой-либо опции компилятора.

Предопределенные макросы
  • В C++ определено несколько макросов, предназначенных в основном для того, чтобы выдавать информацию о версии программы или месте возникновения ошибки.
  • cplusplus — определен, если программа компилируется как файл C++.
  • DATE — содержит строку с текущей датой в формате месяц день год, например:

printf(" Дата компиляции - %s \n", DATE );
  • FILE — содержит строку с полным именем текущего файла.
  • LINE — текущая строка исходного текста.
  • TIME — текущее время, например:

printf(" Ошибка в файле %$ \n Время компиляции: %s\n ",
FILE,TIME);



Параллельная обработка


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

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


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

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

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

Описание процесса

process PR(L) is

D

begin

S

end process;


Оператор вызова процесса

init PR1(A1),PR2(A2), …, PRN(An);


Оператор прекращения процесса

init PR(A)[идентификатор];

abort идентификатор;


Завершение процесса генерацией исключения

raise идентификатор’ FAILURE


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


Взаимное исключение


process ПОСТАВЩИК is

use

БУФЕР, ДАННЫЕ : type,

ЖДАТЬ : procedure,

ВЫРАБОТАТЬ :

procedure(out ДАННЫЕ);

use B: in out БУФЕР;

X: ДАННЫЕ;

begin

do

ВЫРАБОТАТЬ(X);

while ПОЛОН(B) do

ЖДАТЬ();

end do;

ЗАНЕСТИ(B,X);

end do;

end process;


process ПОТРЕБИТЕЛЬ is

use

БУФЕР, ДАННЫЕ : type,

ЖДАТЬ : procedure,

ПОТРЕБИТЬ :

procedure(in ДАННЫЕ);

use B: in БУФЕР;

X: ДАННЫЕ;

begin

do

while ПУСТ(B) do

ЖДАТЬ();

end do;

ВЫБРАТЬ(B,X);

ПОТРЕБИТЬ(X);

end do;

end process;


Реализация буфера

subtype ИНДЕКС is integer range 0..n-1;

subtype КОЛИЧЕСТВО is integer range 0..n;

type БУФЕР is record

buffer: array(ИНДЕКС) of ДАННЫЕ;

first : ИНДЕКС; // индекс элемента массива с готовыми данными

count : КОЛИЧЕСТВО; // количество элементов в массиве


Функции ПОЛОН(B) и ПУСТ(B) возвращают результаты сравнения

B.count == n и B.count == 0 соответственно

Функция ЗАНЕСТИ :

B.buffer((B.first + B.count) % n ) := X;

B.count := B.count +1;

Функция ВЫБРАТЬ

X:= B.buffer(B.first);

B.first := (B.first + 1) % n;

B.count := B.count -1;


Возникновение ошибки


Поставщик

B.buffer((B.first + B.count) % n ) := X;


B.count := B.count +1;


Потребитель

X:= B.buffer(B.first);

B.first := (B.first + 1) % n;


B.count := B.count -1;


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

Программное решение проблемы взаимного исключения
  • Необходимо предположение о неделимости операций доступа к памяти

Защита критических интервалов с помощью общей переменной

применим для защиты критических интервалов общую переменную door, которая может принимать два значения — open и close.

Значение close означает, что один из процессов вошел в критический интервал, значение open, что процесс может войти в критический интер­вал.

door: (open, сlose) := open;

— в начале критический интервал не занят


Защита критических интервалов с помощью общей переменной

процесс 1


do until(door=open);

door:=close; критический интервал 1

door:=open;

процесс 2


do until(door=open);

door:=close; критический интервал 2

door:=open;


Упорядочение критических интервалов

применим для защиты критических интервалов общую переменную переменная turn принимает значение 1, когда процесс 1 может войти в свой критический интервал, и значение 25 когда про­цесс 2 может войти в свой критический интервал.

turn: (1,2) := 1;

— вначале процесс 1 может войти в критический интервал, а процесс 2 не может


Упорядочение критических интервалов

процесс 1


do until(turn=1);

критический интервал 1

turn = 2;

процесс 2


do until(turn=2);

критический интервал 2

turn = 1;


Защита критических интервалов с помощью двух переменных

Пусть каждый процесс имеет свою переменную, которая может принимать значения inside и outside.

Значение inside означает, что процесс хочет войти или уже вошел в свой критический интервал, a outside, что процесс находится вне критического интервала.

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

statel,state2:(inside,outside):= outside;

— в начале процессы вне критических интервалов


Защита критических интервалов с помощью двух переменных

процесс 1


state1 := inside;

do until(state2=outside);

критический интервал 1

state1 := outside;


процесс 2


state2 := inside;

do until(state1=outside);

критический интервал 2

state2 := outside;


Защита критических интервалов с помощью двух переменных (доработанные процессы)

процесс 1

do

state1 := inside;

if state2 = inside then

state1 := outside;

end if;

do until

(state2=outside);

until(state1=inside);

критический интервал 1

state1 := outside;

процесс 2

do

state2 := inside;

if state1 = inside then

state2 := outside;

end if;

do until

(state1=outside);

until(state2=inside);

критический интервал 2

state2 := outside;


Защита критических интервалов (комбинированный метод)

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

statel,state2:(inside,outside):= outside;

turn: (1,2) := 1;

— в начале процессы вне критических интервалов, приоритет у первого процесса.


Защита критических интервалов (комбинированный метод)

процесс 1

state1 := inside;

if state2 = inside then

if turn = 2 then

state1 := outside;

do until(turn=1);

state1 := inside;

end if;

do until(state2=outside);

end if;

критический интервал 1

turn := 2;

state1 := outside;

процесс 2

state2 := inside;

if state1 = inside then

if turn = 1 then

state2 := outside;

do until(turn=2);

state2 := inside;

end if;

do until(state1=outside);

end if;

критический интервал 2

turn := 1;

state2 := outside;


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

Двоичные семафоры
  • Двоичный семафор – специальный тип данных.
  • Переменные этого типа принимают значения 0 и 1, допустимы неделимые операции V и P.
  • Операция Р
  • - уменьшает значение семафора на 1, если оно отлично от 0;
  • если значение семафора равно 0, ждет, пока некоторый другой процесс не изменит значения семафора с помощью операции V, а затем уменьшает его
  • Операция V – присваивает семафору значение 1.


mutex:semaphore := 1;

P(mutex);

критический интервал процесса N

V(mutex);


Двоичные семафоры

Достоинства
  • Механизм семафоров обеспечивает организацию любых схем взаимодействия процессов
  • Широко используется в современных операционных системах
  • Включен в ряд языков программирования

Двоичные семафоры

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

Двоичные семафоры
  • Нельзя запрограммировать альтернативное действие для случая, когда семафор окажется занятым
  • Нельзя ждать, пока один из нескольких семафоров окажется свободным
  • За правильный доступ к общим ресурсам ответствен процесс, который осуществляет этот доступ. Это противоречит современной технологии программирования, — данные и все операции над ними должны объединяться в одну программную единицу


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