Создать три варианта библиотеки:
статическую библиотеку;
динамическую библиотеку для загрузки вместе с программой;
динамическую библиотеку для загрузки по запросу из программы.
В библиотеке реализовать функцию, которая является оболочкой одной из системных функций (т.е. оболочка вызывает одну из системных функций).
Системную функцию выбрать из таблицы, приведенной в описании лабораторной работы № 9. Номер выбранной функции соответствует номеру студента в списке группы.
Интерфейс функции-оболочки должен совпадать с интерфейсом выбранной системной функции.
Например, если интерфейс системной функции выглядит следующим образом:
int uname(struct utsname *buf);
то интерфейс библиотечной функции-оболочки, может выглядеть следующим образом:
int my_uname(struct utsname *buf);
Реализовать три программы, использующие три вида указанных библиотек.
Дайте характеристику понятию «цепь доступа».
Дайте характеристику понятию «связывание».
Перечислите этапы жизненного цикла программы, на которых может выполняться построение цепи доступа.
Что такое «абсолютная» и «перемещаемая» программа?
В чем состоит действие – «редактирование связей»?
Дайте характеристику понятию «чистая процедура».
Дайте характеристику понятию «секция связи».
Цель работы – знакомство с сопрограммами как с механизмом передачи управления, реализующим невытесняющую многозадачность в ОС.
Сопрограммы представляют собой участки кода, при выполнении которых возможна передача управления от одного участка к другому. Передача управления производится с помощью специальной процедуры, вызов которой и приводит к передаче управления.
При передаче управления выполнение одной сопрограммы приостанавливается, а выполнение другой сопрограммы возобновляется с той точки, на которой она ранее была приостановлена.
При передаче управления от одной сопрограммы к другой сохраняется состояние приостанавливаемой сопрограммы, поэтому, когда сопрограмме возвращают управление из другой сопрограммы, она продолжает свое выполнение, восстановив ранее сохраненное состояние.
Сохранение и восстановление состояний участков кода, являющихся сопрограммами, происходит за счет того, что каждой сопрограмме предоставляется собственный стек для сохранения локальных данных и точки возобновления, а также структура данных для хранения регистров процессора и адреса вершины стека.
Структура данных, о которой идет речь, называется дескриптором сопрограммы.
Передача управления от одной сопрограммы к другой сопрограмме с помощью специальной процедуры производится в четыре этапа.
Когда приостанавливаемая сопрограмма вызывает специальную процедуру, также как и при вызове обычной процедуры, происходит сохранение локальных параметров и точки возобновления в стеке приостанавливаемой сопрограммы.
Затем код специальной процедуры сохраняет регистры процессора и адрес вершины стека в дескрипторе приостанавливаемой сопрограммы.
Следующим этапом код специальной процедуры восстанавливает регистры процессора и адрес вершины стека из дескриптора возобновляемой сопрограммы.
Последним этапом происходит возврат из специальной процедуры, также как и при возврате из обычной процедуры, но уже на стеке возобновляемой сопрограммы. Поэтому в счетчик команд процессора передается адрес, с которого возобновляемая сопрограмма продолжает свое выполнение.
Сопрограммы содержат следующие компоненты:
код сопрограммы, в качестве кода может выступать и процедура;
стек сопрограммы;
дескриптор сопрограммы;
процедура переключения от одной сопрограммы к другой;
процедура создания сопрограммы.
Процедура создания сопрограммы выполняет следующие действия:
создает стек сопрограммы, как правило, в динамической памяти;
создает дескриптор сопрограммы, как правило, в динамической памяти;
в стек записывает адрес входа в сопрограмму;
в дескриптор записывает адрес вершины стека сопрограммы.
Работа сопрограмм иллюстрирует механизм невытесняющей многозадачности, при которой задачи добровольно передают друг другу управление.
В то же время вытесняющая многозадачность также использует механизм переключения сопрограммам в процедуре диспетчеризации, вызываемой по прерываниям от таймера.
Шаблон программы, использующей механизм передачи управления, основанный на сопрограммах, представлен ниже.
объявить дескриптор сопрограммы 1;
объявить дескриптор сопрограммы 2;
объявить дескриптор сопрограммы 3;
функция 1()
{
пока (истина) делать
{
//выполнение действий
передать управление сопрограмме 2();
}
}
функция 2()
{
пока (истина) делать
{
//выполнение действий
если (условие завершения выполнено) {
передать управление сопрограмме 3();
}иначе{
передать управление сопрограмме 1();
}
}
}
основная программа()
{
объявить стек сопрограммы 1;
объявить стек сопрограммы 2;
создать сопрограмму 1 из функции 1();
создать сопрограмму 2 из функции 1();
создать сопрограмму 3 из основной программы();
передать управление сопрограмме 1();
}
В операционных системах семейства Windows механизм сопрограмм иллюстрируется средством, называемым fibers – нити [1].
Windows предоставляет следующий программный интерфейс для работы с нитями:
ConvertThreadToFiber – преобразование потока в нить;
CreateFiber – создание нити из функции;
SwitchToFiber – передача управления от выполняющейся нити к другой нити;
DeleteFiber – удаление нити.
В операционных системах стандарта POSIX тоже существует программный интерфейс, позволяющий реализовать механизм сопрограмм.
К указанному программному интерфейсу можно отнести следующие средства.
Тип данных ucontext_t, позволяющий сохранять и восстанавливать контекст выполняющейся сопрограммы. Переменная этого типа и представляет собой дескриптор сопрограммы.
Тип данных ucontext_t включает в себя набор полей, из которых отметим следующие поля [2]:
typedef struct ucontext {
stack_t uc_stack;
mcontext_t uc_mcontext;
...
} ucontext_t;
Тип данных stack_t содержит информацию о стеке сопрограммы. В этом типе данных отметим следующие поля [3]:
typedef struct {
void *ss_sp; /* адрес стека */
size_t ss_size; /* размер стека в байтах */
...
} stack_t;
Тип данных mcontext_t позволяет хранить состояние регистров процессора и является аппаратно-зависимым.
Следующая функция инициализирует контекст, представленный переменной типа ucontext_t [2]:
int getcontext(ucontext_t *ucp);
Следующая функция модифицирует контекст, полученный функцией getcontext() [4]:
void makecontext(ucontext_t *ucp, void *func(), int argc, ...);
где:
ucp – указатель на контекст – дескриптор сопрограммы;
func() – функция, реализующая сопрограмму;
argc – количество аргументов, передаваемых функции сопрограммы в качестве параметров целого типа; если argc больше единицы, далее идут сами параметры.
Для случая, когда значение argc равно нулю, функция сопрограммы имеет следующий прототип:
void func(void).
Для сопрограммы должен быть выделен стек в виде массива байтов как, например, показано ниже:
char func_stack[16384].
Структура uc_stack контекста ucp сопрограммы должна быть проинициализированы параметрами стека:
ucp.uc_stack.ss_sp = func_stack;
ucp.uc_stack. ss_size = sizeof(func_stack);
Объявление контекста и стека, а затем вызов функций getcontext() и makecontext() реализуют создание сопрограммы.
Переключение сопрограмм – передача управления от одной сопрограммы к другой сопрограмме выполняется функцией [4]:
int swapcontext(ucontext_t *oucp, const ucontext_t *ucp);
где:
oucp – дескриптор приостанавливаемой сопрограммы;
ucp – дескриптор активизируемой сопрограммы.
Реализовать программу на основе шаблона, представленного выше.
Модифицировать программу п.1 следующим образом: 1. программа должна содержать три рабочих сопрограммы; 2. дескрипторы рабочих сопрограмм включены в очередь дескрипторов; 3. в качестве очереди использовать тип данных vector или queue; 4. программа должна содержать сопрограмму-диспетчер; 5. рабочие сопрограммы передают управление сопрограмме-диспетчеру; 6. после получения управления сопрограмма-диспетчер принимает решение о том, какой из рабочих сопрограмм передать управление; 7. решение принимается следующим образом: - дескриптор приостанавливаемой рабочей сопрограммы ставится в конец очереди дескрипторов; - из начала очереди дескрипторов извлекается дескриптор рабочей сопрограммы; - этой сопрограмме передается управление.
Дайте определение понятия «сопрограмма».
Чем сопрограммы отличаются от процедур?
Приведите примеры реализации сопрограмм.
Объясните, каким способом сопрограммы моделируют невытесняющую многозадачность.
Перечислите элементы, которые в обязательном порядке должна включать сопрограммы.
Перечислите этапы создания сопрограммы.
https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms682661(v=vs.85).aspx
http://man7.org/linux/man-pages/man3/setcontext.3.html
http://man7.org/linux/man-pages/man2/sigaltstack.2.html
http://man7.org/linux/man-pages/man3/makecontext.3.html
Цель работы – знакомство с механизмом взаимодействия потоков через буфер, построенный на условных переменных.
Буферизация является средством согласования скорости записи данных одним потоком и скорости чтения данных другим потоком. При этом буфер является общим, разделяемым объектом для пишущего и читающего потоков.
Существуют следующие требования к алгоритмам функционирования буфера:
нельзя записать сообщение в полный буфер; поток, делающий такую попытку, должен быть блокирован до появления свободной ячейки в буфере;
нельзя прочитать сообщение из пустого буфера; поток, делающий такую попытку, должен быть блокирован до появления сообщения в буфере.
Как правило, механизмы синхронизации записи в буфер и чтения из буфера являются скрытыми для программиста, которому предоставляются лишь примитивы СОЗДАТЬ БУФЕР, УНИЧТОЖИТЬ БУФЕР, ЗАПИСАТЬ ДАННЫЕ В БУФЕР и ПРОЧИТАТЬ ДАННЫЕ ИЗ БУФЕРА, внешне напоминающие работу с файлами.
Шаблон потока, записывающего данные в буфер, выглядит следующим образом:
пока (условие завершения потока не выполнено) {
сгенерировать данные;
записать данные в буфер;
задержать на время;
}
Шаблон потока чтения данных из буфера выглядит следующим образом:
пока (условие завершения потока не выполнено) {
прочитать данные из буфера;
обработать данные;
задержать на время;
}