Лабораторная работа

Ввести n слов с консоли. Найти количество слов, содержащих только символы латинского алфавита, а среди них – количество слов с равным числом гласных и согласных букв

Категория:

Лабораторная работа

Дисциплина:

Системное программирование

Город:

Беларусь, Минск

Учебное заведение:

БНТУ, ФИТР

Тег:

#ОперационныеCистемы

Стоимость работы:

8 руб.

Оценка: 10
Объем страниц: 29
Год сдачи: 2020
Дата публикации: 21.10.2020

* Кроме файла с работой, также есть архив с дополнительными файлами.

Описание дополнительных файлов:

Программа А состоит из следующих файлов:
• test.cc – файл, в котором описана главная функция main, которая создаёт дочерний процесс и принимает значения результатов из него;
• Output.h – файл заголовка, в котором описан прототип функции, которая предлагает вывести на консоль или в файл результат операции;
• Output.cc – файл реализации функции, которая предлагает вывести на консоль или в файл результат операции;
• file_write.h – файл заголовка, в котором описан прототип функции, которая записывает результат операции в файл;
• file_write.cc – файл реализации функции, которая записывает результат операции в файл;
• Menu.h – файл заголовка, в котором описан прототип функции, которая предлагает возможность установки приоритета для дочернего процесса, а также при-вязка дочернего процесса к конкретному ядру процессора;
• Menu.cc – файл реализации функции, которая предлагает возможность установки приоритета для дочернего процесса, а также привязка дочернего процесса к конкретному ядру процессора;
• kernel.h – файл заголовка, в котором описан прототип функции, которая привязывает дочерний процесс к конкретному ядру процессора;
• kernel.cc – файл реализации функции, которая привязывает дочерний процесс к конкретному ядру процессора;
• print_prio.h – файл заголовка, в котором описан прототип функции, которая вы-водит информацию о приоритетах и политики планирования;
• print_prio.cc – файл реализации функции, которая выводит информацию о приоритетах и политики планирования;
• main.cc – файл, в котором описана главная функция main и предусмотрено два способа ввода: через аргументы командной строки и стандартного ввода данных во время работы программы.
• Array_Processing.h – файл заголовка, в котором описан прототип функции модифицирующей строку. Вызывает функции проверки: Search_English_Words(), Vowels_Consonants() и подсчитывает количество латинских слов и слов, с равным количеством гласных и согласных букв и передаёт результат родительскому процессу;
• Array_Processing.cc – файл реализации функции модифицирующей строку. Вызывает функции проверки: Search_English_Words(), Vowels_Consonants() и подсчитывает количество латинских слов и слов, с равным количеством гласных и согласных букв и передаёт результат родительскому процессу;
• Search_English_Words.h – файл заголовка, в котором описан прототип функции проверки: содержит ли введённое слово только символы латинского алфавита;
• Search_English_Words.cc – файл реализации функции проверки: содержит ли введённое слово только символы латинского алфавита;
• Vowels_Consonants.h – файл заголовка, в котором описан прототип функции по нахождению слов с равным количеством гласных и согласных букв;
• Vowels_Consonants.cc – файл реализации функции по нахождению слов с равным количеством гласных и согласных букв;

Программа B состоит из следующих файлов:
• fork.c – файл, в котором описана главная функция main, которая читает из стандартного потока ввода данные и вызывает дочерний процесс;
• tolower.с – файл, в котором описана главная функция main, которая преобразует символы и пишет в стандартный поток вывода;
• toupper.c – файл, в котором описана главная функция main, которая преобразует символы и пишет в стандартный поток вывода;


Программа С состоит из следующих файлов:
• 3.c – файл, в котором описана главная функция main, которая выводит список запущенных пользователем процессов, а также процессов, выполняемых другими пользователями и системных процессов (или всех процессов в системе) и др.

Фрагменты для ознакомления

ЛАБОРАТОРНАЯ РАБОТА № 7

Основы многозадачности в Linux. Процессы в Linux

Цель работы:

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

 

Требования:

Разработать модульное консольное приложение на С/С++ согласно варианту задания. Для компиляции, компоновки и выполнения программы использовать утилиту make.

