
- •Министерство образования и науки Украины
- •Практическое занятие №1
- •1.1. Сокращенная запись двоичных чисел в восьмеричной и шестнадцатеричной системах счисления
- •1.2. Преобразование восьмеричных и шестнадцатеричных чисел в двоичные
- •1.3. Преобразование двоичных, восьмеричных и шестнадцатеричных чисел в десятичные
- •1.4. Преобразование десятичных чисел в двоичные, восьмеричные и шестнадцатеричные
- •2. Упражнения
- •3. Содержание отчёта
- •Практическое занятие №2
- •1.1. Вход в систему
- •1.2. Редактирование командной строки
- •1.3. Память командных строк
- •1.4. Переключение виртуальных консолей
- •1.5. Изменение консольных шрифтов
- •1.6. Основные команды
- •Выполнение некоторых команд
- •2. Команда просмотра содержимого каталогов -ls (LiSt) – выдает на экран перечень файлов и каталогов (по умолчанию из текущего каталога).
- •Жесткая ссылка обозначает ся так же, как файл, на который она ссылается, счетчик ссылок при этом будет иметь значение больше 1.
- •3. Команда создание новых каталогов - mkdir.
- •5. Команда копирование файлов -cp (CoPy).
- •6. Команда перемещение файлов - mv (MoVe).
- •7. Команда удаление файлов - rm (ReMove).
- •8. Команды просмотра содержимого файлов more и cat.
- •Подстановочные символы
- •1.7. Выход из системы
- •2. Упражнения
- •Используя справочную информацию из п.1.6 Основные команды, изучите работу рассмотренных команд с различными параметрами и опциями:
- •1.2. Перенаправление ввода и вывода
- •1.3. Перенаправление с добавлением
- •1.4. Использование конвейера
- •2. Упражнения
- •3. Содержание отчёта
- •Справочная информация
- •Практическое занятие №4 Псевдонимы команд в ос qnx Цель – создание псевдонимов команд для облегчения работы в среде ос qnx
- •1. Краткие теоретические сведения
- •1.1. Управление связями файлов
- •1.2. Жесткие связи
- •1.3. Символические связи
- •1.4. Права доступа к файлам
- •1.5. Зависимости
- •1.6. Изменение прав доступа
- •2. Упражнения
- •3. Содержание отчёта
- •1.2. Сравнение файлов (команда diff)
- •1.3. Подсчет числа слов, строк и байт в файле (команда wc)
- •1.4. Потоковый редактор sed
- •2. Упражнения
- •/Usr/bin/grep
- •/Usr/xpg4/bin/grep
- •/Usr/xpg4/bin/grep
- •Операнды
- •/Usr/bin/grep
- •/Usr/xpg4/bin/grep
- •Использование
- •Работа с большими файлами
- •/Usr/bin/who
- •/Usr/xpg4/bin/who
- •Операнды
- •1.1. Ввод текста
- •1.2. Редактирование текста
- •1.3. Сохранение файлов и выход из VI
- •1.4. Редактирование еще одного файла
- •1.5. Включение других файлов
- •1.6. Выполнение команд Shell
- •2. Упражнения
- •3. Содержание отчёта
- •Практическое занятие №7 Работа с текстовыми файлами Цель – знакомство с командами, работающими с текстовыми файлами (awk-интерпретатор скриптовый)
- •1. Краткие теоретические сведения
- •1.1. Язык awk
- •1.2. Регулярные выражения
- •Метасимволы, используемые в регулярных выражениях
- •1.3. Действия
- •1.4. Awk-переменные и выражения
- •1.5. Использование операций
- •1.6. Использование массивов
- •1.7. Селекторы
- •1.8. Использование операторов
- •1.9. Ввод и вывод данных
- •1.10. Встроенные функции
- •2. Упражнения
- •Структура файла query1
- •Структура файла query2
- •3. Содержание отчёта
- •1.2. Граматика языка shell
- •2. Упражнения
- •3. Содержание отчёта
- •Выполнить:
- •2. Упражнения
- •Примечание:
- •3. Содержание отчёта
- •1.1. Компоновка объектных модулей
- •1.2. Отладка
- •2. Упражнения
- •Задание №1
- •Задание №2
- •Задание №3
- •Задание №4
- •Задание №5
- •Задание №6
- •Задание №13
- •Задание №14
- •Задание №15
- •Задание №16
- •Задание №17
- •Практическое занятие №11
- •2. Упражнения
- •3. Содержание отчёта
- •1.2. Создание каталога
- •1.3. Биты режима для прав доступа
- •1.4. Удаление каталога
- •1.5. Создание жесткой связи
- •1.6. Создание символической связи
- •1.7. Чтение символической связи
- •1.8. Переименование файла
- •1.9. Удаление файла
- •1.10. Обработка ошибок
- •2. Упражнения
- •3. Содержание отчёта
- •1.2. Проверка возможностей управления работой и процессами в shell
- •2. Упражнения
- •3. Содержание отчёта
- •1.3. Ошибки, связанные с именами файлов
- •1.4. Доступ к файлу
- •2. Упражнения
- •3. Содержание отчёта
- •Практическое занятие №15 Организация процессов вQnx
- •1. Методические указания по выполнению практической работы
- •1.1. Файл main.O
- •1.2. Файл input.C
- •1.3. Файл output.C
- •1.4. Файл process.C
- •1.5. Используемые функции
- •1.6. Получение информации о процессах
- •2. Упражнения
- •1.2. Клиент
- •1.3. Определение идентификаторов узла, процесса и канала (nd/pid/chid) нужного сервера
- •1.4. Применение обмена сообщениями
- •2. Упражнения
- •3. Содержание отчёта
- •Практическое занятие №17 Организация потоков в qnx
- •1. Краткие теоретические сведения
- •1.1. Запуск потока
- •1.2. Администрирование атрибутов потока
- •Текст программы
- •Результаты
- •1.2. Текст программы
- •1.3. Последовательность действий
- •1.4. Результаты
- •2. Упражнения
- •3. Содержание отчёта
3. Содержание отчёта
Номер, название и цель работы.
Краткое описание средств запуска процессов и механизмов канального взаимодействия.
Демонстрация работы мультипроцессного приложения.
Оформление письменного отчета по результатам выполнения работы.
Практическое занятие №17 Организация потоков в qnx
Цель работы – ознакомиться со способами организации дочерних потоков в QNX.
1. Краткие теоретические сведения
Для того чтобы увидеть, как «выглядит» многопоточная программа, можно запустить из командного интерпретатора команду pidin. Скажем, нашу программу зовут spud. Если мы выполняем pidin один раз до создания проргаммой spud потоков, и еще раз – после того, как spud создала два потока (тогда всего их будет три), то вот как примерно будет выглядеть вывод (укороченный вывод pidin для демонстрации только того, что относится к spud):
# pidin
pid tid name prio STATE Blocked
12301 1 spud 10r READY
# pidin
pid tid name prio STATE Blocked
12301 1 spud 10r READY
12301 2 spud 10r READY
12301 3 spud 10r READY
Вы можете видеть, что процесс spud (идентификатор процесса 12301) имеет три потока (столбец «tid» в таблице). Эти три потока выполняются с приоритетом 10, с диспетчеризацией карусельного (RR) типа (обозначенной как «г» после цифры 10). Все три процесса находятся в состоянии готовности (READY), т. е. готовы использовать процессор, но в настоящее время не выполняются (поскольку в данный момент выполняется другой поток с более высоким приоритетом).
1.1. Запуск потока
Любой поток может создать другой поток в том же самом процессе; на это не налагается никаких ограничений (за исключением объема памяти, конечно!) Наиболее общий путь реализации этого – использование вызова функций pthread_create():
#include <pthread.h>
int pthread_create (pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
Функция pthread_create() имеет четыре аргумента :
thread - указатель на pthread_t, где хранится идентификатор потока;
attr - атрибутная запись;
start_routine - подпрограмма, с которой начинается поток;
arg - параметр, который передается подпрограмме start_routine.
Отметим, что указатель thread и атрибутная запись (attr) — необязательные элементы, вы можете передавать вместо них NULL.
Параметр thread может использоваться для хранения идентификатора вновь создаваемого потока. Если, мы в этом аргументе передадим NULL, обозначив этим, что мы не заботимся о том, какой идентификатор будет иметь вновь создаваемый поток.
Если мы хотим сохранить идентификатор потока то необходимо сделать так:
pthread_t tid;
pthread_create (&tid, ...
printf («Новый поток имеет идентификатор %d\n», tid);
Такое применение совершенно типично, потому что вам часто может потребоваться знать, какой поток выполняет какой участок кода.
1.2. Администрирование атрибутов потока
Перед использованием атрибутной записи для ее инициализации следует вызвать функцию pthread_attr_init():
pthread_attr_t attr;
pthread_attr_init (&attr);
Атрибут потока «flags» (флаги)
Поток может быть создан как «синхронизирующий» («joinable») или как «обособленный» (detached), поток может наследовать атрибуты диспетчеризации от создающего потока или атрибуты диспетчеризации могут задаваться.
Для создания «синхронизирующего» потока (это значит, что с завершением этого потока можно синхронизировать другой поток) используется вызов:
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE); (по умолчанию)
По умолчанию поток создается с атрибутом JOINABLE (присоединенный к родительскому).
Чтобы создать обособленный поток, синхронизация с завершением которого невозможна надо сделать так:
pthread_attr_setdetachstate (fcattr, THREAD_CREATE_DETACHED);
Если поток создан с атрибутом DETACHED, то, с одной стороны, он не сможет возвращать данные, а с другой – не будет уничтожен ядром при завершении его родителя.
Для того, чтобы поток унаследовал атрибуты диспетчеризации от потока, его создающего (то есть имел бы ту же самую дисциплину диспетчеризации и тот же самый приоритет, что и родитель), вам следует сделать так:
pthread_attr_setinheritsched (&attr, PTHREAD_INHERIT_SCHED); (по умолчанию)
Для создания потока, который использует атрибуты диспетчеризации, указанные в непосредственно в атрибутной записи вызов выглядел бы следующим образом:
pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED);
При этом атрибуты предварительно устанавливаются при помощи функций pthread_attr_setschedparam() и pthread_attr_setschedpolicy().
Атрибуты потока - диспетчеризация «scheduling»
Если дисциплина диспетчеризации не наследуется, то есть вы использовали функцию pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED); то вам необходимо определить дисциплину диспетчеризации и приоритет для потока, который вы намерены создать.
int pthread_attr_setschedpolicy ( pthread_attr_t *attr, int policy);
Параметр policy - это либо SCHED_FIFO, либо SCHED_RR, либо SCHED_OTHER, то есть дисциплина диспетчеризации: FIFO, карусельная диспетчеризация, спорадическая диспетчеризация.
param — структура, которая содержит единственный элемент: sched_priority. Этот параметр можно задать путем прямого присвоения ему значения желаемого приоритета.
Теперь рассмотрим ряд примеров. Будем считать, что в обсуждаемой программе подключены нужные заголовочные файлы (<pthread.h> и <sched.h>), а также что поток, который предстоит создать, называется new_thread(), и для него существуют все необходимые прототипы и определения.
Самый обычный способ создания потока — просто оставить везде значения по умолчанию:
pthread_create (NULL, NULL, new_thread, NULL);
В примере мы создали наш новый поток со значениями параметров по умолчанию и передали ему NULL в качестве его единственного параметра (третий NULL в указанном выше вызове pthread_create()).
Вообще говоря, вы можете передавать вашему новому потоку что угодно через параметр arg. Например, число 123:
pthread_create (NULL, NULL, new_thread, (void *) 123);
Более сложный пример — создание «обособленного» (detached) потока с диспетчеризацией карусельного типа (RR) и приоритетом 15:
pthread_attr_t attr;
pthread_attr_init (&attr); // Инициализировать атрибутную запись
// Установить «обособленность»
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
// Отменить наследование по умолчанию (INHERIT_SCHED) pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy (&attr, SCHED_RR);
attr.param.sched_priority = 15;
//И, наконец, создать поток
pthread_create (NULL, &attr, new_thread, NULL);
Самый простой метод синхронизации — это «присоединение» (joining) потоков. Реально это действие означает ожидание завершения.
Присоединение выполняется одним потоком, ждущим завершения другого потока. Ждущий поток вызывает pthreadjoin():
#include <pthread.h>
int
pthread_join (pthread_t thread, void **value_ptr);
Функции pthreadjoin() передается идентификатор потока, к которому вы желаете присоединиться, а также необязательный аргумент value_ptr, который может быть использован для сохранения возвращаемого присоединяемым потоком значения. (Вы можете передать вместо этого параметра NULL).
Где нам брать идентификатор потока?
В функции pthread_create() в качестве первого аргумента указатель на pthread_t. Там и будет сохранен идентификатор вновь созданного потока.