Федеральное агентство связи ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ
ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ «САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ТЕЛЕКОММУНИКАЦИЙ ИМ. ПРОФ. М. А. БОНЧ-БРУЕВИЧА» (СПбГУТ)
Факультет инфокоммуникационных сетей и систем Кафедра программной инженерии и вычислительной техники
ЛАБОРАТОРНАЯ РАБОТА №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