Для каждой бригады необходимо выполнить задание A полностью и по одному варианту задания B на человека (к примеру, если в бригаде 2 человека, то необходимо выполнить 2 задания, если в бригаде 3 человека – 3 задания и т.д.).

 

Задание A

Приложение, разработанное при выполнении лабораторной работы № 2, запустить как дочерний процесс. Родитель должен передавать соответствующие данные для работы дочернего процесса, получать результат выполнения и выводить его в терминал и/или в файл. Предусмотреть возможность установки приоритета для соответствующего запускаемого дочернего процесса, а также привязку его выполнения на конкретном ядре процессора.

 

Индивидуальное задание из лабораторной работы № 2:

Ввести n слов с консоли. Найти количество слов, содержащих только символы латинского алфавита, а среди них – количество слов с равным числом гласных и согласных букв. 

 

Задание B 

1. Написать программу-фильтр, которая читает из стандартного потока ввода и пишет в свой стандартный поток вывода, выполняя при этом полезное преобразование.

2. Необходимо написать программу, которая выводит список выполняемых текущим пользователем процессов, а также процессов, выполняемых другими пользователями и системных процессов (или всех процессов в системе);

 

Ход выполнения лабораторной работы:

Выбрал метод решения индивидуальных заданий и разработал алгоритм.

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

Ознакомился с функциями, которые возвращают pid процесса и pid процесса родителя.

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

Поиск и изучение литературу по привязке процесса к ядру, изменение приоритета процесса и алгоритма планировщика.

В текстовом редакторе gedit набрал исходный код решения задания Aна языке программирования С и сохранил исходник с именем. Программа А состоит из следующих файлов (см. рис. 1):

test.cc – файл, в котором описана главная функция main, которая создаёт дочерний процесс и принимает значения результатов из него;

Output.h  файл заголовка, в котором описан прототип функции, которая предлагает вывести на консоль или в файл результат операции;

Output.cc – файл реализации функции, которая предлагает вывести на консоль или в файл результат операции;

file_write.h файл заголовка, в котором описан прототип функции, которая записывает результат операции в файл;

file_write.cc – файл реализации функции,  которая записывает результат операции в файл;

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

Menu.cc – файл реализации функции, которая предлагает возможность установки приоритета для дочернего процесса, а также привязка дочернего процесса к конкретному ядру процессора;

kernel.h файл заголовка, в котором описан прототип функции, которая привязывает дочерний процесс к конкретному ядру процессора;

kernel.cc – файл реализации функции, которая привязывает дочерний процесс к конкретному ядру процессора;

print_prio.h файл заголовка, в котором описан прототип функции, которая выводит информацию о приоритетах и политики планирования;

print_prio.cc – файл реализации функции, которая выводит информацию о приоритетах и политики планирования;

main.cc – файл, в котором описана главная функция main и предусмотрено два способа ввода: через аргументы командной строки и стандартного ввода данных во время работы программы. 

Array_Processing.h  файл заголовка, в котором описан прототип функции модифицирующей строку. Вызывает функции проверки: Search_English_Words(), Vowels_Consonants() и подсчитывает количество латинских слов и слов, с равным количеством гласных и согласных букв и передаёт результат родительскому процессу;

Array_Processing.cc файл реализации функции модифицирующей строку. Вызывает функции проверки: Search_English_Words(), Vowels_Consonants() и подсчитывает количество латинских слов и слов, с равным количеством гласных и согласных букв и передаёт результат родительскому процессу;

Search_English_Words.h  файл заголовка, в котором описан прототип функции проверки: содержит ли введённое слово только символы латинского алфавита;

Search_English_Words.cc –  файл реализации функции проверки: содержит ли введённое слово только символы латинского алфавита;

Vowels_Consonants.h – файл заголовка, в котором описан прототип функции по нахождению слов с равным количеством гласных и согласных букв;

Vowels_Consonants.cc –  файл реализации функции по нахождению слов с равным количеством гласных и согласных букв;

Создал Makefile (см. Makefile  Приложение А).

Запустил терминал Linux и с помощью команды cd перешёл в папку местонахождения Мейкфайла.

Для компиляции программы использовал автосборку проекта с помощью Makefile(см. рис. 2).

Для тестирования работоспособности запустил программу и ввёл определённые данные (см. рис. 3).

Изучил функции для очистки потока, чтения и изъятия символа.

