Материал: ОСиС. Лабораторная работа 5

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

Федеральное агентство связи ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ

ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ «САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ТЕЛЕКОММУНИКАЦИЙ ИМ. ПРОФ. М. А. БОНЧ-БРУЕВИЧА» (СПбГУТ)

Факультет инфокоммуникационных сетей и систем Кафедра программной инженерии и вычислительной техники

ЛАБОРАТОРНАЯ РАБОТА №5 по дисциплине «Операционные системы и сети»

на тему «Разработка многопоточной программы под Linux»

Выполнил: студент 3-го курса дневного отделения группы ИКПИ-85

Коваленко Леонид Александрович Преподаватель:

доцент кафедры ПИиВТ Дагаев Александр Владимирович

Санкт-Петербург 2020

Цель работы Разработать многопоточную программу с применением механизмов

синхронизации потоков под Linux.

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

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

2.Написать программу на C++ для решения задачи об обедающих философах и продемонстрировать ее работу.

Ход работы

Работа выполняется в операционной системе Linux Debian.

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

Таблица 1 — Файл script.sh

#!/bin/bash while [ true ] do

echo "-== Меню ==-"

echo "1. Список всех потоков." echo "2. Поиск по всем процессам." echo "3. Системный монитор."

echo "4. XKILL." read n

if [[ $n = "1"* ]] then

ps -A

elif [[ $n = "2"* ]] then

read -p "Введите вхождение: " substr

read -p "Остановить все найденные процессы? (y/n): " is_all if [ $is_all = "y" ] || [ $is_all = "Y" ]

then

killall $substr

fi

elif [[ $n = "3"* ]] then

top -H

elif [[ $n = "4"* ]] then

xkill

elif [[ $n = "exit"* ]] then

exit

else

echo "Ошибка ввода"

fi

done

Запустим скрипт на выполнение и проверим его работу (рис. 1, 2, 3, 4). 2

Рисунок 1 — Проверка первого пункта меню

Рисунок 2 — Проверка второго пункта меню

Рисунок 3 — Проверка третьего пункта меню

Рисунок 4 — Проверка четвертого пункта меню 3

Для того, чтобы выйти, достаточно ввести exit (и нажать Enter) или нажать Ctrl+C.

Напишем программу на C++ для решения задачи об обедающих философах (табл. 2).

Таблица 2 — Файл main.cpp

#include <iostream> #include <mutex> #include <thread>

// Класс "Вилка" class Fork {

public:

// Конструктор

Fork(std::string name) : mName(name) {}

//Ожидание и взятие вилки void take() { mMutex.lock(); }

//Попытка взятия вилки

bool tryTake() { return mMutex.try_lock(); }

// Освобождение вилки

void put() { mMutex.unlock(); }

// Получить условное название вилки std::string getName() const { return mName; }

private:

//Мьютекс std::mutex mMutex;

//Условное название вилки std::string mName;

};

// Класс "Философ" class Philosopher {

public:

// Конструктор

Philosopher(const std::string &name, Fork &leftFork, Fork &rightFork)

:mName(name), mLeftFork(&leftFork), mRightFork(&rightFork) {}

//Функция потока

void run(int iteration) {

std::string in = mName + " философ начал кушать\n"; std::string out = mName + " философ приостановил трапезу\n"; while (iteration > 0) {

//Думаем

wait();

//Берем две вилки или блокируемся mLeftFork->take();

if (!mRightFork->tryTake()) { mLeftFork->put(); continue;

}

//Обедаем

std::cout << in; std::cout.flush(); wait();

std::cout << out;

4

std::cout.flush();

// Кладем на стол обе вилки mLeftFork->put();

wait(); mRightFork->put(); wait(); --iteration;

}

}

private:

//Ожидание milliseconds миллисекунд void wait(int milliseconds = 100) const {

std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));

}

//Имя философа

std::string mName;

// Левая и правая вилки

Fork *mLeftFork, *mRightFork;

};

int main() {

using namespace std;

std::cout << "[Старт] Начался обед двух философов" << std::endl;

{

Fork f1("#1"), f2("#2");

Philosopher p1("#1", f1, f2), p2("#2", f2, f1);

thread thread1(&Philosopher::run, &p1, 2); thread thread2(&Philosopher::run, &p2, 2);

thread1.join();

thread2.join();

}

std::cout << "[Финиш] Два философа пообедали" << std::endl; std::cout << "[Старт] Начался обед пяти философов" << std::endl;

{

Fork f1("#1"), f2("#2"), f3("#3"), f4("#4"), f5("#5"); Philosopher p1("#1", f1, f2), p2("#2", f2, f3), p3("#3", f3, f4),

p4("#4", f4, f5), p5("#5", f5, f1);

thread thread1(&Philosopher::run, &p1, 2); thread thread2(&Philosopher::run, &p2, 2); thread thread3(&Philosopher::run, &p3, 2); thread thread4(&Philosopher::run, &p4, 2); thread thread5(&Philosopher::run, &p5, 2);

thread1.join();

thread2.join();

thread3.join();

thread4.join();

thread5.join();

}

std::cout << "[Финиш] Пять философов пообедали" << std::endl; return 0;

}

5