В текстовом редакторе gedit набрал исходный код решения задания Bна языке программирования С и сохранил исходник с именем. Программа B состоит из следующих файлов (см. рис. 4):

fork.c – файл, в котором описана главная функция main, которая читает из стандартного потока ввода данные и вызывает дочерний процесс;

tolower.с файл, в котором описана главная функция main, которая преобразует символы и пишет в стандартный поток вывода;

toupper.c – файл, в котором описана главная функция main, которая преобразует символы и пишет в стандартный поток вывода ;

Изучил команду ps, которая выдаёт список обо всех процессах;

В текстовом редакторе gedit набрал исходный код решения задания Cна языке программирования С и сохранил исходник с именем. Программа С состоит из следующих файлов:

3.c – файл, в котором описана главная функция main, которая выводит список запущенных пользователем процессов, а также процессов, выполняемых другими пользователями и системных процессов (или всех процессов в системе) и др.;

 

Результаты выполнения лабораторной работы:                                                                         

Рисунок 1 – Содержимое папки OC1 программы лабораторной работы № 7

 

Рисунок 2— Организация автосборки проекта А с помощью Makefile

 

Рисунок 3.1— Запуск программы и привязка к определённому ядру процессора

 

Рисунок 3.2— Установка приоритета и вывод информации о классе планирования

 

Рисунок 3.3— Реализация главной задачи и вывод результата на экран

 

Рисунок 3.4— Запуск программы, передача аргументов командной строки и вывод результат на экран

 

Рисунок 4 – Содержимое папки 2 программы лабораторной работы № 7

Рисунок 5.1 – Запуск программы, установка связи потока ввода с файлом и выполнение преобразований и вывод в поток вывода

 

Рисунок 5.2 – Запуск программы, установка связи потока ввода с файлом и выполнение преобразований и вывод в поток вывода

 

Рисунок 6.1 – Запуск программы

Рисунок 6.2 – Вывод всех процессов

 

Что я освоил в процессе выполнения лабораторной работы:

  1. Именованные и неименованные каналы;
  2. Функцию, которая превращает один процесс в два идентичных, которые называют родитель и потомок;
  3. Функцию, которая принуждает родительский процесс ждать завершения работы процесса потомка;
  4. Функцию, которая прекращает процесс, из которого эта функция была вызвана;
  5. Отображение алгоритма планировщика и управление им;
  6. Изменение приоритета процесса, и привязка его к конкретному ядру процессора;
  7. Работу с потоками: очистка потоков, извлечение символов из стандартных потоков ввода и вывода;
  8. Команда для вывода всех процессов в системе в режиме реального времени;

 

Выводы:

Процесс - это одна выполняемая программа. Она может быть "системной" или "пользовательской" (инициированной пользователем).  Когда ОС UNIX выполняет процесс, этому процессу выдается уникальный идентификационный номер pid.  Команда UNIX ps выдает список все выполняющихся процессов и перечисляет их pid.  C-функция int getpid() возвращает уникальный идентификационный номер процесса (pid), из которого эта функция вызвана. C-функция int getppid() возвращает уникальный идентификационный номер родителя процесса (pid), из которого эта функция вызвана. 

Труба является однонаправленным коммуникационным каналом между двумя процессами и может использоваться для поддержки коммуникаций и контроля информационного потока между двумя процессами. Труба может принимать только определенный объем данных (обычно 4 Кб). Если труба заполнена, процесс останавливается до тех пор, пока хотя бы один байт из этой трубы не будет прочитан и не появится свободное место, чтобы снова заполнить ее данными. С другой стороны, если труба пуста, то читающий процесс останавливается до тех пор, пока пишущий процесс не внесёт данные в эту трубу.  Труба описывается двумя дескрипторами файлов. Первый дескриптор служит для чтения, второй - для записи в трубу: 

int pipe(int fd[2]); 

Здесь fd[0] является дескриптором для чтения, а fd[1] - дескриптором для записи в трубу.

Для передачи данных между неродственными процессами можно использовать механизм именованных каналов (named pipes). Данные передаются по принципу FIFO (First In First Out) (первым записан — первым прочитан), поэтому они называются также FIFO pipes или просто FIFO. Именованные каналы отличаются от неименованных наличием идентификатора канала, который представлен как специальный файл (соответственно имя именованного канала — это имя файла). Файлы именованных каналов создаются функцией mkfifo.

int mkfifo ( const char *pathname , mode_t mode) ;

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

pid_t wait (int *status_location) принуждает родительский процесс ждать завершения работы процесса потомка. wait () возвращает уникальный идентификационный номер процесса-потомка или -1 в случае ошибки.

При вызове fork() порождается новый процесс (процесс-потомок), который почти идентичен порождающему процессу-родителю. Процесс-потомок наследует следующие признаки родителя: 

Сегменты кода, данных и стека программы 

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

Рабочий и корневой каталоги 

Реальный и эффективный номер пользователя и номер группы 

Приоритеты процесса (администратор может изменить их через nice) 

Контрольный терминал 

Маску сигналов 

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

Среду выполнения 

Разделяемые сегменты памяти 

Потомок не получает от родителя следующие признаки: 

Идентификатор процесса (PID, PPID) 

Израсходованное время CPU (оно обнуляется) 

Сигналы процесса-родителя, требующие ответа 

Блокированные файлы (record locking)

Вызов  exec() заменяет пользовательский контекст текущего процесса на содержимое некоторого исполняемого файла и устанавливает начальные значения регистров процессора. Этот вызов требует для своей работы задания имени исполняемого файла, аргументов командной строки и параметров окружающей среды. Для осуществления вызова программист может воспользоваться одной из шести функций: execlp(), execvp(), execl(), execv(), execle(), execve(), отличающихся друг от друга представлением параметров, необходимых для работы системного вызова exec().

Суффиксы l, v, p и e, добавляемые к имени семейства exec обозначают, что данная функция будет работать с некоторыми особенностями: p — определяет, что функция будет искать «дочернюю» программу в директориях. Без суффикса p поиск будет производиться только в рабочем каталоге.

Суффикс l употребляется, когда число пере даваемых аргументов заранее известно. v — показывает, что адресные указатели (arg[0], arg[1],...arg[n]) передаются, как массив указателей. Обычно, суффикс v используется, когда передаётся переменное число аргументов. e — показывает, что «дочернему» процессу может быть передан аргумент envp, который позволяет выбирать среду «дочернего» процесса. Без суффикса e «дочерний» процесс унаследует среду «родительского» процесса.

Функция freopen сначала пытается закрыть любой файл уже связанный с потоком, который указан в параметре filestream. Независимо от того, был поток успешно отсоединён или нет, freopen открывает файл, имя которого передается в первом параметре, fname, то есть связывает файл fname с  только что отсоединенным потоком так же, как и функция fopen, используя режим доступа, указанное в качестве второго параметра, mode.

FILE * freopen( const char * fname, const char * modeopen, FILE * filestream );

Функция putchar записывает символ в текущей позиции в стандартный поток вывода (stdout) и перемещает внутренний указатель положения файла в следующую позицию.

Получить символ из стандартного потока ввода — функция getchar возвращает следующий символ из стандартного потока ввода (stdin).

Системный вызов nice (установить процессу приоритет) имеет следующий формат: nice (incr). Системный вызов nice устанавливается текущему процессу новый приоритет, равный текущему приоритету плюс значение аргумента incr. Значение аргумента incr должно лежать в определенном диапазоне, конкретные границы которого зависят от версии ОС UNIX. UNIX 7: Диапазон значений incr лежит в пределах от -20 до 20. Отрицательное приращение может задавать только привилегированный пользователь. UNIX System V: Диапазон значений incr лежит в пределах от 0 до 39. Приращения, выходящие за границы этого диапазона, уменьшаются до граничных значений. Чем выше значение аргумента incr, тем ниже устанавливаемый приоритет.

 

Другие функции:

Для выполнения системных команд используют int system (const char * string), которая выполняет, указанные в string, системные команды.

Для установки или получения политики диспетчеризации процесса используют:

int sched_setscheduler(pid_t pid, int policy, const struct sched_param *p);
int sched_getscheduler(pid_t pid);

Для установки или получения привязки процесса к конкретному процессору многопроцессорной системы.

int sched_setaffinity(pid_t pid, unsigned int len, unsigned long *mask);

int sched_getaffinity(pid_t pid, unsigned int len, unsigned long *mask);

388